aboutsummaryrefslogtreecommitdiffstats
path: root/libpyside
diff options
context:
space:
mode:
authorHugo Lima <hugo.lima@openbossa.org>2009-12-23 16:50:19 -0200
committerHugo Lima <hugo.lima@openbossa.org>2009-12-30 14:35:45 -0200
commit73b5357057b7ca2a72806313877860488cce0854 (patch)
treeb5f91861de7f4ad420c93629799c0c74dcfcae34 /libpyside
parent750a56af8ac182147c63d7a29ec3aa987d0e0ed7 (diff)
Initial implementation of the new architeture for signal/slots.
Reviewed by Renato Araújo <renato.filho@openbossa.org>
Diffstat (limited to 'libpyside')
-rw-r--r--libpyside/CMakeLists.txt5
-rw-r--r--libpyside/abstractqobjectconnection.cpp58
-rw-r--r--libpyside/abstractqobjectconnection.h91
-rw-r--r--libpyside/dynamicqmetaobject.cpp62
-rw-r--r--libpyside/dynamicqmetaobject.h14
-rw-r--r--libpyside/globalreceiver.cpp (renamed from libpyside/signalslotconnection.cpp)79
-rw-r--r--libpyside/globalreceiver.h (renamed from libpyside/signalslotconnection.h)28
-rw-r--r--libpyside/proxyslot.h88
-rw-r--r--libpyside/signalmanager.cpp160
-rw-r--r--libpyside/signalmanager.h11
-rw-r--r--libpyside/signalsignalconnection.cpp51
-rw-r--r--libpyside/signalsignalconnection.h54
-rw-r--r--libpyside/typeresolver.cpp6
-rw-r--r--libpyside/typeresolver.h1
14 files changed, 194 insertions, 514 deletions
diff --git a/libpyside/CMakeLists.txt b/libpyside/CMakeLists.txt
index 2c2aa4d68..4a5049554 100644
--- a/libpyside/CMakeLists.txt
+++ b/libpyside/CMakeLists.txt
@@ -1,12 +1,9 @@
project(libpyside)
set(libpyside_SRC
-abstractqobjectconnection.cpp
dynamicqmetaobject.cpp
-proxyslot.cpp
signalmanager.cpp
-signalsignalconnection.cpp
-signalslotconnection.cpp
+globalreceiver.cpp
typeresolver.cpp
)
diff --git a/libpyside/abstractqobjectconnection.cpp b/libpyside/abstractqobjectconnection.cpp
deleted file mode 100644
index 1ecd5ae58..000000000
--- a/libpyside/abstractqobjectconnection.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-* This file is part of the Shiboken Python Bindings Generator project.
-*
-* Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-*
-* Contact: PySide team <contact@pyside.org>
-*
-* This program is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Lesser General Public License
-* version 2.1 as published by the Free Software Foundation. Please
-* review the following information to ensure the GNU Lesser General
-* Public License version 2.1 requirements will be met:
-* http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-*
-* As a special exception to the GNU Lesser General Public License
-* version 2.1, the object code form of a "work that uses the Library"
-* may incorporate material from a header file that is part of the
-* Library. You may distribute such object code under terms of your
-* choice, provided that the incorporated material (i) does not exceed
-* more than 5% of the total size of the Library; and (ii) is limited to
-* numerical parameters, data structure layouts, accessors, macros,
-* inline functions and templates.
-*
-* This program is distributed in the hope that it will be useful, but
-* WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this program; if not, write to the Free Software
-* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA
-*/
-
-#include "abstractqobjectconnection.h"
-#include "typeresolver.h"
-#include "signalmanager.h"
-#include <QDebug>
-
-using namespace PySide;
-
-AbstractQObjectConnection::AbstractQObjectConnection(QObject* source, const char* signal, Qt::ConnectionType connectionType)
- : m_source(source), m_connectionType(connectionType), m_slotIndex(-1)
-{
- m_signalArgs = getArgsFromSignature(signal);
- m_signalIndex = source->metaObject()->indexOfSignal(signal);
-}
-
-void AbstractQObjectConnection::trigger(void** args)
-{
- int numArgs = m_signalArgs.count();
- PyObject* pyArgs = PyTuple_New(numArgs);
- for (int i = 0; i < numArgs; ++i) {
- PyObject* arg = TypeResolver::get(m_signalArgs[i])->toPython(args[i+1]);
- PyTuple_SET_ITEM(pyArgs, i, arg);
- }
- trigger(pyArgs);
-}
diff --git a/libpyside/abstractqobjectconnection.h b/libpyside/abstractqobjectconnection.h
deleted file mode 100644
index 5ba43194c..000000000
--- a/libpyside/abstractqobjectconnection.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
-* This file is part of the Shiboken Python Bindings Generator project.
-*
-* Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-*
-* Contact: PySide team <contact@pyside.org>
-*
-* This program is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Lesser General Public License
-* version 2.1 as published by the Free Software Foundation. Please
-* review the following information to ensure the GNU Lesser General
-* Public License version 2.1 requirements will be met:
-* http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-*
-* As a special exception to the GNU Lesser General Public License
-* version 2.1, the object code form of a "work that uses the Library"
-* may incorporate material from a header file that is part of the
-* Library. You may distribute such object code under terms of your
-* choice, provided that the incorporated material (i) does not exceed
-* more than 5% of the total size of the Library; and (ii) is limited to
-* numerical parameters, data structure layouts, accessors, macros,
-* inline functions and templates.
-*
-* This program is distributed in the hope that it will be useful, but
-* WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this program; if not, write to the Free Software
-* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA
-*/
-
-#ifndef ABSTRACTQOBJECTCONNECTION_H
-#define ABSTRACTQOBJECTCONNECTION_H
-#include <Python.h>
-#include <Qt>
-#include <QStringList>
-
-class QObject;
-
-namespace PySide
-{
-class AbstractQObjectConnection
-{
-public:
- AbstractQObjectConnection(QObject* source, const char* signal, Qt::ConnectionType connectionType);
- virtual ~AbstractQObjectConnection() {}
-
- QObject* source() const
- {
- return m_source;
- }
- void setSignalIndex(int signalIndex)
- {
- m_signalIndex = signalIndex;
- }
-
- int signalIndex() const
- {
- return m_signalIndex;
- }
-
- void setSlotIndex(int slotIndex)
- {
- m_slotIndex = slotIndex;
- }
-
- int slotIndex() const
- {
- return m_slotIndex;
- }
-
- Qt::ConnectionType type() const
- {
- return m_connectionType;
- }
-
- void trigger(void** args);
- virtual void trigger(PyObject* args) = 0;
-private:
- QObject* m_source;
- QStringList m_signalArgs;
- Qt::ConnectionType m_connectionType;
- int m_signalIndex;
- int m_slotIndex;
-};
-}
-
-#endif
diff --git a/libpyside/dynamicqmetaobject.cpp b/libpyside/dynamicqmetaobject.cpp
index 47baf6c82..4cf249434 100644
--- a/libpyside/dynamicqmetaobject.cpp
+++ b/libpyside/dynamicqmetaobject.cpp
@@ -38,6 +38,7 @@
#include <QList>
#include <QObject>
#include <cstring>
+#include <QDebug>
using namespace PySide;
@@ -54,21 +55,19 @@ static int registerString(const QByteArray& s, QList<QByteArray>* strings)
return idx;
}
-DynamicQMetaObject::DynamicQMetaObject(const QObject* object) : m_originalMetaObject(object->metaObject())
+DynamicQMetaObject::DynamicQMetaObject(const QMetaObject* metaObject)
{
- m_metaObject.d.superdata = m_originalMetaObject;
- m_metaObject.d.stringdata = 0;
- m_metaObject.d.data = 0;
- m_metaObject.d.extradata = 0;
- m_stringData = 0;
- m_data = 0;
+ d.superdata = metaObject;
+ d.stringdata = 0;
+ d.data = 0;
+ d.extradata = 0;
updateMetaObject();
}
DynamicQMetaObject::~DynamicQMetaObject()
{
- delete[] m_stringData;
- delete[] m_data;
+ delete[] d.stringdata;
+ delete[] d.data;
}
void DynamicQMetaObject::addSignal(const char* signal)
@@ -79,7 +78,7 @@ void DynamicQMetaObject::addSignal(const char* signal)
void DynamicQMetaObject::addSlot(const char* slot)
{
- m_signals << QByteArray(slot);
+ m_slots << QByteArray(slot);
updateMetaObject();
}
@@ -112,32 +111,33 @@ void DynamicQMetaObject::updateMetaObject()
const int HEADER_LENGHT = sizeof(header)/sizeof(int);
header[5] = HEADER_LENGHT;
// header size + 5 indexes per method + an ending zero
- delete[] m_data;
- m_data = new uint[HEADER_LENGHT + n_methods*5 + 1];
- std::memcpy(m_data, header, sizeof(header));
+ delete[] d.data;
+ unsigned int* data;
+ data = new unsigned int[HEADER_LENGHT + n_methods*5 + 1];
+ std::memcpy(data, header, sizeof(header));
QList<QByteArray> strings;
- registerString(m_originalMetaObject->className(), &strings); // register class string
+ registerString(d.superdata->className(), &strings); // register class string
const int NULL_INDEX = registerString("", &strings); // register a null string
int index = HEADER_LENGHT;
//write signals
foreach(QByteArray signal, m_signals) {
- m_data[index++] = registerString(signal, &strings); // func name
- m_data[index++] = NULL_INDEX; // arguments
- m_data[index++] = NULL_INDEX; // normalized type
- m_data[index++] = NULL_INDEX; // tags
- m_data[index++] = AccessPublic | MethodSignal; // flags
+ data[index++] = registerString(signal, &strings); // func name
+ data[index++] = NULL_INDEX; // arguments
+ data[index++] = NULL_INDEX; // normalized type
+ data[index++] = NULL_INDEX; // tags
+ data[index++] = AccessPublic | MethodSignal; // flags
}
//write slots
foreach(QByteArray slot, m_slots) {
- m_data[index++] = registerString(slot, &strings); // func name
- m_data[index++] = NULL_INDEX; // arguments
- m_data[index++] = NULL_INDEX; // normalized type
- m_data[index++] = NULL_INDEX; // tags
- m_data[index++] = AccessPublic | MethodSlot; // flags
+ data[index++] = registerString(slot, &strings); // func name
+ data[index++] = NULL_INDEX; // arguments
+ data[index++] = NULL_INDEX; // normalized type
+ data[index++] = NULL_INDEX; // tags
+ data[index++] = AccessPublic | MethodSlot; // flags
}
- m_data[index++] = 0; // the end
+ data[index++] = 0; // the end
// create the m_metadata string
QByteArray str;
@@ -145,11 +145,9 @@ void DynamicQMetaObject::updateMetaObject()
str.append(signature);
str.append(char(0));
}
- delete[] m_stringData;
- m_stringData = new char[str.count()];
- std::copy(str.begin(), str.end(), m_stringData);
-
- // create metaobject
- m_metaObject.d.stringdata = m_stringData;
- m_metaObject.d.data = m_data;
+ delete[] d.stringdata;
+ char* stringData = new char[str.count()];
+ std::copy(str.begin(), str.end(), stringData);
+ d.data = data;
+ d.stringdata = stringData;
}
diff --git a/libpyside/dynamicqmetaobject.h b/libpyside/dynamicqmetaobject.h
index a7fb3b6f2..eca78af5f 100644
--- a/libpyside/dynamicqmetaobject.h
+++ b/libpyside/dynamicqmetaobject.h
@@ -35,6 +35,7 @@
#ifndef DYNAMICQMETAOBJECT_H
#define DYNAMICQMETAOBJECT_H
+#include "pysidemacros.h"
#include <QMetaObject>
#include <QLinkedList>
#include <QByteArray>
@@ -44,26 +45,17 @@ class QObject;
namespace PySide
{
-class DynamicQMetaObject
+class PYSIDE_API DynamicQMetaObject : public QMetaObject
{
public:
- DynamicQMetaObject(const QObject* object);
+ DynamicQMetaObject(const QMetaObject* metaObject);
~DynamicQMetaObject();
void addSignal(const char* signal);
void addSlot(const char* slot);
- const QMetaObject* metaObject() const
- {
- return &m_metaObject;
- }
private:
- const QMetaObject* m_originalMetaObject;
- QMetaObject m_metaObject;
-
QLinkedList<QByteArray> m_signals;
QLinkedList<QByteArray> m_slots;
- unsigned int* m_data;
- char* m_stringData;
void updateMetaObject();
};
diff --git a/libpyside/signalslotconnection.cpp b/libpyside/globalreceiver.cpp
index 125396345..880c2503d 100644
--- a/libpyside/signalslotconnection.cpp
+++ b/libpyside/globalreceiver.cpp
@@ -32,53 +32,68 @@
* 02110-1301 USA
*/
-#include "signalslotconnection.h"
+#include "globalreceiver.h"
+#include <QMetaMethod>
#include <QDebug>
+#include "signalmanager.h"
+#include <autodecref.h>
+#include "typeresolver.h"
using namespace PySide;
-SignalSlotConnection::SignalSlotConnection(QObject* source, const char* signal, PyObject* callback, Qt::ConnectionType connectionType)
- : AbstractQObjectConnection(source, signal, connectionType), m_receiver(0)
+GlobalReceiver::GlobalReceiver() : m_metaObject(&QObject::staticMetaObject)
{
- if (PyMethod_Check(callback)) {
- m_function = PyMethod_GET_FUNCTION(callback);
- if (PyObject* self = PyMethod_GET_SELF(callback))
- m_receiver = self;
- } else {
- m_function = callback;
- }
- Py_INCREF(m_function);
- PyCodeObject* objCode = reinterpret_cast<PyCodeObject*>(PyFunction_GET_CODE(m_function));
- m_numSlotArgs = objCode->co_flags & CO_VARARGS ? -1 : objCode->co_argcount;
}
-SignalSlotConnection::~SignalSlotConnection()
+GlobalReceiver::~GlobalReceiver()
+{
+ foreach(PyObject* obj, m_slotReceivers)
+ Py_DECREF(obj);
+}
+
+const QMetaObject* GlobalReceiver::metaObject() const
+{
+ return &m_metaObject;
+}
+
+void GlobalReceiver::addSlot(const char* slot, PyObject* callback)
{
- Py_DECREF(m_function);
+ m_metaObject.addSlot(slot);
+ int slotId = m_metaObject.indexOfSlot(slot);
+ Py_INCREF(callback);
+ m_slotReceivers[slotId] = callback;
+
+ Q_ASSERT(slotId >= QObject::staticMetaObject.methodCount());
}
-void SignalSlotConnection::trigger(PyObject* args)
+void GlobalReceiver::removeSlot(int slotId)
{
- Q_ASSERT(PySequence_Size(args) >= m_numSlotArgs);
+ PyObject* obj = m_slotReceivers.take(slotId);
+ Py_XDECREF(obj);
+}
- const int useSelf = m_receiver ? 1 : 0;
- int numSlotArgs = m_numSlotArgs;
+int GlobalReceiver::qt_metacall(QMetaObject::Call call, int id, void** args)
+{
+ Q_ASSERT(call == QMetaObject::InvokeMetaMethod);
+ Q_ASSERT(id >= QObject::staticMetaObject.methodCount());
+ QMetaMethod slot = m_metaObject.method(id);
+ Q_ASSERT(slot.methodType() == QMetaMethod::Slot);
+ QList<QByteArray> paramTypes = slot.parameterTypes();
- if (numSlotArgs == -1)
- numSlotArgs = PySequence_Size(args) + useSelf;
+ PyObject* callback = m_slotReceivers.value(id);
+ if (!callback) {
+ qWarning("Unknown global slot.");
+ return -1;
+ }
- PyObject* preparedArgs = PyTuple_New(numSlotArgs);
- if (m_receiver)
- PyTuple_SetItem(preparedArgs, 0, m_receiver);
- for (int i = 0, max = numSlotArgs - useSelf; i < max; ++i) {
- PyTuple_SET_ITEM(preparedArgs, i + useSelf, PyTuple_GET_ITEM(args, i));
+ Shiboken::AutoDecRef preparedArgs(PyTuple_New(paramTypes.count()));
+ for (int i = 0, max = paramTypes.count(); i < max; ++i) {
+ PyObject* arg = TypeResolver::get(paramTypes[i].constData())->toPython(args[i+1]);
+ PyTuple_SET_ITEM(preparedArgs.object(), i, arg);
}
- PyObject* retval = PyObject_CallObject(m_function, preparedArgs);
- if (retval) {
- Py_DECREF(retval);
- } else {
+ Shiboken::AutoDecRef retval(PyObject_CallObject(callback, preparedArgs));
+ if (!retval)
qWarning("Error calling slot");
- }
- Py_DECREF(preparedArgs);
+ return -1;
}
diff --git a/libpyside/signalslotconnection.h b/libpyside/globalreceiver.h
index 4c9015c98..32fc71539 100644
--- a/libpyside/signalslotconnection.h
+++ b/libpyside/globalreceiver.h
@@ -32,27 +32,31 @@
* 02110-1301 USA
*/
-#ifndef SIGNALSLOTCONNECTION_H
-#define SIGNALSLOTCONNECTION_H
+#ifndef GLOBALRECEIVER_H
+#define GLOBALRECEIVER_H
-#include "abstractqobjectconnection.h"
-
-class QObject;
+#include <Python.h>
+#include <QObject>
+#include <QHash>
+#include "dynamicqmetaobject.h"
namespace PySide
{
-class SignalSlotConnection : public AbstractQObjectConnection
+class GlobalReceiver : public QObject
{
public:
- SignalSlotConnection(QObject* source, const char* signal, PyObject* callback, Qt::ConnectionType connectionType);
- ~SignalSlotConnection();
- void trigger(PyObject* args);
+ GlobalReceiver();
+ ~GlobalReceiver();
+ int qt_metacall(QMetaObject::Call call, int id, void** args);
+ const QMetaObject* metaObject() const;
+ void addSlot(const char* slot, PyObject* callback);
+ void removeSlot(int slotId);
private:
- PyObject* m_receiver;
- PyObject* m_function;
- int m_numSlotArgs;
+ DynamicQMetaObject m_metaObject;
+ QHash<int, PyObject* > m_slotReceivers;
};
}
+
#endif
diff --git a/libpyside/proxyslot.h b/libpyside/proxyslot.h
deleted file mode 100644
index c2334f799..000000000
--- a/libpyside/proxyslot.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
-* This file is part of the Shiboken Python Bindings Generator project.
-*
-* Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-*
-* Contact: PySide team <contact@pyside.org>
-*
-* This program is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Lesser General Public License
-* version 2.1 as published by the Free Software Foundation. Please
-* review the following information to ensure the GNU Lesser General
-* Public License version 2.1 requirements will be met:
-* http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-*
-* As a special exception to the GNU Lesser General Public License
-* version 2.1, the object code form of a "work that uses the Library"
-* may incorporate material from a header file that is part of the
-* Library. You may distribute such object code under terms of your
-* choice, provided that the incorporated material (i) does not exceed
-* more than 5% of the total size of the Library; and (ii) is limited to
-* numerical parameters, data structure layouts, accessors, macros,
-* inline functions and templates.
-*
-* This program is distributed in the hope that it will be useful, but
-* WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this program; if not, write to the Free Software
-* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA
-*/
-
-#include <QObject>
-#include <QHash>
-#include "dynamicqmetaobject.h"
-
-namespace PySide
-{
-
-class AbstractQObjectConnection;
-
-class ProxySlot : public QObject
-{
-public:
- ProxySlot(const QObject* signalSource);
- bool connect(AbstractQObjectConnection* connection);
- DynamicQMetaObject* dynamicQMetaObject()
- {
- return &m_metaObject;
- }
-
-protected:
- /**
- * Qt's meta-object system uses the qt_metacall() function to access the
- * meta-information for a particular QObject object (its signals, slots,
- * properties, etc.).
- *
- * About the implemmentation
- *
- * The call may indicate access to the meta-object of the QObject base
- * class, we need to take care of this use case.
- * If the QObject::qt_metacall() call returns -1, this means that the
- * metacall has been handled by QObject and that there is nothing to do.
- * In that case, we return immediately. Similarly, if the metacall isn't
- * a slot invocation, we follow QObject's convention and return an
- * identifier that can be handled by a subclass.
- *
- * If all goes well, we invoke the specified slot and return -1 to
- * indicate that the metacall has been processed.
- *
- * \see \link http://doc.trolltech.com/qq/qq16-dynamicqobject.html
- */
- int qt_metacall(QMetaObject::Call call, int id, void **args);
-
-private:
- DynamicQMetaObject m_metaObject;
- const QObject* m_signalSource;
- int m_nextSlotIndex;
- // slot_index => connection_info, used by qt_metacall
- // to recover the connection_info
- QHash<int, AbstractQObjectConnection*> m_connections;
-
- void attachAbstractConnection(AbstractQObjectConnection* connection);
-};
-
-} \ No newline at end of file
diff --git a/libpyside/signalmanager.cpp b/libpyside/signalmanager.cpp
index 464e49410..a222e0371 100644
--- a/libpyside/signalmanager.cpp
+++ b/libpyside/signalmanager.cpp
@@ -33,10 +33,13 @@
*/
#include "signalmanager.h"
-#include "proxyslot.h"
+
#include <QHash>
#include <QStringList>
+#include <QMetaMethod>
+#include <autodecref.h>
#include <QDebug>
+#include <limits>
#if QSLOT_CODE != 1 || QSIGNAL_CODE != 2
#error QSLOT_CODE and/or QSIGNAL_CODE changed! change the hardcoded stuff to the correct value!
@@ -44,12 +47,16 @@
#define PYSIDE_SLOT '1'
#define PYSIDE_SIGNAL '2'
#include "typeresolver.h"
-#include "signalslotconnection.h"
-#include "signalsignalconnection.h"
+#include "globalreceiver.h"
using namespace PySide;
-static bool checkSignal(const char* signal)
+bool PySide::isSignal(const char* signal)
+{
+ return signal[0] == PYSIDE_SIGNAL;
+}
+
+bool PySide::checkSignal(const char* signal)
{
if (signal[0] != PYSIDE_SIGNAL) {
PyErr_SetString(PyExc_TypeError, "Use the function PySide.QtCore.SIGNAL on signals");
@@ -58,6 +65,33 @@ static bool checkSignal(const char* signal)
return true;
}
+QString PySide::getCallbackSignature(const char* signal, PyObject* callback)
+{
+ PyObject* function;
+ int useSelf = PyMethod_Check(callback);
+ if (useSelf) {
+ function = PyMethod_GET_FUNCTION(callback);
+ } else {
+ function = callback;
+ }
+
+ PyCodeObject* objCode = reinterpret_cast<PyCodeObject*>(PyFunction_GET_CODE(function));
+ QString signature(PyString_AS_STRING(objCode->co_name));
+ signature.append(QString::number(quint64(callback), 16));
+ signature.append('(');
+ int numArgs = objCode->co_flags & CO_VARARGS ? -1 : objCode->co_argcount;
+
+ QStringList args = getArgsFromSignature(signal);
+ if (numArgs == -1)
+ numArgs = std::numeric_limits<int>::max();
+ while (args.count() > numArgs - useSelf) {
+ args.removeLast();
+ }
+ signature.append(args.join(","));
+ signature.append(')');
+ return signature;
+}
+
QStringList PySide::getArgsFromSignature(const char* signature)
{
QString qsignature(signature);
@@ -76,23 +110,7 @@ QStringList PySide::getArgsFromSignature(const char* signature)
struct SignalManager::SignalManagerPrivate
{
- QHash<const QObject*, ProxySlot*> m_proxies;
-
- ProxySlot* findProxy(const QObject* signalSource) const
- {
- return m_proxies.value(signalSource);
- }
-
- ProxySlot* getProxy(const QObject* signalSource)
- {
- ProxySlot* proxy = findProxy(signalSource);
- if (!proxy) {
- proxy = new ProxySlot(signalSource);
- m_proxies[signalSource] = proxy;
- QObject::connect(signalSource, SIGNAL(destroyed()), proxy, SLOT(deleteLater()));
- }
- return proxy;
- }
+ GlobalReceiver m_globalReceiver;
};
SignalManager::SignalManager() : m_d(new SignalManagerPrivate)
@@ -110,57 +128,14 @@ SignalManager& SignalManager::instance()
return me;
}
-bool SignalManager::connect(QObject* source, const char* signal, PyObject* callback, Qt::ConnectionType type)
+QObject* SignalManager::globalReceiver()
{
- if (!checkSignal(signal))
- return false;
- signal++;
-
- ProxySlot* proxy = m_d->getProxy(source);
- if (source->metaObject()->indexOfSignal(signal) == -1)
- proxy->dynamicQMetaObject()->addSignal(signal);
- AbstractQObjectConnection* connection = new SignalSlotConnection(source, signal, callback, type);
- return proxy->connect(connection);
+ return &m_d->m_globalReceiver;
}
-bool SignalManager::connect(QObject* source, const char* signal, QObject* receiver, const char* slot, Qt::ConnectionType type)
+void SignalManager::addGlobalSlot(const char* slot, PyObject* callback)
{
- if (!checkSignal(signal))
- return false;
- signal++;
-
- if (!QMetaObject::checkConnectArgs(signal, slot))
- return false;
-
- // Check if is a dynamic signal
- ProxySlot* proxy = m_d->getProxy(source);
- int signalIndex = source->metaObject()->indexOfSignal(signal);
- if (signalIndex == -1) {
- proxy->dynamicQMetaObject()->addSignal(signal);
- signalIndex = source->metaObject()->indexOfSignal(signal);
- }
-
- int slotIndex;
- bool slotIsSignal = checkSignal(slot);
- slot++;
- // Signal -> Signal connection
- if (slotIsSignal) {
- slotIndex = receiver->metaObject()->indexOfSignal(slot);
- if (slotIndex == -1) {
- ProxySlot* proxy = m_d->getProxy(receiver);
- proxy->dynamicQMetaObject()->addSignal(slot);
- slotIndex = receiver->metaObject()->indexOfSignal(slot);
- }
- AbstractQObjectConnection* connection = new SignalSignalConnection(source, signal, receiver, slot, type);
- proxy->connect(connection);
- } else {
- // Signal -> Slot connection
- slotIndex = receiver->metaObject()->indexOfSlot(slot);
- if (slotIndex == -1)
- return false;
- }
-
- return QMetaObject::connect(source, signalIndex, receiver, slotIndex, type);
+ m_d->m_globalReceiver.addSlot(slot, callback);
}
bool SignalManager::emitSignal(QObject* source, const char* signal, PyObject* args)
@@ -174,25 +149,56 @@ bool SignalManager::emitSignal(QObject* source, const char* signal, PyObject* ar
int signalIndex = source->metaObject()->indexOfSignal(signal);
if (signalIndex != -1) {
QStringList argTypes = getArgsFromSignature(signal);
+ if (argsGiven > argTypes.count()) {
+ PyErr_SetString(PyExc_TypeError, "Too many arguments for this signal.");
+ return false;
+ }
void* signalArgs[argsGiven+1];
signalArgs[0] = 0;
for (int i = 0; i < argsGiven; ++i)
signalArgs[i+1] = TypeResolver::get(argTypes[i])->toCpp(PySequence_GetItem(args, i));
QMetaObject::activate(source, signalIndex, signalArgs);
+ // FIXME: This will cause troubles with non-direct connections.
+ for (int i = 0; i < argsGiven; ++i)
+ TypeResolver::get(argTypes[i])->deleteObject(signalArgs[i+1]);
return true;
}
return false;
}
-void PySide::SignalManager::removeProxySlot(const QObject* signalSource)
+int PySide::SignalManager::qt_metacall(QObject* object, QMetaObject::Call call, int id, void** args)
{
- m_d->m_proxies.remove(signalSource);
-}
+ const QMetaObject* metaObject = object->metaObject();
+ // only meta method invocation is supported right now.
+ if (call != QMetaObject::InvokeMetaMethod) {
+ qWarning("Only meta method invocation is supported right now by PySide.");
+ return id - metaObject->methodCount();
+ }
+ QMetaMethod method = metaObject->method(id);
-const QMetaObject* PySide::SignalManager::getMetaObject(const QObject* object) const
-{
- ProxySlot* proxy = m_d->findProxy(object);
- if (proxy)
- return proxy->dynamicQMetaObject()->metaObject();
- return 0;
+ if (method.methodType() == QMetaMethod::Signal) {
+ // emit python signal
+ QMetaObject::activate(object, id, args);
+ } else {
+ // call python slot
+ QList<QByteArray> paramTypes = method.parameterTypes();
+ PyObject* self = Shiboken::BindingManager::instance().retrieveWrapper(object);
+ Shiboken::AutoDecRef preparedArgs(PyTuple_New(paramTypes.count()+1));
+
+ PyTuple_SET_ITEM(preparedArgs.object(), 0, self);
+ for (int i = 0, max = paramTypes.count(); i < max; ++i) {
+ PyObject* arg = TypeResolver::get(paramTypes[i].constData())->toPython(args[i+1]);
+ PyTuple_SET_ITEM(preparedArgs.object(), i + 1, arg);
+ }
+
+ QString methodName = method.signature();
+ methodName = methodName.left(methodName.indexOf('('));
+
+ Shiboken::AutoDecRef pyMethodName(PyString_FromString(qPrintable(methodName)));
+ Shiboken::AutoDecRef pyMethod(PyObject_GetAttr(self, pyMethodName));
+ Shiboken::AutoDecRef retval(PyObject_CallObject(pyMethod, preparedArgs));
+ if (!retval)
+ qWarning("Error calling slot");
+ }
+ return -1;
}
diff --git a/libpyside/signalmanager.h b/libpyside/signalmanager.h
index 4e6fe6d9f..14ade8a6d 100644
--- a/libpyside/signalmanager.h
+++ b/libpyside/signalmanager.h
@@ -45,17 +45,20 @@ class QObject;
namespace PySide
{
+PYSIDE_API bool isSignal(const char* signal);
+PYSIDE_API bool checkSignal(const char* signal);
+PYSIDE_API QString getCallbackSignature(const char* signal, PyObject* callback);
QStringList getArgsFromSignature(const char* signature);
class PYSIDE_API SignalManager
{
public:
static SignalManager& instance();
- bool connect(QObject* source, const char* signal, PyObject* callback, Qt::ConnectionType type = Qt::AutoConnection);
- bool connect(QObject* source, const char* signal, QObject* receiver, const char* slot, Qt::ConnectionType type = Qt::AutoConnection);
+ QObject* globalReceiver();
bool emitSignal(QObject* source, const char* signal, PyObject* args);
- void removeProxySlot(const QObject* signalSource);
- const QMetaObject* getMetaObject(const QObject* object) const;
+
+ static int qt_metacall(QObject* object, QMetaObject::Call call, int id, void** args);
+ void addGlobalSlot(const char* slot, PyObject* callback);
private:
struct SignalManagerPrivate;
SignalManagerPrivate* m_d;
diff --git a/libpyside/signalsignalconnection.cpp b/libpyside/signalsignalconnection.cpp
deleted file mode 100644
index 2a03dfe3b..000000000
--- a/libpyside/signalsignalconnection.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
-* This file is part of the Shiboken Python Bindings Generator project.
-*
-* Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-*
-* Contact: PySide team <contact@pyside.org>
-*
-* This program is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Lesser General Public License
-* version 2.1 as published by the Free Software Foundation. Please
-* review the following information to ensure the GNU Lesser General
-* Public License version 2.1 requirements will be met:
-* http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-*
-* As a special exception to the GNU Lesser General Public License
-* version 2.1, the object code form of a "work that uses the Library"
-* may incorporate material from a header file that is part of the
-* Library. You may distribute such object code under terms of your
-* choice, provided that the incorporated material (i) does not exceed
-* more than 5% of the total size of the Library; and (ii) is limited to
-* numerical parameters, data structure layouts, accessors, macros,
-* inline functions and templates.
-*
-* This program is distributed in the hope that it will be useful, but
-* WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this program; if not, write to the Free Software
-* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA
-*/
-
-#include "signalsignalconnection.h"
-#include <QDebug>
-#include "signalmanager.h"
-
-using namespace PySide;
-
-SignalSignalConnection::SignalSignalConnection(QObject* source, const char* signal, QObject* receiver, const char* otherSignal, Qt::ConnectionType connectionType)
- : AbstractQObjectConnection(source, signal, connectionType), m_receiver(receiver), m_signal(otherSignal)
-{
- m_signal.prepend('2');
-}
-
-void SignalSignalConnection::trigger(PyObject* args)
-{
- SignalManager::instance().emitSignal(m_receiver, m_signal.constData(), args);
-}
-
diff --git a/libpyside/signalsignalconnection.h b/libpyside/signalsignalconnection.h
deleted file mode 100644
index e444ed101..000000000
--- a/libpyside/signalsignalconnection.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
-* This file is part of the Shiboken Python Bindings Generator project.
-*
-* Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-*
-* Contact: PySide team <contact@pyside.org>
-*
-* This program is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Lesser General Public License
-* version 2.1 as published by the Free Software Foundation. Please
-* review the following information to ensure the GNU Lesser General
-* Public License version 2.1 requirements will be met:
-* http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-*
-* As a special exception to the GNU Lesser General Public License
-* version 2.1, the object code form of a "work that uses the Library"
-* may incorporate material from a header file that is part of the
-* Library. You may distribute such object code under terms of your
-* choice, provided that the incorporated material (i) does not exceed
-* more than 5% of the total size of the Library; and (ii) is limited to
-* numerical parameters, data structure layouts, accessors, macros,
-* inline functions and templates.
-*
-* This program is distributed in the hope that it will be useful, but
-* WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this program; if not, write to the Free Software
-* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA
-*/
-
-#ifndef SIGNALSIGNALCONNECTION_H
-#define SIGNALSIGNALCONNECTION_H
-#include "abstractqobjectconnection.h"
-
-namespace PySide
-{
-
-class SignalSignalConnection : public AbstractQObjectConnection
-{
-public:
- SignalSignalConnection(QObject* source, const char* signal, QObject* receiver, const char* otherSignal, Qt::ConnectionType connectionType);
- virtual void trigger(PyObject* args);
-private:
- QObject* m_receiver;
- QByteArray m_signal;
-};
-
-}
-
-#endif
diff --git a/libpyside/typeresolver.cpp b/libpyside/typeresolver.cpp
index d4c704ab9..49ca19f75 100644
--- a/libpyside/typeresolver.cpp
+++ b/libpyside/typeresolver.cpp
@@ -116,3 +116,9 @@ PyObject* TypeResolver::toPython(void* cppObj)
return m_d->cppToPython(cppObj);
}
+void TypeResolver::deleteObject(void* object)
+{
+ if (m_d->deleteObject)
+ m_d->deleteObject(object);
+}
+
diff --git a/libpyside/typeresolver.h b/libpyside/typeresolver.h
index 25ccfdf7f..84191f578 100644
--- a/libpyside/typeresolver.h
+++ b/libpyside/typeresolver.h
@@ -89,6 +89,7 @@ public:
const char* typeName() const;
PyObject* toPython(void* cppObj);
void* toCpp(PyObject* pyObj);
+ void deleteObject(void* object);
private:
struct TypeResolverPrivate;
TypeResolverPrivate* m_d;