diff options
author | Renato Filho <renato.filho@openbossa.org> | 2011-05-23 11:39:17 -0300 |
---|---|---|
committer | Hugo Parente Lima <hugo.pl@gmail.com> | 2012-03-08 16:54:25 -0300 |
commit | 77559ac63945da93f7e90c2910232c6eb2629487 (patch) | |
tree | d5647375e1b48d7cef0d344433ddf9c578433829 | |
parent | d9c43275a09fc68146a210a9da281a9491d62980 (diff) |
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.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 |