[PyKDE] Re: newest Version

Jim Bublitz jbublitz at nwinternet.com
Thu Oct 30 20:07:00 GMT 2003


On Thursday October 30 2003 00:34, Roland Schulz wrote:
> On Thursday 30 October 2003 06:29, you wrote:
> > On Wednesday October 29 2003 17:46, David Boddie wrote:
> > > On Wednesday 29 October 2003 22:40, Jim Bublitz wrote:
> > > > If you get
> > > > QWidget::metaObject(), will you get the QFrame and
> > > > QLineEdit meta data too?

> > > I would have thought that the meta object will still
> > > contain all the information that was stored in it
> > > regardless of the class used to call metaObject.

> > Yeah - I didn't think this through very clearly. For any
> > QObject descendent, there's only one instance of QMetaObject
> > [1], so the derived class's meta data has to be attached to
> > that. So in the example (PyWidget) above, even if you have a
> > QWidget *w, w->metaObject() has to include the meta data
> > added by QFrame and QLineEdit (and you should be able to add
> > PyWidget's meta data as well). You may need to set things
> > like "className".

> Like I wrote in the mail before, we can't change the
> QMetaObject, because we would also change it for the C++
> objets. And if we overwrite the metaObject method we can
> return a new QMetaObject everythime we need to.

Oh details, details. :) I did screw that up, didn't I? Still it 
doesn't make a lot of difference. David's suggestion was to do 
something like PyKPanelApplet, which makes more sense to me now. 
That won't work either - if you insist that all Python-created 
widgets inherit from some PyQWidget base class, you won't be 
able to handle things like widgets derived from QListView or 
QLineEdit. Your suggestion about overloading metaObject() seems 
like a good idea to me - that let's you construct your own 
QMetaObject and gets around the "private" stuff (I think you can 
get around most of that anyway, but this way you don't have to).

My suggestion (v2.0) would be to create (in C++) a proxy for 
QWidget (greatly oversimplified):

    class ProxyQWidget : public QWidget
    {
    public:
        // construct from the QWidget createWidget returns
       ProxyQWidget (QWidget *wIn) { w = wIn; }
  

        //  overload this to allow you to contruct your own
        //  QMetaObject from QWidget passed in and data
        //  in Python module this proxies.
        virtual QMetaObject *metaObject (); 

        // overload *all* of ProxyQWidget's virtual methods
        // with calls to QWidget's (w's) methods
        virtual void show () { w->show (); }
        ...

    private:
        QWidget *w;
    };

Return the ProxyQWidget instance to QtDesigner instead of 
QWidget. ProxyQWidget will have the same virtual methods as 
QWidget and it's own QMetaObject (not static). The constructor 
(or some class method) needs to be able to access the "meta 
data" the Python widget supplies too and "customize" the class 
to the class being proxied - I haven't shown that above.

I'm guessing that QtDesigner really only calls QWidget methods 
for *any* widget (except for special stuff which is specifically 
hardcoded - the QListViewItem editor). If not, you might need 
somthing like ProxyQFrame or ProxyQLabel if there are some 
specialized methods that QtDesigner needs beyond what's in 
QWidget. They could probably inherit from ProxyQWidget too.
Then you'd need a switch to select the correct proxy class.

I'm also not sure if you need to be able to handle objects that 
inherit from QObject, but not QWidget (eg QLayout), but it's 
simple to test for the case where QWidget isn't a base class. 
Then you just need additional proxy classes (perhaps 
ProxyQObject or ProxyQLayout).

It's somewhat of a pain to write all of the overloads, but there 
aren't that many, they're trivial,  and you only have to do it 
once. Effectively you're copying the virtual method table from 
QWidget -> ProxyQWidget with one substitution. I don't think 
there's any easier way to do that (at run time).

> > If that weren't true it'd be a lot harder for TT to write
> > QtDesigner in the first place - the type casting would be a
> > real pain.
> >
> > Cases like:
> >
> > class A (QWidget)
> > class B (A)
> >
> > will need some special handling (by the user) to set the
> > Python meta data correctly.

> I don't think so. If we have overwritten the metaObect method
> call so it returns the apropriate new created for the Python
> subclasses, we get the correct QMetaObject also for a Python
> superclass and can pass this to the QMetaObject constructor,
> so it adds all those informations too.

You're right if you actually create real C++ classes for the 
Python class. However, if you want a single .so plugin for all 
Python widgets (instead of one .so per widget or module), I 
don't think you can use  a static meta object. There might be a 
way to "emulate" a static meta object though, but I'd wonder if 
that's worth doing.

> > [1] The exception might be if the class inherits multiple
> > QObject or QWidget derived classes, but that can't be done
> > directly in Python/PyQt. Don't know if a Qt class like that
> > exists.

> We probably have to test this. I have no clue what happens
> than ;-)

I'd leave this for a "future version" myself.

> > This is Roland's project, so it's up to him to give orders
> > on how to proceed. If what I'm suggesting isn't clear (and
> > I've certainly been muddling through this), I can write up
> > an example to test out creating a Python widget, adding the
> > meta data, and testing calls for virtual methods. It should
> > be possible to code the plugin from that. That of course
> > assumes you want to try going that route.

> Like I wrote I think it's not possible. But of course I can be
> completly wrong.

Like me?

I'd still lean towards doing this in some way that requires no 
changes/minimal changes to PyQt.

I still think this is your project and your choice. I'm just 
making suggestions (sometimes not very good ones).

Jim




More information about the PyQt mailing list