Development/Tutorials/Kross/Connecting Signals and slots in Kross: Difference between revisions
Some cleanup and a note about emitting object signals from scripts. |
|||
Line 78: | Line 78: | ||
action->addObject(cmbInterpreters, "MyInterpreter"); | action->addObject(cmbInterpreters, "MyInterpreter"); | ||
action->addObject(lblMessage, "MyLabel"); | action->addObject(lblMessage, "MyLabel"); | ||
} | } | ||
Line 123: | Line 121: | ||
=== krossSigsSlots.js === | === krossSigsSlots.js === | ||
This script does the same | This script does the same as the script above but using the JavaScript scripting language. | ||
<code javascript> | <code javascript> | ||
Line 133: | Line 131: | ||
</code> | </code> | ||
{{TODO|Write similar for other interpreters}} | |||
== Autoconnecting Signals and Slots == | == Autoconnecting Signals and Slots == | ||
Line 166: | Line 166: | ||
{ | { | ||
text = text.replace(/\b([aeiou][a-z]*)\b/gi, "$1way"); // Rule 2 | text = text.replace(/\b([aeiou][a-z]*)\b/gi, "$1way"); // Rule 2 | ||
pigLatin = text.replace(/\b([ | pigLatin = text.replace(/\b([bcdfghjklmnpqrstvwxyz]+)([a-z]*)\b/gi, "$2$1ay"); // Rule 1 | ||
MyLabel.text = pigLatin; | MyLabel.text = pigLatin; | ||
Line 172: | Line 172: | ||
} | } | ||
</code> | </code> | ||
{{TODO|Write similar for other interpreters}} | |||
[[Image:Krosssigsandslots1.png]] | |||
== Emitting signals from within scripts == | |||
So far this tutorial has described connecting signals in c++ objects with slots in scripts. The objects published to kross scripts also make their signals available to the scripts. The signals can then be emitted by calling them. This is equivalent to calling: | |||
<code cpp> | |||
emit signalName(); | |||
</code> | |||
in c++ code. To illustrate this, change the python script to emit the setEnabled(bool) signal of the QCombobox: | |||
<code python> | |||
#!/usr/bin/env kross | |||
import MyLabel | |||
import MyInterpreter | |||
def textChanged(s): | |||
if s == "off": | |||
MyInterpreter.setEnabled(False) | |||
elif s == "on": | |||
MyInterpreter.setEnabled(True) | |||
s = MyInputString.text[::-1] | |||
MyLabel.text = s | |||
</code> | |||
If 'off' is written in the text field, the setEnabled signal is emitted and the combobox is greyed out. It is not re-enabled again until 'on' is written in the text field. | |||
This is a simple demonstration of signal-slot relationships using kross. More complex interfaces may be written to complete a plugin architecture. |
Revision as of 00:49, 7 November 2007
Tutorial Series | Kross tutorials |
Previous | Kross Hello World |
What's Next | Scripts as plugins |
Further Reading | n/a |
Under Construction |
---|
This page is under construction. This page is actively being developed and updated with new information, and may be incomplete. You can help by editing this page |
This tutorial shows how to use a system of signals and slots to provide a scripting interface for a KDE application. It builds upon the Kross Hello World tutorial and again follows a 'Hello World' type format.
Update source files
mainwindow.h
Edit mainwindow.h to handle the changes to mainwindow.cpp. Note that the change is the addition of a private Kross::Action .
- ifndef MAINWINDOW_H
- define MAINWINDOW_H
- include <QComboBox>
- include <QLabel>
- include <QLineEdit>
- include <kross/core/action.h>
class MainWindow : public QWidget
{
Q_OBJECT
public:
MainWindow(QWidget *parent=0);
private Q_SLOTS:
void interpreterActivated(const QString &);
private:
QLineEdit* txtInputString;
QLabel* lblMessage;
QComboBox* cmbInterpreters;
Kross::Action* action;
};
- endif
mainwindow.cpp
Using the same CmakeLists.txt and main.cpp from the previous tutorial, edit the mainwindow.cpp as follows:
- include "mainwindow.h"
- include <QVBoxLayout>
- include <QDebug>
- include <kross/core/manager.h>
- include <kross/core/action.h>
MainWindow::MainWindow(QWidget *parent) : QWidget(parent)
{
txtInputString = new QLineEdit();
lblMessage = new QLabel("Hello");
cmbInterpreters = new QComboBox ();
cmbInterpreters->addItem("Choose Interpreter", "");
foreach(QString s, Kross::Manager::self().interpreters())
cmbInterpreters->addItem(s);
connect(cmbInterpreters, SIGNAL(activated(const QString &)),
SLOT(interpreterActivated(const QString &)));
QVBoxLayout *vLayout = new QVBoxLayout;
vLayout->addWidget(cmbInterpreters);
vLayout->addWidget(txtInputString);
vLayout->addWidget(lblMessage);
setLayout(vLayout);
action = new Kross::Action(this, "MyScript");
action->addObject(txtInputString, "MyInputString");
action->addObject(cmbInterpreters, "MyInterpreter");
action->addObject(lblMessage, "MyLabel");
}
void MainWindow::interpreterActivated(const QString &strSelectedInterpreter)
{
if(strSelectedInterpreter.isEmpty()) {
lblMessage->setText("-");
return;
}
QString filename;
if(strSelectedInterpreter == "python")
filename = "krossSigsSlots.py";
else if(strSelectedInterpreter == "javascript")
filename = "krossSigsSlots.js";
else
return;
action->setFile(filename);
action->trigger();
}
The changes are addition of a text entry field and the reorganisation of logic handling the Kross::Action. Note also that there is no code in mainwindow.cpp to set the label, as there was in the previous tutorial. Instead, Objects are simply made available to the scripting interface through the action->addObject calls, without any knowledge of what the script will use them for. This removes the need to know at the time of writing the application what function the scripts will perform, and is therefore suited to a plugin interface.
krossSigsSlots.py
This script catches the textChanged SIGNAL of the QLineEdit, and connects it to a simple python function to reverse the string in the QLineEdit and display it in the QLabel.
- !/usr/bin/env kross
import MyLabel
import MyInterpreter
import MyInputString
def reverseString(s):
s = s[::-1]
MyLabel.text = s
MyInputString.connect("textChanged(const QString &)", reverseString)
krossSigsSlots.js
This script does the same as the script above but using the JavaScript scripting language.
function reverseString(s){
MyLabel.text = s.split("").reverse().join("");
}
connect(MyInputString, "textChanged(const QString &)", this, "reverseString(const QString &)");
TODO |
---|
Write similar for other interpreters |
Autoconnecting Signals and Slots
It is possible to connect signals from your Object to slots in your script file automatically. Edit the mainwindow.cpp file to add another argument to the addObject function:
action->addObject(txtInputString, "MyInputString",
Kross::ChildrenInterface::AutoConnectSignals);
action->addObject(cmbInterpreters, "MyInterpreter");
action->addObject(lblMessage, "MyLabel");
The Kross::ChildrenInterface::AutoConnectSignals argument causes signals of the object to be automatically connected with scripting functions of the same name. Therefore, the scripts can again be simplified:
Simplified scripts
The python function reverses the string:
- !/usr/bin/env kross
import MyLabel
def textChanged(s):
s = s[::-1]
MyLabel.text = s
The javascript function converts the string to pig latin:
function textChanged(text)
{
text = text.replace(/\b([aeiou][a-z]*)\b/gi, "$1way"); // Rule 2
pigLatin = text.replace(/\b([bcdfghjklmnpqrstvwxyz]+)([a-z]*)\b/gi, "$2$1ay"); // Rule 1
MyLabel.text = pigLatin;
}
TODO |
---|
Write similar for other interpreters |
Emitting signals from within scripts
So far this tutorial has described connecting signals in c++ objects with slots in scripts. The objects published to kross scripts also make their signals available to the scripts. The signals can then be emitted by calling them. This is equivalent to calling:
emit signalName();
in c++ code. To illustrate this, change the python script to emit the setEnabled(bool) signal of the QCombobox:
- !/usr/bin/env kross
import MyLabel
import MyInterpreter
def textChanged(s):
if s == "off":
MyInterpreter.setEnabled(False)
elif s == "on":
MyInterpreter.setEnabled(True)
s = MyInputString.text[::-1]
MyLabel.text = s
If 'off' is written in the text field, the setEnabled signal is emitted and the combobox is greyed out. It is not re-enabled again until 'on' is written in the text field.
This is a simple demonstration of signal-slot relationships using kross. More complex interfaces may be written to complete a plugin architecture.