[PyKDE] Sugestions for PyQt4

David Boddie david at boddie.org.uk
Mon Mar 20 18:18:32 GMT 2006


On Mon, 20 Mar 2006 10:26:27, Eric Jardim wrote: 
 
>- "Pythonic" Qt properties: instead of using things like: 
>"isEnabled()" and "setEnabled()", properties could be acessed 
>like python real properties, I mean, just "enabled". The functions 
>could still be mapped anyway. 
 
This could be added or enabled in an additional wrapper. Maybe even 
one that is distributed in the PyQt4 package. 
 
>I don't know how SIP works (automatically or handmade), and it 
>will give a lot of work to acomplish this "by hand". I've have 
>made some progress with a tool called pygccxml, that can parse C++ 
>code and find Qt properties and other Qt special macros (with some 
>tricks). 
 
As I understand it, the SIP binding definitions are auto-generated 
by another tool that does this sort of thing. Adding support for 
Qt properties in "standard" Qt widgets could be done in Python, and 
could either be implemented using Python's descriptors (properties) 
 
  http://docs.python.org/ref/descriptors.html 
  http://docs.python.org/api/descriptor-objects.html 
 
or with __getattr__ and __setattr__. 
 
>- C++ embedding: it may be useful for some users to embed Python 
>plugins in an C++ application. This could be a "magic gate" for 
>some "static" applications that want to be more flexible. There 
>should be some limitations to this technique, but if we can easily 
>use Python obejcts in C++ applications. Remember that we have to 
>connect C++ signals/slots to Python signal/slots (see dynamic 
>metaobjects below). 
 
In many ways, it's straightforward to achieve this by implementing 
a suitable plugin class in C++ then wrapping it for Python with 
SIP. The code generated by SIP then acts as the "magic gate". 
 
>- QtDesigner integration: I think this is a dream of everyone to 
>make your custom widgets available in QtDesigner. With the new Qt4 
>API, it is very easy to write plugins for QtDesigner. 
 
Yes, I'm really interested in this. 
 
>The problem of the QtDesigner approach is that you have to create 
>a share object (plugin library) for each component you may add to 
>the Widget Box (palette). 
 
This can be a good thing in certain situations. 
 
>I thought of a single approach of creating a generic QPythonWidget 
>(a proxy) that internally calls your custom real Python extension. 
 
I can't remember if you managed that with your early prototypes 
for python-qt. The main problem is that the widgets you return to 
Designer have to have the correct meta-information in order for 
them to work properly. It's quite easy to give them the correct 
class name and super class information; the rest is more difficult. 
 
>Plus, we must adapt the QtUiTools::QUiLoader 
>(http://doc.trolltech.com/4.1/quiloader.html) and pyuic4 to load 
>the Python widget correctly. A scratch of this can be found 
>here: 
>http://svn.berlios.de/viewcvs/python-qt4/trunk/PythonQt/ 
 
I haven't looked at this. 
 
>By the way, to be fully useful, our Python widgets should expose 
>their SIGNALs, SLOTs and properties to QtDesigner (and native C++ 
>classes if embedded), and this means a new way of facing 
>metaobjects (see below). 
 
It basically means having support for custom Qt properties, signals 
and slots, so that C++ code can introspect them just like it would 
any other QObject subclass. 
 
[...] 
 
>When you create a new class, derived from QObject (or any other 
>like QWidget and so on), moc (meta object compiler) creates a 
>"static" metaobject, describing the class. I mean static in two 
>meanings: it is static (is the same) for every object the class, 
>and do not change with time (like const). 
>This is Ok for C++ extensions, but Python widgets may change 
>durring the execution of the program. We can add new signals, 
>slots or properties class-wide or object-wide. This makes the 
>complexity grows a little bit. 
 
What's more, you can't just create these objects at the level of 
the bindings because subclasses of Python-implemented widgets 
also need to store their own meta-data somewhere. 
 
>My progress over this is here: 
>http://svn.berlios.de/viewcvs/python-qt4/trunk/PythonQt/QtWrapper.h?view=markup 
 
I need to look at this again. 
 
>With this feature, we can use Python signals inside QtDesigner, 
>inside a C++ embedded python application and we can treat all of 
>them the same way (goodbye PYSIGNAL). The way things are today, 
>there is no way declare a Python signal. You just know it exist 
>when you emit it. OTOH, any method in your class can be a slot. 
>This is fine, but how do you want to expose your class to someone? 
>How do you tell that just some of your methods are really meant to 
>be slots? 
 
I think there was a decorator-inspired solution to this problem 
that 
is equivalent to your suggestion: 
 
>- The new Signal, Slot, Property idom: 
>With all this changes, it should be nice to define the a way to 
>declare our QObject classes extensions. My sugestion is the 
simples 
>as possible: 
 
[...] 
 
>    # how to define a slot 
>    def aSlot(sender, text): 
>        ... 
>    aSlot = QSLOT(aSlot, 'QObject, str') 
> 
>    # how to define a signal 
>    def aSignal(message): 
>        ... 
>    aSignal = QSIGNAL(aSlot, 'str') 
 
I also chose to implement properties in a similar way to you: 
 
>    # how to define a property 
>    def pSet(value): 
>        ... 
>    def pGet(): 
>        ... 
>    p = QPROPERTY(pGet, PSet, ...)  #look: p is a Qt and Python 
>    property! 
 
The only problem here is that Qt and Python have slightly 
different ideas about the other purpose of the property. 
Qt supports properties that can be reset; Python's can be 
deleted. 
 
>In Python 2.4 we can also have sintax sugar: 
>class MyWidget(QWidget): 
>    @QSLOT('QObject, str') 
>     def aSlot(sender, text): 
>        ... 
> 
>     @QSIGNAL('str') 
>    def aSignal(message): 
>        ... 
 
Yes, this looks familiar. :-) 
 
>Sweet, hu? So you got the idea.  But you may also have noticed 
>that I declared the types of the params. Some people may not 
>like this. But think that, in some cases, there is no way of 
>guessing what kind of slot you are talking about, unless you 
>specify the types (remember Qt have some slots with same name, 
>but different types). It will help with QtDesigner integration. 
 
Designer integration is the main purpose, as far as I'm concerned. 
You absolutely need type information for that. 
 
For properties, things are a little simpler. You could 
let developers specify Python types for those because you are 
dealing with value types. 
 
[Smart connections] 
 
>- How to deal with Qt Intefaces? 
>Not thought about this yet. 
 
I decided to write a C++ plugin class that implemented 
QDesignerCustomWidgetInterface using Qt's macros. I think that 
this is the place to mix C++ and Python because it's designed to 
be instantiated only once, it's simple to construct in a loader 
library, and it lets us write the widget in pure Python. 
 
Ideally, I'd write the plugin itself (apart from the loader 
library) in Python, but I couldn't think of a way to do it. 
 
>Well, here we have a good start. There are other little things, 
>but let's focus on this first :) 
 
I haven't touched my code for about a month. I'll build the 
latest SIP and PyQt4 snapshots and see if I can get it working 
with them. Then I'll upload the code somewhere. 
 
David 
 


___________________________________________________________
$0 Web Hosting with up to 200MB web space, 1000 MB Transfer
10 Personalized POP and Web E-mail Accounts, and much more.
Signup at www.doteasy.com




More information about the PyQt mailing list