aboutsummaryrefslogtreecommitdiffstats
path: root/libpyside
diff options
context:
space:
mode:
Diffstat (limited to 'libpyside')
-rw-r--r--libpyside/dynamicqmetaobject.cpp15
-rw-r--r--libpyside/dynamicqmetaobject.h4
-rw-r--r--libpyside/globalreceiver.cpp92
-rw-r--r--libpyside/globalreceiver.h6
-rw-r--r--libpyside/signalmanager.cpp10
-rw-r--r--libpyside/signalmanager.h3
6 files changed, 120 insertions, 10 deletions
diff --git a/libpyside/dynamicqmetaobject.cpp b/libpyside/dynamicqmetaobject.cpp
index 40e74ce67..083f1d666 100644
--- a/libpyside/dynamicqmetaobject.cpp
+++ b/libpyside/dynamicqmetaobject.cpp
@@ -39,6 +39,7 @@
#include <QObject>
#include <cstring>
#include <QDebug>
+#include <QMetaMethod>
using namespace PySide;
@@ -83,6 +84,20 @@ void DynamicQMetaObject::addSlot(const char* slot)
updateMetaObject();
}
+void DynamicQMetaObject::removeSlot(uint index)
+{
+ QMetaMethod m = method(index);
+ if (m_slots.removeAll(m.signature()))
+ updateMetaObject();
+}
+
+void DynamicQMetaObject::removeSignal(uint index)
+{
+ QMetaMethod m = method(index);
+ if (m_signals.removeAll(m.signature()))
+ updateMetaObject();
+}
+
void DynamicQMetaObject::updateMetaObject()
{
// these values are from moc source code, generator.cpp:66
diff --git a/libpyside/dynamicqmetaobject.h b/libpyside/dynamicqmetaobject.h
index 572d3b444..557ebe146 100644
--- a/libpyside/dynamicqmetaobject.h
+++ b/libpyside/dynamicqmetaobject.h
@@ -50,9 +50,13 @@ class PYSIDE_API DynamicQMetaObject : public QMetaObject
public:
DynamicQMetaObject(const char* className, const QMetaObject* metaObject);
~DynamicQMetaObject();
+
void addSignal(const char* signal);
void addSlot(const char* slot);
+ void removeSignal(uint idex);
+ void removeSlot(uint index);
+
private:
QLinkedList<QByteArray> m_signals;
QLinkedList<QByteArray> m_slots;
diff --git a/libpyside/globalreceiver.cpp b/libpyside/globalreceiver.cpp
index 0d6ce7cf2..333268081 100644
--- a/libpyside/globalreceiver.cpp
+++ b/libpyside/globalreceiver.cpp
@@ -39,16 +39,87 @@
#include <autodecref.h>
#include "typeresolver.h"
+
+namespace PySide
+{
+
+class DynamicSlotData
+{
+ public:
+ DynamicSlotData(PyObject *callback);
+ void incRef();
+ void decRef();
+ int refCount() const;
+ PyObject *callback() const;
+ ~DynamicSlotData();
+
+ private:
+ int m_refCount;
+ PyObject *m_callback;
+};
+
+}
+
using namespace PySide;
-GlobalReceiver::GlobalReceiver() : m_metaObject("GlobalReceiver", &QObject::staticMetaObject)
+DynamicSlotData::DynamicSlotData(PyObject *callback)
+ : m_refCount(0)
+{
+ m_callback = callback;
+ Py_INCREF(callback);
+}
+
+void DynamicSlotData::incRef()
+{
+ m_refCount++;
+}
+
+void DynamicSlotData::decRef()
+{
+ m_refCount--;
+}
+
+int DynamicSlotData::refCount() const
+{
+ return m_refCount;
+}
+
+PyObject *DynamicSlotData::callback() const
+{
+ return m_callback;
+}
+
+DynamicSlotData::~DynamicSlotData()
+{
+ Py_XDECREF(m_callback);
+}
+
+
+GlobalReceiver::GlobalReceiver()
+ : m_metaObject("GlobalReceiver", &QObject::staticMetaObject)
{
}
GlobalReceiver::~GlobalReceiver()
{
- foreach(PyObject* obj, m_slotReceivers)
- Py_DECREF(obj);
+ foreach(DynamicSlotData* data, m_slotReceivers)
+ delete data;
+}
+
+void GlobalReceiver::connectNotify(int slotId)
+{
+ if (m_slotReceivers.contains(slotId))
+ m_slotReceivers[slotId]->incRef();
+}
+
+void GlobalReceiver::disconnectNotify(int slotId)
+{
+ if (m_slotReceivers.contains(slotId)) {
+ DynamicSlotData *data = m_slotReceivers[slotId];
+ data->decRef();
+ if (data->refCount() == 0)
+ removeSlot(slotId);
+ }
}
const QMetaObject* GlobalReceiver::metaObject() const
@@ -60,8 +131,9 @@ void GlobalReceiver::addSlot(const char* slot, PyObject* callback)
{
m_metaObject.addSlot(slot);
int slotId = m_metaObject.indexOfSlot(slot);
- Py_INCREF(callback);
- m_slotReceivers[slotId] = callback;
+ if (!m_slotReceivers.contains(slotId)) {
+ m_slotReceivers[slotId] = new DynamicSlotData(callback);
+ }
bool isShortCircuit = true;
for (int i = 0; slot[i]; ++i) {
@@ -78,8 +150,9 @@ void GlobalReceiver::addSlot(const char* slot, PyObject* callback)
void GlobalReceiver::removeSlot(int slotId)
{
- PyObject* obj = m_slotReceivers.take(slotId);
- Py_XDECREF(obj);
+ delete m_slotReceivers.take(slotId);
+ m_metaObject.removeSlot(slotId);
+ m_shortCircuitSlots.remove(slotId);
}
int GlobalReceiver::qt_metacall(QMetaObject::Call call, int id, void** args)
@@ -89,14 +162,15 @@ int GlobalReceiver::qt_metacall(QMetaObject::Call call, int id, void** args)
QMetaMethod slot = m_metaObject.method(id);
Q_ASSERT(slot.methodType() == QMetaMethod::Slot);
- PyObject* callback = m_slotReceivers.value(id);
- if (!callback) {
+ DynamicSlotData* data = m_slotReceivers.value(id);
+ if (!data) {
qWarning() << "Unknown global slot, id:" << id;
return -1;
}
int numArgs;
PyObject* retval = 0;
+ PyObject* callback = data->callback();
if (m_shortCircuitSlots.contains(id)) {
retval = PyObject_CallObject(callback, reinterpret_cast<PyObject*>(args[1]));
} else {
diff --git a/libpyside/globalreceiver.h b/libpyside/globalreceiver.h
index e1e230b7b..9243f9d3f 100644
--- a/libpyside/globalreceiver.h
+++ b/libpyside/globalreceiver.h
@@ -44,6 +44,8 @@
namespace PySide
{
+class DynamicSlotData;
+
class GlobalReceiver : public QObject
{
public:
@@ -53,10 +55,12 @@ public:
const QMetaObject* metaObject() const;
void addSlot(const char* slot, PyObject* callback);
void removeSlot(int slotId);
+ void connectNotify(int slotId);
+ void disconnectNotify(int slotId);
private:
DynamicQMetaObject m_metaObject;
- QHash<int, PyObject* > m_slotReceivers;
QSet<int> m_shortCircuitSlots;
+ QHash<int, DynamicSlotData* > m_slotReceivers;
};
}
diff --git a/libpyside/signalmanager.cpp b/libpyside/signalmanager.cpp
index c8b55e77f..99b2e5ae4 100644
--- a/libpyside/signalmanager.cpp
+++ b/libpyside/signalmanager.cpp
@@ -164,6 +164,16 @@ QObject* SignalManager::globalReceiver()
return &m_d->m_globalReceiver;
}
+void SignalManager::globalReceiverConnectNotify(int slotIndex)
+{
+ m_d->m_globalReceiver.connectNotify(slotIndex);
+}
+
+void SignalManager::globalReceiverDisconnectNotify(int slotIndex)
+{
+ m_d->m_globalReceiver.disconnectNotify(slotIndex);
+}
+
void SignalManager::addGlobalSlot(const char* slot, PyObject* callback)
{
m_d->m_globalReceiver.addSlot(slot, callback);
diff --git a/libpyside/signalmanager.h b/libpyside/signalmanager.h
index 870aecdfe..60888ee0c 100644
--- a/libpyside/signalmanager.h
+++ b/libpyside/signalmanager.h
@@ -59,6 +59,9 @@ public:
static int qt_metacall(QObject* object, QMetaObject::Call call, int id, void** args);
void addGlobalSlot(const char* slot, PyObject* callback);
+
+ void globalReceiverConnectNotify(int slotIndex);
+ void globalReceiverDisconnectNotify(int slotIndex);
private:
struct SignalManagerPrivate;
SignalManagerPrivate* m_d;