PySide Bugzilla Closed for New Bugs

PySide is now a Qt Add-on and uses the Qt Project's JIRA Bug Tracker instead of this Bugzilla instance. This Bugzilla is left for reference purposes.

Bug 421 - Add connectSlotsByName functionality
: Add connectSlotsByName functionality
Status: CLOSED INVALID
Product: PySide
Classification: Unclassified
Component: QtCore
: 0.4.2
: All All
: P3 normal
Assigned To: Hugo Parente Lima
:
:
:
  Show dependency treegraph
 
Reported: 2010-10-19 00:58 EEST by kbrownlees
Modified: 2011-01-06 16:25 EET (History)
9 users (show)

See Also:


Attachments
Example showing the auto connect feature working on PySide (10.00 KB, application/octet-stream)
2010-12-23 18:16 EET, Hugo Parente Lima
Details

Note You need to log in before you can comment on or make changes to this bug.
Description kbrownlees 2010-10-19 00:58:07 EEST
Reporting as per
http://www.mail-archive.com/pyside@lists.openbossa.org/msg00187.html (someone
else made that post but such a useful feature!)

My apologies if this is fixed in the latest trunk, don't have time to test
against it currently (couldn't find any check-in messages which contained
connectSlotsByName).

Here is dirty python version which does the job:
def connectSlotsByName(topLevelObject):
    # Dirty little hack, strict naming convention which says anything starting
    # With on_ needs to be a method which should be connected.
    for slotAttr in [d for d in dir(topLevelObject) if d.startswith("on_")]:
        itemName, signalName = slotAttr[3:].rsplit("_", 1)
        # Now to find the corresponding signal
        signalChild = topLevelObject.findChild(QtCore.QObject, itemName)
        signal = getattr(signalChild, signalName)
        signalConnect = getattr(signal, "connect")
        signalConnect(getattr(topLevelObject, slotAttr))
Comment 1 Chris Morgan 2010-11-14 23:02:32 EET
I came across this and have found the real solution: provide the on_*_* methods
with the QtCore.Slot decorator.

What's more, this fixed up the being-called-multiple-times issue in both PyQt4
and PySide, which is precisely what I wanted. (Naturally, in PyQt4 I need to do
QtCore.Slot = QtCore.pyqtSlot.)

For example, here was one def I had, to disable another field if it was
such-and-such a value:

    def on_DisplayVersionType_currentIndexChanged(self, value):
        # Gets called twice: once with the index, once with a QString.
        if type(value) == int:
            return
        ...

By decorating it with QtCore.Slot(unicode), I was able to get rid of the if
type(value) == int: return, as the int version doesn't get called.
(QtCore.Slot(str) has the same effect.)

This also fixes the ridiculously common issue people have of a button callback
being called twice: once as clicked() and once as clicked(bool). (Search for
"pyqt clicked checked twice" or "pyqt signal twice"!) I had fixed that with a
decorator, but now realise QtCore.Slot was the right way to fix it.

My personal recommendation would be to fix this to do it as PyQt4 does it (not
requiring it to be decorated with Slot) but to raise a DeprecatedWarning when
it is done without the Slot decorator, which will alert users to the proper way
to do it - and avoid nasty hacks like this one which I had had:

    def apply_checked_param_fix(func):
        """Decorator to handle the 'checked' issue where you need a
checked=None
        parameter because it'll call it twice."""
        @wraps(func)
        def decorate(self, *args, **kwargs):
            if args == ():
                return
            func(self, *args, **kwargs)
        return decorate

    class Main(QtGui.QMainWindow):
        ...
        @apply_checked_param_fix
        def on_packageButton_clicked(self, checked=None):
            ...

I was able to replace that apply_checked_param_fix directly with QtCore.Slot()
and remove the checked parameter altogether (with QCommandLinkButton it's
always False so I don't want it).
Comment 2 Matti Airas 2010-11-23 05:51:34 EET
Acknowledging and retaining P3 - this will be fixed in the upcoming sprints.
Comment 3 Hugo Parente Lima 2010-12-23 18:16:20 EET
Created attachment 203 [details]
Example showing the auto connect feature working on PySide

I tested and connectSlotsByNames works fine, but you have to declare your slots
with the decorator @Slot and the right type parameters.

I think this is better and less error prone than accept any method on auto
connect feature, besides if you use the decorator your code will be compatible
with PyQt4.

I attached an example showing the feature.
Comment 4 Hugo Parente Lima 2010-12-23 18:17:53 EET
Marking the bug as invalid, fell free to reopen the bug or add any comments if
you think it's necessary.
Comment 5 renato filho 2011-01-06 16:25:19 EET
released on beta3