summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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