Created PySide cleanup functions used to register functions to be called before the python die.

Reviewer: Hugo Parente Lima <hugo.pl@gmail.com>
          Luciano Wolf <luciano.wolf@openbossa.org>
This commit is contained in:
renatofilho 2010-09-17 17:03:01 -03:00
commit 6974551674
6 changed files with 59 additions and 20 deletions

View file

@ -1,21 +1,20 @@
// Global variables used to store argc and argv values // Global variables used to store argc and argv values
static int QCoreApplicationArgCount; static int QCoreApplicationArgCount;
static char** QCoreApplicationArgValues; static char** QCoreApplicationArgValues;
static bool leavingPython = false;
/** /**
* Called at QtCore module exit * Called at QtCore module exit
*/ */
void DeleteQCoreApplicationAtExit() void DeleteQCoreApplicationAtExit()
{ {
leavingPython = true;
QCoreApplication *cpp = QCoreApplication::instance(); QCoreApplication *cpp = QCoreApplication::instance();
if (cpp) { if (cpp) {
Shiboken::BindingManager &bmngr = Shiboken::BindingManager::instance(); Shiboken::BindingManager &bmngr = Shiboken::BindingManager::instance();
PyObject* pySelf = bmngr.retrieveWrapper(cpp); PyObject* pySelf = bmngr.retrieveWrapper(cpp);
if (pySelf) cpp->flush();
QCoreApplication::processEvents();
bmngr.invalidateWrapper(pySelf); bmngr.invalidateWrapper(pySelf);
cpp->deleteLater(); delete cpp;
} }
} }
@ -54,7 +53,7 @@ int SbkQCoreApplication_Init(PyObject* self, PyObject* args, PyObject*)
PySide::signalUpdateSource(self); PySide::signalUpdateSource(self);
cptr->metaObject(); cptr->metaObject();
Py_AtExit(DeleteQCoreApplicationAtExit); PySide::registerCleanupFunction(DeleteQCoreApplicationAtExit);
Py_INCREF(self); Py_INCREF(self);
return 1; return 1;
} }

View file

@ -553,7 +553,7 @@
<add-function signature="__moduleShutdown()"> <add-function signature="__moduleShutdown()">
<inject-code class="target" position="beginning"> <inject-code class="target" position="beginning">
PySide::SignalManager::instance().clear(); PySide::runCleanupFunctions();
</inject-code> </inject-code>
</add-function> </add-function>
@ -1875,12 +1875,7 @@
<!-- Obsolete --> <!-- Obsolete -->
<modify-function signature="argc()" remove="all"/> <modify-function signature="argc()" remove="all"/>
<!-- Obsolete --> <!-- Obsolete -->
<modify-function signature="notify(QObject*,QEvent*)"> <modify-function signature="notify(QObject*,QEvent*)" allow-thread="yes">
<inject-code class="shell" position="beginning">
Shiboken::ThreadStateSaver threadStateSaver;
if (!leavingPython)
threadStateSaver.save();
</inject-code>
<modify-argument index="2" invalidate-after-use="yes"/> <modify-argument index="2" invalidate-after-use="yes"/>
</modify-function> </modify-function>
<modify-function signature="QCoreApplication(int &amp;, char **)" access="private"/> <modify-function signature="QCoreApplication(int &amp;, char **)" access="private"/>

View file

@ -4,19 +4,29 @@ extern PyObject* moduleQtGui;
static int QApplicationArgCount; static int QApplicationArgCount;
static char** QApplicationArgValues; static char** QApplicationArgValues;
static const char QAPP_MACRO[] = "qApp"; static const char QAPP_MACRO[] = "qApp";
static bool leavingPython = false;
void DeleteQApplicationAtExit() void DeleteQApplicationAtExit()
{ {
leavingPython = true;
PySide::SignalManager::instance().clear(); PySide::SignalManager::instance().clear();
QCoreApplication* cpp = QApplication::instance(); QCoreApplication* cpp = QApplication::instance();
if (cpp) { if (cpp) {
Shiboken::BindingManager &bmngr = Shiboken::BindingManager::instance(); Shiboken::BindingManager &bmngr = Shiboken::BindingManager::instance();
PyObject* pySelf = bmngr.retrieveWrapper(cpp); cpp->flush();
if (pySelf)
// Delete all widgets, this is slow but is necessary to avoid problems with python object
foreach(QWidget* w, QApplication::allWidgets()) {
PyObject* pySelf = bmngr.retrieveWrapper(w);
w->deleteLater();
//Make sure all events will send before invalidated the python object
QApplication::processEvents();
bmngr.invalidateWrapper(pySelf); bmngr.invalidateWrapper(pySelf);
}
PyObject* pySelf = bmngr.retrieveWrapper(cpp);
cpp->deleteLater(); cpp->deleteLater();
QApplication::processEvents();
bmngr.invalidateWrapper(pySelf);
} }
} }
@ -62,7 +72,7 @@ int SbkQApplication_Init(PyObject* self, PyObject* args, PyObject*)
} }
PyObject_SetAttrString(moduleQtGui, QAPP_MACRO, self); PyObject_SetAttrString(moduleQtGui, QAPP_MACRO, self);
Py_AtExit(DeleteQApplicationAtExit); PySide::registerCleanupFunction(DeleteQApplicationAtExit);
Py_INCREF(self); Py_INCREF(self);
return 1; return 1;
} }

View file

@ -24,18 +24,22 @@
#include "pyside.h" #include "pyside.h"
#include "signalmanager.h" #include "signalmanager.h"
#include "qproperty.h" #include "qproperty.h"
#include "qsignal.h"
#include <basewrapper.h> #include <basewrapper.h>
#include <conversions.h> #include <conversions.h>
#include <algorithm> #include <algorithm>
#include "qsignal.h" #include <QStack>
extern "C" void init_signal(PyObject* module); extern "C" void init_signal(PyObject* module);
extern "C" void init_slot(PyObject* module); extern "C" void init_slot(PyObject* module);
extern "C" void init_qproperty(PyObject* module); extern "C" void init_qproperty(PyObject* module);
static QStack<PySide::CleanupFunction> cleanupFunctionList;
namespace PySide namespace PySide
{ {
void init(PyObject *module) void init(PyObject *module)
{ {
init_signal(module); init_signal(module);
@ -82,5 +86,20 @@ bool fillQtProperties(PyObject* qObj, const QMetaObject* metaObj, PyObject* kwds
return true; return true;
} }
void registerCleanupFunction(CleanupFunction func)
{
cleanupFunctionList.push(func);
}
void runCleanupFunctions()
{
while (!cleanupFunctionList.isEmpty()) {
CleanupFunction f = cleanupFunctionList.pop();
f();
}
}
} //namespace PySide } //namespace PySide

View file

@ -75,6 +75,15 @@ template<typename T>
struct initQtMetaType<T, false> { struct initQtMetaType<T, false> {
}; };
typedef void (*CleanupFunction)(void);
/**
* Register a function to be called before python die
*/
PYSIDE_API void registerCleanupFunction(CleanupFunction func);
PYSIDE_API void runCleanupFunctions();
} //namespace PySide } //namespace PySide

View file

@ -22,6 +22,7 @@
#include "signalmanager.h" #include "signalmanager.h"
#include "qproperty.h" #include "qproperty.h"
#include "pyside.h"
#include <QHash> #include <QHash>
#include <QStringList> #include <QStringList>
@ -223,6 +224,11 @@ struct SignalManager::SignalManagerPrivate
GlobalReceiver m_globalReceiver; GlobalReceiver m_globalReceiver;
}; };
static void clearSignalManager()
{
PySide::SignalManager::instance().clear();
}
SignalManager::SignalManager() : m_d(new SignalManagerPrivate) SignalManager::SignalManager() : m_d(new SignalManagerPrivate)
{ {
// Register Qt primitive typedefs used on signals. // Register Qt primitive typedefs used on signals.
@ -234,6 +240,7 @@ SignalManager::SignalManager() : m_d(new SignalManagerPrivate)
TypeResolver::createValueTypeResolver<PyObjectWrapper>(PYTHON_TYPE); TypeResolver::createValueTypeResolver<PyObjectWrapper>(PYTHON_TYPE);
TypeResolver::createValueTypeResolver<PyObjectWrapper>("object"); TypeResolver::createValueTypeResolver<PyObjectWrapper>("object");
TypeResolver::createValueTypeResolver<PyObjectWrapper>("PySide::PyObjectWrapper"); TypeResolver::createValueTypeResolver<PyObjectWrapper>("PySide::PyObjectWrapper");
PySide::registerCleanupFunction(clearSignalManager);
} }
void SignalManager::clear() void SignalManager::clear()