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