summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHugo Parente Lima <hugo.pl@gmail.com>2010-10-22 17:28:43 -0200
committerHugo Parente Lima <hugo.pl@gmail.com>2010-10-22 19:16:51 -0200
commit77a1654ad587241d3c14bafa2c0deae53e1599ee (patch)
tree1b2dece9fe99a5a956420e03229d0872916a9a05
parent800fb4613cb61dbff33750ec0ab4b18ca3369c6c (diff)
downloadpyside-77a1654ad587241d3c14bafa2c0deae53e1599ee.tar.gz
pyside-77a1654ad587241d3c14bafa2c0deae53e1599ee.tar.xz
pyside-77a1654ad587241d3c14bafa2c0deae53e1599ee.zip
Fix bugs 430, 426, 429, 394, 433.
These bugs are about QApplication instance being destroyed before some QObject. Reviewer: Luciano Wolf <luciano.wolf@openbossa.org> Renato Ara├║jo <renato.filho@openbossa.org>
-rw-r--r--PySide/QtCore/glue/qcoreapplication_init.cpp17
-rw-r--r--PySide/QtGui/glue/qapplication_init.cpp24
-rw-r--r--libpyside/pyside.cpp26
-rw-r--r--libpyside/pyside.h5
-rw-r--r--tests/QtGui/CMakeLists.txt3
-rw-r--r--tests/QtGui/bug_429.py10
-rw-r--r--tests/QtGui/bug_430.py14
-rw-r--r--tests/QtGui/bug_433.py14
-rw-r--r--tests/QtUiTools/CMakeLists.txt1
-rw-r--r--tests/QtUiTools/bug_426.py18
-rw-r--r--tests/QtUiTools/bug_426.ui19
11 files changed, 112 insertions, 39 deletions
diff --git a/PySide/QtCore/glue/qcoreapplication_init.cpp b/PySide/QtCore/glue/qcoreapplication_init.cpp
index 461757c..66247bf 100644
--- a/PySide/QtCore/glue/qcoreapplication_init.cpp
+++ b/PySide/QtCore/glue/qcoreapplication_init.cpp
@@ -2,21 +2,6 @@
static int QCoreApplicationArgCount;
static char** QCoreApplicationArgValues;
-/**
- * Called at QtCore module exit
- */
-void DeleteQCoreApplicationAtExit()
-{
- QCoreApplication *cpp = QCoreApplication::instance();
- if (cpp) {
- Shiboken::BindingManager &bmngr = Shiboken::BindingManager::instance();
- cpp->flush();
- QCoreApplication::processEvents();
- bmngr.destroyWrapper(cpp);
- delete cpp;
- }
-}
-
int SbkQCoreApplication_Init(PyObject* self, PyObject* args, PyObject*)
{
if (Shiboken::isUserType(self) && !Shiboken::canCallConstructor(self->ob_type, Shiboken::SbkType<QApplication >()))
@@ -52,7 +37,7 @@ int SbkQCoreApplication_Init(PyObject* self, PyObject* args, PyObject*)
PySide::signalUpdateSource(self);
cptr->metaObject();
- PySide::registerCleanupFunction(DeleteQCoreApplicationAtExit);
+ PySide::registerCleanupFunction(&PySide::destroyQCoreApplication);
Py_INCREF(self);
return 1;
}
diff --git a/PySide/QtGui/glue/qapplication_init.cpp b/PySide/QtGui/glue/qapplication_init.cpp
index d082b99..ba98f02 100644
--- a/PySide/QtGui/glue/qapplication_init.cpp
+++ b/PySide/QtGui/glue/qapplication_init.cpp
@@ -5,28 +5,6 @@ static int QApplicationArgCount;
static char** QApplicationArgValues;
static const char QAPP_MACRO[] = "qApp";
-void DeleteQApplicationAtExit()
-{
- PySide::SignalManager::instance().clear();
- QCoreApplication* cpp = QApplication::instance();
- if (cpp) {
- Shiboken::BindingManager &bmngr = Shiboken::BindingManager::instance();
-
- // Delete all widgets, this is slow but is necessary to avoid problems with python object
- foreach(QWidget* w, QApplication::allWidgets()) {
- PyObject* wrapper = bmngr.retrieveWrapper(w);
- if (wrapper) {
- if (SbkBaseWrapper_hasOwnership(wrapper))
- delete w; // destroy C++ object and invalidate wrapper object
- else
- bmngr.destroyWrapper(wrapper); // only invalidate wrapper object
- }
- }
- cpp->flush();
- delete cpp;
- }
-}
-
int SbkQApplication_Init(PyObject* self, PyObject* args, PyObject*)
{
if (Shiboken::isUserType(self) && !Shiboken::canCallConstructor(self->ob_type, Shiboken::SbkType<QApplication >()))
@@ -69,7 +47,7 @@ int SbkQApplication_Init(PyObject* self, PyObject* args, PyObject*)
}
PyObject_SetAttrString(moduleQtGui, QAPP_MACRO, self);
- PySide::registerCleanupFunction(DeleteQApplicationAtExit);
+ PySide::registerCleanupFunction(&PySide::destroyQCoreApplication);
Py_INCREF(self);
return 1;
}
diff --git a/libpyside/pyside.cpp b/libpyside/pyside.cpp
index 7d92300..c2e1435 100644
--- a/libpyside/pyside.cpp
+++ b/libpyside/pyside.cpp
@@ -24,9 +24,11 @@
#include "pyside.h"
#include <basewrapper.h>
#include <conversions.h>
+#include <typeresolver.h>
#include <algorithm>
#include <cctype>
#include <QStack>
+#include <QCoreApplication>
#include "signalmanager.h"
#include "qproperty_p.h"
#include "qproperty.h"
@@ -98,5 +100,29 @@ void runCleanupFunctions()
}
}
+void destroyQCoreApplication()
+{
+ SignalManager::instance().clear();
+ QCoreApplication* app = QCoreApplication::instance();
+ if (!app)
+ return;
+
+ Shiboken::BindingManager& bm = Shiboken::BindingManager::instance();
+ PyObject* pyQApp = bm.retrieveWrapper(app);
+ PyTypeObject* pyQObjectType = Shiboken::TypeResolver::get("QObject*")->pythonType();
+ assert(pyQObjectType);
+
+ foreach (PyObject* pyObj, bm.getAllPyObjects()) {
+ if (pyObj != pyQApp && PyObject_TypeCheck(pyObj, pyQObjectType)) {
+ if (SbkBaseWrapper_hasOwnership(pyObj)) {
+ bm.destroyWrapper(pyObj);
+ delete static_cast<QObject*>(Shiboken::getCppPointer(pyObj, Shiboken::SbkType<QObject*>()));
+ }
+ }
+ }
+ app->flush();
+ delete app;
+}
+
} //namespace PySide
diff --git a/libpyside/pyside.h b/libpyside/pyside.h
index 2c5afb5..fe9ce3a 100644
--- a/libpyside/pyside.h
+++ b/libpyside/pyside.h
@@ -84,6 +84,11 @@ typedef void (*CleanupFunction)(void);
PYSIDE_API void registerCleanupFunction(CleanupFunction func);
PYSIDE_API void runCleanupFunctions();
+/**
+ * Destroy a QCoreApplication taking care of destroy all instances of QObject first.
+ */
+PYSIDE_API void destroyQCoreApplication();
+
} //namespace PySide
diff --git a/tests/QtGui/CMakeLists.txt b/tests/QtGui/CMakeLists.txt
index 21aa769..7ff2f7e 100644
--- a/tests/QtGui/CMakeLists.txt
+++ b/tests/QtGui/CMakeLists.txt
@@ -13,6 +13,9 @@ PYSIDE_TEST(bug_367.py)
PYSIDE_TEST(bug_389.py)
PYSIDE_TEST(bug_400.py)
PYSIDE_TEST(bug_416.py)
+PYSIDE_TEST(bug_429.py)
+PYSIDE_TEST(bug_430.py)
+PYSIDE_TEST(bug_433.py)
PYSIDE_TEST(customproxywidget_test.py)
PYSIDE_TEST(deepcopy_test.py)
PYSIDE_TEST(float_to_int_implicit_conversion_test.py)
diff --git a/tests/QtGui/bug_429.py b/tests/QtGui/bug_429.py
new file mode 100644
index 0000000..f49d244
--- /dev/null
+++ b/tests/QtGui/bug_429.py
@@ -0,0 +1,10 @@
+from PySide.QtCore import *
+from PySide.QtGui import *
+import sys
+
+app = QApplication(sys.argv)
+scene = QGraphicsScene()
+label = QLabel("hello world")
+label.show()
+QTimer.singleShot(0, label.close)
+exit(app.exec_())
diff --git a/tests/QtGui/bug_430.py b/tests/QtGui/bug_430.py
new file mode 100644
index 0000000..256c4e2
--- /dev/null
+++ b/tests/QtGui/bug_430.py
@@ -0,0 +1,14 @@
+import sys
+from PySide.QtCore import *
+from PySide.QtGui import *
+
+class ListModel(QAbstractListModel):
+ def rowCount(self, parent = QModelIndex()):
+ return len(self._items)
+
+app = QApplication([])
+model = ListModel()
+v = QListView()
+v.setModel(model)
+QTimer.singleShot(0, v.close)
+app.exec_()
diff --git a/tests/QtGui/bug_433.py b/tests/QtGui/bug_433.py
new file mode 100644
index 0000000..97d897e
--- /dev/null
+++ b/tests/QtGui/bug_433.py
@@ -0,0 +1,14 @@
+from PySide import QtCore, QtGui
+import sys
+
+class Test(QtGui.QGraphicsView):
+ def __init__(self, parent=None):
+ super(Test, self).__init__(parent)
+ self.s = QtGui.QGraphicsScene()
+ self.setScene(self.s)
+
+a = QtGui.QApplication(sys.argv)
+t = Test()
+t.show()
+QtCore.QTimer.singleShot(0, t.close)
+sys.exit(a.exec_())
diff --git a/tests/QtUiTools/CMakeLists.txt b/tests/QtUiTools/CMakeLists.txt
index 7cb8b6a..ebf7a23 100644
--- a/tests/QtUiTools/CMakeLists.txt
+++ b/tests/QtUiTools/CMakeLists.txt
@@ -1,5 +1,6 @@
PYSIDE_TEST(bug_360.py)
PYSIDE_TEST(bug_376.py)
PYSIDE_TEST(bug_392.py)
+PYSIDE_TEST(bug_426.py)
PYSIDE_TEST(uiloader_test.py)
PYSIDE_TEST(ui_test.py)
diff --git a/tests/QtUiTools/bug_426.py b/tests/QtUiTools/bug_426.py
new file mode 100644
index 0000000..11e2631
--- /dev/null
+++ b/tests/QtUiTools/bug_426.py
@@ -0,0 +1,18 @@
+import sys
+import os
+from PySide import QtCore, QtGui
+from PySide.QtUiTools import QUiLoader
+
+class Window(object):
+ def __init__(self):
+ loader = QUiLoader()
+ filePath = os.path.join(os.path.dirname(__file__), 'bug_426.ui')
+ self.widget = loader.load(filePath)
+ self.group = QtGui.QActionGroup(self.widget)
+ self.widget.show()
+ QtCore.QTimer.singleShot(0, self.widget.close)
+
+if __name__ == "__main__":
+ app = QtGui.QApplication(sys.argv)
+ win = Window()
+ sys.exit(app.exec_())
diff --git a/tests/QtUiTools/bug_426.ui b/tests/QtUiTools/bug_426.ui
new file mode 100644
index 0000000..99353cd
--- /dev/null
+++ b/tests/QtUiTools/bug_426.ui
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Form</class>
+ <widget class="QWidget" name="Form">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>