JUN
8
2006

Qyoto custom slots and signals are working

The Qyoto C#/mono bindings are getting quite close to being useful. I first started on them about two and a half years ago, and so it's taken forever to get going. But we've just passed a key milestone, which is getting the cannon game tutorial t7 working. That means you can now define custom slots and signals in C#, and connect them to C++ or C# slots and signals.

A couple of months ago Simon Edwards ported the Qt3 bindings to Qt4, and after that it seemed a bit late to bother with Qt3. I got the Qt4 code generation working, and then Arno Rehn added the code to get the custom signals declarations, and transform them into structures suitable for lookup at runtime. More recently Paolo Capriotti has being doing great stuff getting the runtime creation of QMetaObjects working and implementing custom slots. I've just commited the QtDBus classes, and I'm hoping it will be as easy to get that working as it was for QtRuby.

Here is what tutorial t7 looks like. The LCDRange class has both a custom slot and custom signal, and the signal is connected to a C++ signal emitted by QSlider. The classes are now all in a 'Qyoto' namespace, and so the code starts with a 'using Qyoto;' declaration.


using Qyoto;

class LCDRange : QWidget {
private QSlider slider;

public LCDRange() : this((QWidget) null) {}

public LCDRange(QWidget parent) : base(parent) {
QLCDNumber lcd = new QLCDNumber(2);
lcd.SetSegmentStyle(QLCDNumber.SegmentStyle.Filled);

slider = new QSlider(Qt.Orientation.Horizontal);
slider.SetRange(0,99);
slider.SetValue(0);

Connect(slider, SIGNAL("valueChanged(int)"),
lcd, SLOT("display(int)"));
Connect(slider, SIGNAL("valueChanged(int)"),
this, SIGNAL("valueChanged(int)"));

QVBoxLayout layout = new QVBoxLayout();
layout.AddWidget(lcd);
layout.AddWidget(slider);

SetLayout(layout);

}
public int Value() {
return slider.Value();
}

[Q_SLOT("setValue(int)")]
public void SetValue(int value) {
slider.SetValue(value);
}

protected new ILCDRangeSignals Emit() {
return (ILCDRangeSignals) Q_EMIT;
}
}

public interface ILCDRangeSignals : IQWidgetSignals {
[Q_SIGNAL("valueChanged(int)")]
void ValueChanged(int newValue);
}

class MyWidget : QWidget {
public MyWidget(QWidget parent) : base(parent) {
QPushButton quit = new QPushButton("Quit");
Connect(quit, SIGNAL("clicked()"), qApp, SLOT("quit()"));

QGridLayout grid = new QGridLayout();
LCDRange previousRange = null;

for (int row = 0; row < 3; ++row) {
for (int column = 0; column < 3; ++column) {
LCDRange lcdRange = new LCDRange();
grid.AddWidget(lcdRange, row, column);
if (previousRange != null)
Connect(lcdRange, SIGNAL("valueChanged(int)"),
previousRange, SLOT("setValue(int)"));
previousRange = lcdRange;
}
}

QVBoxLayout layout = new QVBoxLayout();
layout.AddWidget(quit);
layout.AddLayout(grid);
SetLayout(layout);
}
protected new IMyWidgetSignals Emit() {
return (IMyWidgetSignals) Q_EMIT;
}
public static void Main(string[] args) {
new QApplication(args);
MyWidget main = new MyWidget((QWidget)null);
main.Show();
QApplication.Exec();
}
}

public interface IMyWidgetSignals : IQWidgetSignals {
}

A slot is defined with a Q_SLOT() attribute like this, with the C++ type signature as a string argument (we hope to make the optional in the future):


[Q_SLOT("setValue(int)")]
public void SetValue(int value) {
slider.SetValue(value);
}

Signals are defined in a similar manner. You need to add an interface to your class, and add Q_SIGNAL attributes to the method signature declarations. Then add an Emit() method which returns the type of the signals interface like this:

...
protected new ILCDRangeSignals Emit() {
return (ILCDRangeSignals) Q_EMIT;
}
}

public interface ILCDRangeSignals : IQWidgetSignals {
[Q_SIGNAL("valueChanged(int)")]
void ValueChanged(int newValue);
}

Well that's all for now, the next stop is D-BUS..

Comments

Very excellent work; this is exciting news. I hope that this serves to further unite GNOME and KDE by opening up the Mono project to everyone.

Tell me, will theere be any conflict in the difference between Qt's GPL license and Mono's LGPL?


By jclinton at Thu, 06/08/2006 - 20:29

"Tell me, will theere be any conflict in the difference between Qt's GPL license and Mono's LGPL?"

There is no conflict at all if you are writing GPL code. We'll only need to bother about a dual licensed version of Qyoto/Kimono if and when someone wants to write a commercial Qt or KDE app in conjunction with Trolltech's commercial version of Qt.


By Richard Dale at Fri, 06/09/2006 - 08:32

I think (not know) that it works like this:
If you write a FOSS app, you don't have to worry. FOSS is GPL, LGPL, BSD, ... This is coverd be the QPL.
But if you want to write al closed source app, you have to pay trolltech.


By Mathias Panzenböck at Fri, 06/09/2006 - 12:00

I can't wait to make programs for my favorite desktop (kde, of course) using my favorite programming language! (:

Thanks so much for your work on this!


By eto at Fri, 06/09/2006 - 01:46