[PyQt] Re: QStyle manipulations

Hans-Peter Jansen hpj at urpla.net
Mon Jul 27 20:03:59 BST 2009


Am Montag, 27. Juli 2009 schrieb Hans-Peter Jansen:
> Am Montag, 27. Juli 2009 schrieb Phil Thompson:
> > On Mon, 27 Jul 2009 18:40:18 +0200, "Hans-Peter Jansen" <hpj at urpla.net>
> >
> > wrote:
> > > Am Montag, 27. Juli 2009 schrieb Hans-Peter Jansen:
> > >> Am Montag, 27. Juli 2009 schrieb Hans-Peter Jansen:
> > >> > Next you find a test script simply intercepting this slot, but
> > >> > while the constructor of PlastiqueStyle is being called correctly,
> > >> > the slot is not :-(.
> > >
> > > For what is worth, here's an updated version of the test script, that
> > > depends on the former q*style.sip files included in your PyQt
> >
> > installation.
> >
> > > I've still no idea, why the layoutSpacingImplementation() slot is not
> > > called, but this script proves, that both PM_LayoutHorizontalSpacing
> > > and PM_LayoutVerticalSpacing do return -1, which is prerequisite for
> > > Qt to
> >
> > call
> >
> > > this slot.
> > >
> > > My theory is, that this paragraph is the culprit:
> > >
> > > About QStyle::layoutSpacing():
> > > For binary compatibility reasons, this function is not virtual. If
> > > you
> >
> > want
> >
> > > to specify custom layout spacings in a QStyle subclass, implement a
> > > slot called layoutSpacingImplementation(). QStyle will discover the
> > > slot at run-time (using Qt's meta-object system) and direct all calls
> > > to layoutSpacing() to layoutSpacingImplementation().
> > >
> > > Phil, could it be, that Qt isn't able to discover the slot being
> >
> > available
> >
> > > as a pyqt slot?
> >
> > Almost certainly.
>
> Let's face the enemy:
>
> /*!
>     \since 4.3
>
>     Returns the spacing that should be used between \a control1 and
>     \a control2 in a layout. \a orientation specifies whether the
>     controls are laid out side by side or stacked vertically. The \a
>     option parameter can be used to pass extra information about the
>     parent widget. The \a widget parameter is optional and can also
>     be used if \a option is 0.
>
>     This function is called by the layout system. It is used only if
>     PM_LayoutHorizontalSpacing or PM_LayoutVerticalSpacing returns a
>     negative value.
>
>     For binary compatibility reasons, this function is not virtual.
>     If you want to specify custom layout spacings in a QStyle
>     subclass, implement a slot called layoutSpacingImplementation().
>     QStyle will discover the slot at run-time (using Qt's
>     \l{meta-object system}) and direct all calls to layoutSpacing()
>     to layoutSpacingImplementation().
>
>     \sa combinedLayoutSpacing(), layoutSpacingImplementation()
> */
> int QStyle::layoutSpacing(QSizePolicy::ControlType control1,
> QSizePolicy::ControlType control2, Qt::Orientation orientation, const
> QStyleOption *option, const QWidget *widget) const
> {
>     Q_D(const QStyle);
>     if (d->layoutSpacingIndex == -1) {
>         d->layoutSpacingIndex = metaObject()->indexOfMethod(
>            
> "layoutSpacingImplementation(QSizePolicy::ControlType,QSizePolicy::Contro
>lType," "Qt::Orientation,const QStyleOption*,const QWidget*)" );
>     }
>     if (d->layoutSpacingIndex < 0)
>         return -1;
>     int result = -1;
>     void *param[] = {&result, &control1, &control2, &orientation,
> &option, &widget};
>
>     const_cast<QStyle
> *>(this)->qt_metacall(QMetaObject::InvokeMetaMethod,
> d->layoutSpacingIndex, param); return result;
> }
>
>
> Do you see any chance of getting this to behave?

Hmm, from what I can see (though I _am_ blind, when it comes to the guts
from sip and PyQt), most of needed mechanics is in place. The question is,
what have to be done, that:
 * the metaObject is able to locate our method with
   metaObject()->indexOfMethod(), and 
 * qt_metacall is able to invoke our method

The former may already do what it should (otherwise parts of the QMetaObject
stuff won't do at all, it's even wrapped in qobjectdefs.sip). Moment: it's 
even accessible from Python:

destroyed(QObject*)
destroyed()
deleteLater()
_q_reregisterTimers(void*)
standardIconImplementation(StandardPixmap,const QStyleOption*,const QWidget*)
standardIconImplementation(StandardPixmap,const QStyleOption*)
standardIconImplementation(StandardPixmap)
layoutSpacingImplementation(QSizePolicy::ControlType,QSizePolicy::ControlType,Qt::Orientation,const QStyleOption*,const QWidget*)
layoutSpacingImplementation(QSizePolicy::ControlType,QSizePolicy::ControlType,Qt::Orientation,const QStyleOption*)
layoutSpacingImplementation(QSizePolicy::ControlType,QSizePolicy::ControlType,Qt::Orientation)
standardIconImplementation(StandardPixmap,const QStyleOption*,const QWidget*)
standardIconImplementation(StandardPixmap,const QStyleOption*)
standardIconImplementation(StandardPixmap)
standardIconImplementation(StandardPixmap,const QStyleOption*,const QWidget*)
standardIconImplementation(StandardPixmap,const QStyleOption*)
standardIconImplementation(StandardPixmap,const QStyleOption*,const QWidget*)
standardIconImplementation(StandardPixmap,const QStyleOption*)
standardIconImplementation(StandardPixmap)
layoutSpacingImplementation(QSizePolicy::ControlType,QSizePolicy::ControlType,Qt::Orientation,const QStyleOption*,const QWidget*)
layoutSpacingImplementation(QSizePolicy::ControlType,QSizePolicy::ControlType,Qt::Orientation,const QStyleOption*)
layoutSpacingImplementation(QSizePolicy::ControlType,QSizePolicy::ControlType,Qt::Orientation)
layoutSpacingImplementation(QSizePolicy::ControlType,QSizePolicy::ControlType,Qt::Orientation,QStyleOption*,QWidget*)

That's the effect of these lines in the PlastiqueStyle constructor:
        mo = self.metaObject()
        for i in range(mo.methodCount()):
            print mo.method(i).signature()

Interestingly layoutSpacingImplementation appears muliple times with the
same singature! Phil?

The latter seems to be the problem, since it may need some kind of handler.
Parts of qpy/QtCore/qpycore_pyqtproxy.cpp look like they handle similar 
cases. Is it possible to register our method at run-time and be done with 
it, Phil?

Sorry for being such a nuisance lately.

Thanks,
Pete


More information about the PyQt mailing list