summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRenato Filho <renato.filho@openbossa.org>2011-05-23 11:39:17 -0300
committerRenato Filho <renato.filho@openbossa.org>2011-05-23 17:43:38 -0300
commit959aa385f576aca35f86fc04f8336e6a4ce044f1 (patch)
tree9161952f3213a533d8223fccad0a16911feb69c4
parent05431cbfc03a815d0f56e63728dca4b8e4a52d0a (diff)
downloadpyside-959aa385f576aca35f86fc04f8336e6a4ce044f1.tar.gz
pyside-959aa385f576aca35f86fc04f8336e6a4ce044f1.tar.xz
pyside-959aa385f576aca35f86fc04f8336e6a4ce044f1.zip
Created DestroyListener class.
This class is used to keep the Python object live until the signal destroyed emission. With this is possible to use the QObject on destruction signal. Fixes bug #505. Reviewer: Marcelo Lira <marcelo.lira@openbossa.org> Hugo Parente Lima <hugo.pl@gmail.com>
-rw-r--r--libpyside/CMakeLists.txt6
-rw-r--r--libpyside/destroylistener.cpp67
-rw-r--r--libpyside/destroylistener.h32
-rw-r--r--libpyside/pyside.cpp3
-rw-r--r--tests/QtCore/CMakeLists.txt1
-rw-r--r--tests/QtCore/destroysignal_test.py27
-rw-r--r--tests/QtGui/bug_576.py1
7 files changed, 137 insertions, 0 deletions
diff --git a/libpyside/CMakeLists.txt b/libpyside/CMakeLists.txt
index 2d2a613..e05a8cd 100644
--- a/libpyside/CMakeLists.txt
+++ b/libpyside/CMakeLists.txt
@@ -1,7 +1,11 @@
project(libpyside)
+
+qt4_wrap_cpp(DESTROYLISTENER_MOC "destroylistener.h")
+
set(libpyside_SRC
dynamicqmetaobject.cpp
+ destroylistener.cpp
signalmanager.cpp
globalreceiver.cpp
pysideclassinfo.cpp
@@ -11,6 +15,7 @@ set(libpyside_SRC
pysideproperty.cpp
pysideweakref.cpp
pyside.cpp
+ ${DESTROYLISTENER_MOC}
)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}
@@ -34,6 +39,7 @@ set_target_properties(pyside PROPERTIES
#
set(libpyside_HEADERS
+ destroylistener.h
dynamicqmetaobject.h
globalreceiver.h
pysideclassinfo.h
diff --git a/libpyside/destroylistener.cpp b/libpyside/destroylistener.cpp
new file mode 100644
index 0000000..600d922
--- /dev/null
+++ b/libpyside/destroylistener.cpp
@@ -0,0 +1,67 @@
+#include "destroylistener.h"
+
+#include <Python.h>
+#include <QObject>
+#include <shiboken.h>
+#include <QDebug>
+#include <QMutex>
+
+PySide::DestroyListener* PySide::DestroyListener::m_instance = 0;
+
+namespace PySide
+{
+
+struct DestroyListenerPrivate
+{
+ static bool m_destroyed;
+};
+
+
+DestroyListener* DestroyListener::instance()
+{
+ if (!m_instance)
+ m_instance = new DestroyListener(0);
+ return m_instance;
+}
+
+void DestroyListener::destroy()
+{
+ if (m_instance) {
+ m_instance->disconnect();
+ delete m_instance;
+ m_instance = 0;
+ }
+}
+
+void DestroyListener::listen(QObject *obj)
+{
+ SbkObject* wrapper = Shiboken::BindingManager::instance().retrieveWrapper(obj);
+ if (!wrapper) // avoid problem with multiple inheritance
+ return;
+
+ if (Py_IsInitialized() == 0)
+ onObjectDestroyed(obj);
+ else
+ QObject::connect(obj, SIGNAL(destroyed(QObject*)), this, SLOT(onObjectDestroyed(QObject*)), Qt::DirectConnection);
+}
+
+void DestroyListener::onObjectDestroyed(QObject* obj)
+{
+ SbkObject* wrapper = Shiboken::BindingManager::instance().retrieveWrapper(obj);
+ if (wrapper) //make sure the object exists before destroy
+ Shiboken::Object::destroy(wrapper, obj);
+}
+
+DestroyListener::DestroyListener(QObject *parent)
+ : QObject(parent)
+{
+ m_d = new DestroyListenerPrivate();
+}
+
+DestroyListener::~DestroyListener()
+{
+ delete m_d;
+}
+
+}//namespace
+
diff --git a/libpyside/destroylistener.h b/libpyside/destroylistener.h
new file mode 100644
index 0000000..54dda2c
--- /dev/null
+++ b/libpyside/destroylistener.h
@@ -0,0 +1,32 @@
+#ifndef PYSIDE_DESTROY_LISTENER
+#define PYSIDE_DESTROY_LISTENER
+
+
+#include <QObject>
+#include "pysidemacros.h"
+
+namespace PySide
+{
+class DestroyListenerPrivate;
+class PYSIDE_API DestroyListener : public QObject
+{
+ Q_OBJECT
+ public:
+ static DestroyListener* instance();
+ static void destroy();
+ void listen(QObject* obj);
+
+ public slots:
+ void onObjectDestroyed(QObject* obj);
+
+ private:
+ static DestroyListener* m_instance;
+ DestroyListenerPrivate* m_d;
+ DestroyListener(QObject *parent);
+ ~DestroyListener();
+};
+
+}//namespace
+
+#endif
+
diff --git a/libpyside/pyside.cpp b/libpyside/pyside.cpp
index a4fcbcc..af763aa 100644
--- a/libpyside/pyside.cpp
+++ b/libpyside/pyside.cpp
@@ -31,6 +31,7 @@
#include "pysidemetafunction_p.h"
#include "pysidemetafunction.h"
#include "dynamicqmetaobject.h"
+#include "destroylistener.h"
#include <basewrapper.h>
#include <conversions.h>
@@ -101,10 +102,12 @@ void registerCleanupFunction(CleanupFunction func)
void runCleanupFunctions()
{
+ //PySide::DestroyListener::instance()->destroy();
while (!cleanupFunctionList.isEmpty()) {
CleanupFunction f = cleanupFunctionList.pop();
f();
}
+ PySide::DestroyListener::destroy();
}
static void destructionVisitor(SbkObject* pyObj, void* data)
diff --git a/tests/QtCore/CMakeLists.txt b/tests/QtCore/CMakeLists.txt
index 251add1..365305f 100644
--- a/tests/QtCore/CMakeLists.txt
+++ b/tests/QtCore/CMakeLists.txt
@@ -21,6 +21,7 @@ PYSIDE_TEST(classinfo_test.py)
PYSIDE_TEST(child_event_test.py)
PYSIDE_TEST(deepcopy_test.py)
PYSIDE_TEST(deletelater_test.py)
+PYSIDE_TEST(destroysignal_test.py)
PYSIDE_TEST(duck_punching_test.py)
PYSIDE_TEST(hash_test.py)
PYSIDE_TEST(max_signals.py)
diff --git a/tests/QtCore/destroysignal_test.py b/tests/QtCore/destroysignal_test.py
new file mode 100644
index 0000000..1c5f986
--- /dev/null
+++ b/tests/QtCore/destroysignal_test.py
@@ -0,0 +1,27 @@
+from PySide.QtCore import QTimer, QObject
+import sys
+import unittest
+
+class TestDestroySignal(unittest.TestCase):
+ def onObjectDestroyed(self, timer):
+ self.assert_(isinstance(timer, QTimer))
+ self._destroyed = True
+
+ def testSignal(self):
+ self._destroyed = False
+ t = QTimer()
+ t.destroyed[QObject].connect(self.onObjectDestroyed)
+ del t
+ self.assert_(self._destroyed)
+
+ def testWithParent(self):
+ self._destroyed = False
+ p = QTimer()
+ t = QTimer(p)
+ t.destroyed[QObject].connect(self.onObjectDestroyed)
+ del p
+ self.assert_(self._destroyed)
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/tests/QtGui/bug_576.py b/tests/QtGui/bug_576.py
index b3c11a3..e66e109 100644
--- a/tests/QtGui/bug_576.py
+++ b/tests/QtGui/bug_576.py
@@ -8,6 +8,7 @@ import unittest
class Bug576(unittest.TestCase):
def onButtonDestroyed(self, button):
self._destroyed = True
+ self.assert_(isinstance(button, QtGui.QPushButton))
def testWidgetParent(self):
self._destroyed = False