[PyQt] Re: QStyle manipulations

Phil Thompson phil at riverbankcomputing.com
Mon Jul 27 20:28:03 BST 2009


On Mon, 27 Jul 2009 21:03:59 +0200, "Hans-Peter Jansen" <hpj at urpla.net>
wrote:
> 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?

You can certainly work around the problem with C++ code - but I'm not sure
if SIP will allow you to place the C++ code in the right place.

Phil


More information about the PyQt mailing list