On 23/04/2013 17:52, Phil Thompson wrote:
Please see the minimal test code below. In short connecting a signal
to
a
functools.partial slot breaks the expected moveToThread behaviour.
Reasonable, I'd say, once you think about it. I'm just asking some
suggestion
about how this issue can be addressed. I thought about reimplementing
some
signal class with a connect_partial method that stores bound args.
Python 2.7.3, Qt 4.8.2, PyQt 4.10 on Linux.

Should be fixed in tonight's PyQt4 snapshot.

I'm curious to understand how you fixed it. Can I ask for a diff or some
other
pointer to look at?

Look at get_receiver() in qpy/QtCore/qpycore_pyqtboundsignal.cpp. It just
strips off the functools.partial wrappers until it gets to the QObject. The
proxy that is created is then moved to the same thread as the QObject.

Works correctly with pyqtSignal.
I'm not able to reproduce the desired behaviour with QtCore.QObject.connect.
Any suggestion? What I'm missing?


#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys
import functools
import logging

from PyQt4 import QtCore

logging.basicConfig(level=logging.DEBUG)

logger = logging.getLogger('blah')


class CApp(QtCore.QCoreApplication):
    def __init__(self):
        QtCore.QCoreApplication.__init__(self, sys.argv)
        self.signature_noargs = QtCore.SIGNAL("signature_noargs()")
        self.signature_1arg = QtCore.SIGNAL("signature_1arg(PyQt_PyObject)")

    def emit_noargs(self):
        QtCore.QCoreApplication.emit(self, self.signature_noargs)

    def emit_1arg(self, *args):
        QtCore.QCoreApplication.emit(self, self.signature_1arg, *args)


class CReceiver(QtCore.QObject):
    def slot_noargs(self):
        logger.debug("slot_noargs %s", QtCore.QThread.currentThreadId())

    def slot_1arg(self, arg):
        logger.debug("slot_1arg %s %s", arg, QtCore.QThread.currentThreadId())


class CPartialProxy(QtCore.QObject):
    def __init__(self, functools_partial_instance):
        QtCore.QObject.__init__(self)
        real_code_object = functools_partial_instance.func
        t = real_code_object.im_self.thread()
        self.moveToThread(t)
        self._obj = real_code_object
        self._args = functools_partial_instance.args
        self._kwargs = functools_partial_instance.keywords

    def __call__(self, *args, **kwargs):
        kw = dict(kwargs)
        if self._kwargs is not None:
            kw.update(self._kwargs)
        self._obj(*(self._args + args), **kw)


app = CApp()
app_thread = app.thread()
logger.info("Main thread ID %s", QtCore.QThread.currentThreadId())

thread = QtCore.QThread()
thread.start()
while not thread.isRunning():
    pass

a = CReceiver()
a.moveToThread(thread)

receiver_partial = functools.partial(a.slot_1arg, "Partial ARG")
receiver_partial_proxy = CPartialProxy(receiver_partial)

QtCore.QObject.connect(app, app.signature_noargs, a.slot_noargs, QtCore.Qt.QueuedConnection) QtCore.QObject.connect(app, app.signature_noargs, receiver_partial_proxy, QtCore.Qt.QueuedConnection)

timer = QtCore.QTimer()
timer.setInterval(1000)
timer.timeout.connect(app.emit_noargs)
timer.start()

app.exec_()


--
            Giuseppe Corbelli
WASP Software Engineer, Copan Italia S.p.A
Phone: +390303666318  Fax: +390302659932
E-mail: giuseppe.corbe...@copanitalia.com
_______________________________________________
PyQt mailing list    PyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt

Reply via email to