[PyQt] PyQt4 question (follow on)

Phil Thompson phil at riverbankcomputing.co.uk
Mon May 28 10:22:49 BST 2007


On Monday 28 May 2007 9:53 am, Detlev Offenbach wrote:
> On Montag, 28. Mai 2007, Detlev Offenbach wrote:
> > On Sonntag, 27. Mai 2007, Phil Thompson wrote:
> > > On Sunday 27 May 2007 1:10 pm, Detlev Offenbach wrote:
> > > > On Sonntag, 27. Mai 2007, Phil Thompson wrote:
> > > > > On Sunday 27 May 2007 12:37 pm, Detlev Offenbach wrote:
> > > > > > On Sonntag, 27. Mai 2007, Phil Thompson wrote:
> > > > > > > On Sunday 27 May 2007 11:50 am, Detlev Offenbach wrote:
> > > > > > > > On Sonntag, 27. Mai 2007, Phil Thompson wrote:
> > > > > > > > > On Saturday 26 May 2007 9:07 pm, Detlev Offenbach wrote:
> > > > > > > > > > On Samstag, 26. Mai 2007, Phil Thompson wrote:
> > > > > > > > > > > On Saturday 26 May 2007 7:58 pm, Detlev Offenbach wrote:
> > > > > > > > > > > > On Samstag, 26. Mai 2007, Phil Thompson wrote:
> > > > > > > > > > > > > On Saturday 26 May 2007 4:52 pm, Detlev Offenbach
>
> wrote:
> > > > > > > > > > > > > > Hi,
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > is there a PyQt equivalent to
> > > > > > > > > > > > > > "qobject_cast<T*>(object)"?
> > > > > > > > > > > > >
> > > > > > > > > > > > > sip.cast()?
> > > > > > > > > > > > >
> > > > > > > > > > > > > But it shouldn't be necessary if the sub-class
> > > > > > > > > > > > > conversion code has been properly implemented.
> > > > > > > > > > > >
> > > > > > > > > > > > How do I do that. I haven't wrapped complicated stuff
> > > > > > > > > > > > like this so far. The situation is as follows. I have
> > > > > > > > > > > > the following code:
> > > > > > > > > > > >
> > > > > > > > > > > >
> > > > > > > > > > > > self.plugins.extend(self.designer.pluginManager().ins
> > > > > > > > > > > >ta nc es () ) for plugin in self.plugins:
> > > > > > > > > > > >             if isinstance(plugin,
> > > > > > > > > > > > QDesignerFormEditorPluginInterface): if not
> > > > > > > > > > > > plugin.isInitialized():
> > > > > > > > > > > > plugin.initialze(self.designer)
> > > > > > > > > > > >
> > > > > > > > > > > >
> > > > > > > > > > > > "self.designer.pluginManager().instances()" returns a
> > > > > > > > > > > > list of QObject. The first if statement shall check,
> > > > > > > > > > > > wether the returned QObject is of type
> > > > > > > > > > > > QDesignerFormEditorPluginInterface. In C++ you would
> > > > > > > > > > > > do it with code like
> > > > > > > > > > > >
> > > > > > > > > > > > if (
> > > > > > > > > > > > (qobject_cast<QDesignerFormEditorPluginInterface*>(pl
> > > > > > > > > > > >ug in )) )
> > > > > > > > > > > >
> > > > > > > > > > > > How can the problem be solved with PyQt4 and Python?
> > > > > > > > > > > >
> > > > > > > > > > > > Note: self.designer.pluginManager() returns an object
> > > > > > > > > > > > of type QDesignerPluginManager.
> > > > > > > > > > >
> > > > > > > > > > > The wrapper for QDesignerFormEditorPluginInterface must
> > > > > > > > > > > define some %ConvertToSubClassCode which will use RTTI
> > > > > > > > > > > provided by the instance to identify the right Python
> > > > > > > > > > > type object. See how PyQt does it for QObject and
> > > > > > > > > > > QEvent. If the instance doesn't provide any RTTI then
> > > > > > > > > > > you're stuck.
> > > > > > > > > >
> > > > > > > > > > Mustn't the %ConvertToSubClassCode go into the more
> > > > > > > > > > general class (e.g. QObject)?
> > > > > > > > >
> > > > > > > > > No - just in a QObject sub-class in the module.
> > > > > > > > >
> > > > > > > > > > Is there a way to extend the QObject wrapper?
> > > > > > > > >
> > > > > > > > > That's what sip does under the covers.
> > > > > > > >
> > > > > > > > I am stuck at the moment due to my lack of sip know how.
> > > > > > > > Below is the wrapper code in question. How does the
> > > > > > > > %ConvertToSubClassCode have to be?
> > > > > > > >
> > > > > > > > -------------------------------------------------------------
> > > > > > > >-- -- -- -- -- -- -- - class
> > > > > > > > QDesignerFormEditorPluginInterface {
> > > > > > > >
> > > > > > > > %TypeHeaderCode
> > > > > > > > #include <abstractformeditorplugin.h>
> > > > > > > > %End
> > > > > > > >
> > > > > > > > public:
> > > > > > > >     virtual ~QDesignerFormEditorPluginInterface();
> > > > > > > >
> > > > > > > >     virtual bool isInitialized() const = 0;
> > > > > > > >     virtual void initialize(QDesignerFormEditorInterface
> > > > > > > > *core) = 0; virtual QAction *action() const = 0;
> > > > > > > >
> > > > > > > >     virtual QDesignerFormEditorInterface *core() const = 0;
> > > > > > > > };
> > > > > > > > -------------------------------------------------------------
> > > > > > > >-- -- -- -- -- -- --
> > > > > > >
> > > > > > > What RTTI is available for the code to determine what the class
> > > > > > > really is? I can't see anything that is obviously suitable - in
> > > > > > > which case you are stuck.
> > > > > >
> > > > > > In a C++ program one would do it with this statement
> > > > > >
> > > > > > qobject_cast<QDesignerFormEditorPluginInterface*>(object)
> > > > > >
> > > > > > where object is a pointer to a QObject. If the conversion code
> > > > > > would be in QObject.sip, one could probably use the inherits()
> > > > > > method of QObject.
> > > > >
> > > > > So that's what you put in your conversion code in your
> > > > > QDesignerFormEditorPluginInterface class.
> > > >
> > > > I tried that before I posted to this list, but it didn't work. Phil,
> > > > can you give a little help?
> > >
> > > Post what you tried.
> >
> > I tried it with the following code:
> >
> > %ModuleHeaderCode
> > #include <qobject.h>
> > %End
> >
> > class QDesignerFormEditorPluginInterface
> > {
> >
> > %TypeHeaderCode
> > #include <abstractformeditorplugin.h>
> > %End
> >
> > %ConvertToSubClassCode
> >     if ( (qobject_cast<QDesignerFormEditorPluginInterface*>(sipCpp)) )
> >         sipClass = sipClass_QDesignerFormEditorPluginInterface;
> >     else
> >         sipClass = NULL;
> > %End
> >
> > public:
> >     virtual ~QDesignerFormEditorPluginInterface();
> >
> >     virtual bool isInitialized() const = 0;
> >     virtual void initialize(QDesignerFormEditorInterface *core) = 0;
> >     virtual QAction *action() const = 0;
> >
> >     virtual QDesignerFormEditorInterface *core() const = 0;
> > };
> >
> > However, that code doesn't even compile because at this place,
> > QDesignerFormEditorPluginInterface isn't derived from QObject. It seems,
> > that this is a mixin class, that QDesignerPluginManager takes care of and
> > returns a QObject.
>
> I traced this a bit further through the Qt code and found, that the plugin
> is loaded via QPluginLoader::instance(). Here is an excerpt from the Qt
> docu on how to use such a plugin.
>
> "The component object is a QObject. Use qobject_cast() to access interfaces
> you are interested in."
>
> It seems, we are missing something here on the Python side.

I'm not sure how to come to that conclusion.

I would look at creating a C++ class that is the minimal implementation of an 
object that conforms to the interface (ie. it is subclassed from QObject and 
QDesignerFormEditorPluginInterface). Then provide it with appropriate 
sub-class conversion code. You could look at the QtDesigner QPy classes in 
PyQt4 - these don't include sub-class convertor code because they are 
intended for writing Python plugins rather than loading C++ plugins.

Phil


More information about the PyQt mailing list