Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 66 additions & 55 deletions src/PythonQt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
/*!
// \file PythonQt.cpp
// \author Florian Link
// \author Last changed by $Author: florian $
// \date 2006-05
*/
//----------------------------------------------------------------------------------
Expand Down Expand Up @@ -324,8 +323,7 @@ void PythonQt::init(int flags, const QByteArray& pythonQtModuleName)
void PythonQt::cleanup()
{
if (_self) {
// Remove signal handlers in advance, since destroying them calls back into
// PythonQt::priv()->removeSignalEmitter()
// Remove all created signal receivers
_self->removeSignalHandlers();

delete _self;
Expand Down Expand Up @@ -879,65 +877,34 @@ PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, Py
return result;
}

PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
{
PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
if (!r) {
r = new PythonQtSignalReceiver(obj);
_p->_signalReceivers.insert(obj, r);
}
return r;
}

bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
{
bool flag = false;
PythonQtObjectPtr callable = lookupCallable(module, objectname);
if (callable) {
PythonQtSignalReceiver* r = getSignalReceiver(obj);
flag = r->addSignalHandler(signal, callable);
if (!flag) {
// signal not found
}
} else {
// callable not found
return _p->addSignalHandler(obj, signal, callable);
}
return flag;
// callable not found
return false;
}

bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* callable)
{
bool flag = false;
PythonQtSignalReceiver* r = getSignalReceiver(obj);
if (r) {
flag = r->addSignalHandler(signal, receiver);
}
return flag;
return _p->addSignalHandler(obj, signal, callable);
}

bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
{
bool flag = false;
PythonQtObjectPtr callable = lookupCallable(module, objectname);
if (callable) {
PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
if (r) {
flag = r->removeSignalHandler(signal, callable);
}
} else {
// callable not found
return _p->removeSignalHandler(obj, signal, callable);
}
return flag;
// callable not found
return false;
Comment thread
usiems marked this conversation as resolved.
}

bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* callable)
{
bool flag = false;
PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
if (r) {
flag = r->removeSignalHandler(signal, receiver);
}
return flag;
return _p->removeSignalHandler(obj, signal, callable);
}

PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
Expand Down Expand Up @@ -1619,20 +1586,14 @@ void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
}
}

void PythonQtPrivate::removeSignalEmitter(QObject* obj)
{
_signalReceivers.remove(obj);
}

void PythonQt::removeSignalHandlers()
{
QList<PythonQtSignalReceiver*> signalReceivers = _p->_signalReceivers.values();

// just delete all signal receivers, they will remove themselves via removeSignalEmitter()
for (PythonQtSignalReceiver* receiver : qAsConst(signalReceivers)) {
delete receiver;
auto it = _p->_signalReceivers.begin();
while (it != _p->_signalReceivers.end()) {
it.value()->markAsRemoved();
delete it.value();
it++;
}
// just to be sure, clear the receiver map as well
_p->_signalReceivers.clear();
}

Expand Down Expand Up @@ -2012,6 +1973,56 @@ PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const c
return info;
}

bool PythonQtPrivate::addSignalHandler(QObject* sender, const char* signal, PyObject* callable)
{
PYTHONQT_GIL_SCOPE
int sigId = PythonQtSignalReceiver::getSignalIndex(sender, signal);
if (sigId >= 0) {
// create PythonQtMethodInfo from signal
auto* receiver = new PythonQtSignalReceiver(sender, sigId, callable);
_signalReceivers.insert(SignalKey(sender, sigId), receiver);
return true;
}
return false;
}

bool PythonQtPrivate::removeSignalHandler(QObject* sender, const char* signal, PyObject* callable)
{
PYTHONQT_GIL_SCOPE
int foundCount = 0;
int sigId = PythonQtSignalReceiver::getSignalIndex(sender, signal);
if (sigId >= 0) {
SignalKey hashKey(sender, sigId);
auto it = _signalReceivers.find(hashKey);
while (it != _signalReceivers.end() && it.key() == hashKey) {
if (!callable || it.value()->isSameCallable(callable)) {
it.value()->markAsRemoved();
// delete later in case the connection is removed from the receiver callable itself
it.value()->deleteLater();
foundCount++;
it = _signalReceivers.erase(it);
} else {
it++;
}
}
}
return foundCount > 0;
}

void PythonQtPrivate::removeSignalReceiver(PythonQtSignalReceiver* receiver)
{
PYTHONQT_GIL_SCOPE
SignalKey hashKey(receiver->sender(), receiver->signalId());
auto it = _signalReceivers.find(hashKey);
while (it != _signalReceivers.end() && it.key() == hashKey) {
if (it.value() == receiver) {
_signalReceivers.erase(it);
break; // each receiver is only entered once
}
it++;
}
}

void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
{
_p->addPolymorphicHandler(typeName, cb);
Expand Down
18 changes: 11 additions & 7 deletions src/PythonQt.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
/*!
// \file PythonQt.h
// \author Florian Link
// \author Last changed by $Author: florian $
// \date 2006-05
*/
//----------------------------------------------------------------------------------
Expand All @@ -55,6 +54,7 @@
#include <QVariant>
#include <QList>
#include <QHash>
#include <QMultiHash>
#include <QByteArray>
#include <QStringList>
#include <QtDebug>
Expand Down Expand Up @@ -654,9 +654,6 @@ class PYTHONQT_EXPORT PythonQt : public QObject
//! callback for stderr redirection, emits pythonStdErr signal
static void stdErrRedirectCB(const QString& str);

//! get (and create if not available) the signal receiver of that QObject, signal receiver is made child of the passed \c obj
PythonQtSignalReceiver* getSignalReceiver(QObject* obj);

PythonQt(int flags, const QByteArray& pythonQtModuleName);
~PythonQt() override;
static PythonQt* _self;
Expand Down Expand Up @@ -729,8 +726,14 @@ class PYTHONQT_EXPORT PythonQtPrivate : public QObject
//! lookup existing classinfo and return new if not yet present
PythonQtClassInfo* lookupClassInfoAndCreateIfNotPresent(const char* typeName);

//! called when a signal emitting QObject is destroyed to remove the signal handler from the hash map
void removeSignalEmitter(QObject* obj);
//! add a signal handler
bool addSignalHandler(QObject* sender, const char* signal, PyObject* callable);

//! remove a signal handler for given callable (or all callables on that signal if callable is NULL)
bool removeSignalHandler(QObject* sender, const char* signal, PyObject* callable = nullptr);

//! called when a signal receiver is deleted to remove it from the hash map
void removeSignalReceiver(PythonQtSignalReceiver* receiver);

//! wrap the given QObject into a Python object (or return existing wrapper!)
PyObject* wrapQObject(QObject* obj);
Expand Down Expand Up @@ -865,7 +868,8 @@ class PYTHONQT_EXPORT PythonQtPrivate : public QObject
QHash<QByteArray, QByteArray> _knownLazyClasses;

//! stores signal receivers for QObjects
QHash<QObject*, PythonQtSignalReceiver*> _signalReceivers;
typedef QPair<QObject*, int> SignalKey;
QMultiHash<SignalKey, PythonQtSignalReceiver*> _signalReceivers;

//! the PythonQt python module
PythonQtObjectPtr _pythonQtModule;
Expand Down
Loading
Loading