[Kde-bindings] Hacking moc-generated code
Eric Jardim
ericjardim at gmail.com
Fri Sep 9 17:49:25 UTC 2005
2005/9/9, Richard Dale <Richard_Dale at tipitina.demon.co.uk>:
>
> You need some syntax to emit a signal:
> emit foobar("hello", 5)
Ok. I was thinking in nothing special:
>>> button.clicked()
or
>>> button.signal_clicked()
But we can do something like:
>>> button.emit('clicked()', (,) )
Or
>>> button.emit('clicked(bool)', (True,) )
So emit() would be a method which doesn't actually do anything, then
> foobar()
> might actually map onto a common method for all signals. You then look at
> the
> current stackframe to find the name of the actual ruby method, then look
> up
> it's id number via the QMetaObject.
Hmm, don't like this part. I think this is not safe, I say, we can have
functions pointing to functions (adapters) and it could mess up. Well, I
just think "button.emit" is more simple.
Yes, it's better to have exactly the same syntax for using both python and
> C++
> signals.
It is not just about sintax. PYSIGNALs don't exist in C++ world. This means
you can't embedded it back in C++. In python-qt4 it is already possible,
with no headaches.
Oops, typo make that just 1000 classes.
Sure, but is still a lot o classes. I am thinking about it. But this sounds
to me we must work on a parser, or to tweak a existing parser, to be able to
read the QObjects and understand those macros like Q_PROPERTY, Q_INTERFACE,
Q_INFO.
I mean, in Python things are a little different:
C++:
button->setVisible(true);
std::cout<< button->isVisible() << std::endl;
Python:
>>> button.visible = True
>>> print button.visible
True
Right now, it is only possible because I say to Boost.Python that
"setVisible" and "isVisible" are setter and getter of a "visible" a
property. "Dumb" scripts will never discover it. That's what I say about
being more Pythonic. Well part of the hole story.
That sounds interesting. I'm pretty sure your shouldn't have to intervene to
> make the binding more pythonic
Not just more Pythonic, but more interesting. For example, there is no point
in wrapping the QString class. Python have a "unicode" and "str" class that
work pretty well. Instead of wrapping everything, we write custom converters
that do it transparently:
In old SIP/PyQt:
>>> button = QPushButton(u'Ok', None) # entered a unicode
>>> button.text() # this is a QString, no unicode.
<__main__.qt.QString object at 0xf7f7b630>
In new python-qt4:
>>> button = QPushButton(u'Ok', None)
>>> button.text # a propery, no need to ()
u'Eric' # a real genuine Python unicode object, ready for i18n
Yes, it sounds worth experimenting with.
Yes, but I think we (binders) must work together in a single parse of a
QObject child class header. That would be good for everyone. Maybe the Smoke
project
Smoke is a language independent auto generated library used by the QtRuby
> and
> PerlQt bindings at the moment.
Sounds tasty. Where can I find Smoke for Qt4?
It could be used by java, C# and possibly
> python too. At the moment its main problem is that it's too monolithic,
> and
> everything is all in one big library.
Java and C# are not "scripting" languages. I see no point porting Qt to
those (no offenses). Well, maybe the guys who write the bindings have some
good points, but I just can't see it. Well, if I want static typing I can
continue with good old C++.
I think new Qt4/Smoke will be very interesting. Maybe the code I wrote for
python-qt4 help in something.
It stands for 'Scripting Meta Object
> Kompiler Engine', and is a sort of 'moc on steroids' - it adds an
> introspection layer for the complete api, and a language independent way
> of
> invoking methods dynamically, or virtual methods callbacks.
Nice.
Yes, that's the idea. Otherwise, you need a large library for each language,
> instead of a single wrapper library like Smoke, with a smaller 'adaptor'
> layer for each language.
Hmm, should think more about it. Need to learn more.
A future version of Smoke could use the Qt4 moc
> format, but include ordinary methods as well as signals and slots, along
> with
> a way of adding virtual method callbacks so you can override them in the
> scripting language.
>
That's easy to do with Boost.Python. The problem is find a way of doing it
for all "script" languages.
I just not agree with that part of "turn all ordinary method signals and
slots". If you think better, it will "polute" the interface of the object.
Beside this, signals and slots can be overloaded, so if you want to use it
with embedded C++ or with other binding, you should do combinatorial job
with the args!
I mean "clicked(bool)" and "clicked()" stantds for the same slot. But this
is just a single C++ method. Now imagine how do you expose
"my_custom_method(self, begin, end, *args, **kw)"? There is no type
information here.
My current idea (I may change it) is:
- If we want to expose a signal (so even QtDesigner can read it), we must
say it, and which types. Ex:
class MyWidget(QObject):
@signal('int, int') # this is a Python decorator. You can do it the old way,
too.
def textChanged(begin, end):
...
# valid for the class
- If we want to expose a slot (same as above):
@slot('QString')
def setHeader(text):
...
# valid for the class
- If we want to connect any kind of signal to a QObject method, we promote
that method to a slot, with the signature you used to connect it:
>>> sender_qobject.connect('clicked(bool)', reciever_qobject.method)
# now reciever_qobject's MetaObject register a new slot signed as
'method(bool)',
# incremental use of the thing (not poluted)
# if the (promoted) slot is connect again with the same signature, it is
ignored.
# if a new one signature is used register the new one (eg. 'method()')
# this is valid for the instance.
- If we want to connect any kind of signal to a function, ordinary method,
or lambda expression, python-qt4 create s a dummy fake QObject
(transparently) that proxies the signal for you:
>>> sender.connect('clicked()', reciever.method)
>>> sender.connect('clicked()', a_function)
>>> sender.connect('clicked()', lambda: QApplication.quit() )
# inside python-qt4 (transparent)
class FakeSlot(QObject):
def __init__(self, destiny):
self.destiny = destiny # python callable
def callback(self, *args, **kw):
self.destiny(*args, **kw) # redirect the call
>>> fakeslot = FakeSlot(my_callable)
>>> sender.connect('clicked(bool)', fakeslot.callback)
Nice, eh?
[Eric Jardim]
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.kde.org/pipermail/kde-bindings/attachments/20050909/e17161ef/attachment.html>
More information about the Kde-bindings
mailing list