diff options
-rw-r--r-- | libpyside/CMakeLists.txt | 6 | ||||
-rw-r--r-- | libpyside/destroylistener.cpp | 67 | ||||
-rw-r--r-- | libpyside/destroylistener.h | 32 | ||||
-rw-r--r-- | libpyside/pyside.cpp | 3 | ||||
-rw-r--r-- | tests/QtCore/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/QtCore/destroysignal_test.py | 27 | ||||
-rw-r--r-- | tests/QtGui/bug_576.py | 1 |
7 files changed, 137 insertions, 0 deletions
diff --git a/libpyside/CMakeLists.txt b/libpyside/CMakeLists.txt index 2d2a61375..e05a8cd7e 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 000000000..600d922c3 --- /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 000000000..54dda2c2e --- /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 a4fcbccf0..af763aa44 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 251add10d..365305fef 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 000000000..1c5f986bc --- /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 b3c11a35c..e66e1099d 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 |