[prev in list] [next in list] [prev in thread] [next in thread] 

List:       pykde
Subject:    [PyKDE] Emitting Python Objects in PyQt4
From:       Phil Thompson <phil () riverbankcomputing ! co ! uk>
Date:       2006-02-19 12:12:24
Message-ID: 200602191212.24431.phil () riverbankcomputing ! co ! uk
[Download RAW message or body]

Current snapshots now support emitting arbitrary Python objects, ie. objects 
that have no corresponding C++ type.

In PyQt3 a connection between a Python signal and a Python slot (ie. a 
callable) is implemented directly and doesn't involve Qt's signal/slot 
mechanism at all. Therefore no conversion of the signal arguments is required 
and the argument list in the signature passed to PYSIGNAL() is optional and 
ignored. (I tend to specify it in my own code just as additional 
documentation.) To emit something like a Python list is done simply as...

    self.emit(PYSIGNAL("signalIntList(int, List)"), (1, []))

...or...

    self.emit(PYSIGNAL("signalIntList"), (1, []))

In PyQt4 all connections are implemented using Qt's signal/slot mechanism. 
This is to support asynchronous and inter-thread connections for all 
connection types. A consequence is that all Python arguments have to be 
converted to C++ types - including those that SIP doesn't know how to 
convert.

To solve this SIP now recognises "PyObject *" as a special argument type. 
(This is the C type the Python API uses to hold any Python object.) It 
handles it by passing the argument unconverted. The above example would then 
be written in PyQt4 as follows...

    self.emit(SIGNAL("signalIntList(int, PyObject *)"), 1, [])

Note that the int argument is converted to a C++ int for the connection and 
back to a Python object when the Python slot is called. The convertion can be 
prevented by telling SIP to treat it as an arbitrary object just like the 
list, so that the following is slightly quicker...

    self.emit(SIGNAL("signalIntList(PyObject *, PyObject *)"), 1, [])

This all works and is consistent - but rather clumsy. Therefore you can also 
specify a "short-circuit" signal by omitting the argument list and () from 
the signature. This is the equivalent of specifying "PyObject *" for every 
argument. This then gives a usage very similar to that of PyQt3...

    self.emit(SIGNAL("signalIntList"), 1, [])

...which is what you'll end up doing 99% of the time.

Note that you can only connect short-circuit signals to other short-circuit 
signals or Python slots - not to Qt signals or slots.

Disconnecting isn't properly handled yet - I'll add that in the next day or 
so.

Phil

_______________________________________________
PyKDE mailing list    PyKDE@mats.imk.fraunhofer.de
http://mats.imk.fraunhofer.de/mailman/listinfo/pykde
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic