aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libpyside/CMakeLists.txt5
-rw-r--r--libpyside/abstractqobjectconnection.cpp3
-rw-r--r--libpyside/dynamicqmetaobject.cpp155
-rw-r--r--libpyside/dynamicqmetaobject.h72
-rw-r--r--libpyside/proxyslot.cpp2
-rw-r--r--libpyside/proxyslot.h11
-rw-r--r--libpyside/signalmanager.cpp39
-rw-r--r--libpyside/signalmanager.h3
-rw-r--r--libpyside/signalslotconnection.cpp17
9 files changed, 275 insertions, 32 deletions
diff --git a/libpyside/CMakeLists.txt b/libpyside/CMakeLists.txt
index ad1ebffce..2c2aa4d68 100644
--- a/libpyside/CMakeLists.txt
+++ b/libpyside/CMakeLists.txt
@@ -1,12 +1,13 @@
project(libpyside)
set(libpyside_SRC
-typeresolver.cpp
-proxyslot.cpp
abstractqobjectconnection.cpp
+dynamicqmetaobject.cpp
+proxyslot.cpp
signalmanager.cpp
signalsignalconnection.cpp
signalslotconnection.cpp
+typeresolver.cpp
)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/libpyside/abstractqobjectconnection.cpp b/libpyside/abstractqobjectconnection.cpp
index 0f5a1b63a..65d47486e 100644
--- a/libpyside/abstractqobjectconnection.cpp
+++ b/libpyside/abstractqobjectconnection.cpp
@@ -35,6 +35,7 @@
#include "abstractqobjectconnection.h"
#include "typeresolver.h"
#include "signalmanager.h"
+#include <QDebug>
using namespace PySide;
@@ -50,7 +51,7 @@ 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]);
+ PyObject* arg = TypeResolver::get(m_signalArgs[i])->toPython(args[i]);
PyTuple_SET_ITEM(pyArgs, i, arg);
}
trigger(pyArgs);
diff --git a/libpyside/dynamicqmetaobject.cpp b/libpyside/dynamicqmetaobject.cpp
new file mode 100644
index 000000000..47baf6c82
--- /dev/null
+++ b/libpyside/dynamicqmetaobject.cpp
@@ -0,0 +1,155 @@
+/*
+* 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 "dynamicqmetaobject.h"
+#include <QByteArray>
+#include <QString>
+#include <QList>
+#include <QObject>
+#include <cstring>
+
+using namespace PySide;
+
+static int registerString(const QByteArray& s, QList<QByteArray>* strings)
+{
+ int idx = 0;
+ for (int i = 0; i < strings->count(); ++i) {
+ const QString &str = strings->at(i);
+ if (str == s)
+ return idx;
+ idx += str.length() + 1;
+ }
+ strings->append(s);
+ return idx;
+}
+
+DynamicQMetaObject::DynamicQMetaObject(const QObject* object) : m_originalMetaObject(object->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;
+ updateMetaObject();
+}
+
+DynamicQMetaObject::~DynamicQMetaObject()
+{
+ delete[] m_stringData;
+ delete[] m_data;
+}
+
+void DynamicQMetaObject::addSignal(const char* signal)
+{
+ m_signals << QByteArray(signal);
+ updateMetaObject();
+}
+
+void DynamicQMetaObject::addSlot(const char* slot)
+{
+ m_signals << QByteArray(slot);
+ updateMetaObject();
+}
+
+void DynamicQMetaObject::updateMetaObject()
+{
+ // these values are from moc source code, generator.cpp:66
+ enum MethodFlags {
+ AccessPrivate = 0x00,
+ AccessProtected = 0x01,
+ AccessPublic = 0x02,
+ MethodMethod = 0x00,
+ MethodSignal = 0x04,
+ MethodSlot = 0x08,
+ MethodConstructor = 0x0c,
+ MethodCompatibility = 0x10,
+ MethodCloned = 0x20,
+ MethodScriptable = 0x40
+ };
+
+ uint n_signals = m_signals.count();
+ uint n_methods = n_signals + m_slots.count();
+ int header[] = {2, // revision
+ 0, // class name index in m_metadata
+ 0, 0, // classinfo and classinfo index, not used by us
+ n_methods, 0, // method count and method list index
+ 0, 0, // prop count and prop indexes
+ 0, 0 // enum count and enum index
+ };
+
+ 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));
+
+ QList<QByteArray> strings;
+ registerString(m_originalMetaObject->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
+ }
+ //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
+ }
+ m_data[index++] = 0; // the end
+
+ // create the m_metadata string
+ QByteArray str;
+ foreach(QByteArray signature, strings) {
+ 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;
+}
diff --git a/libpyside/dynamicqmetaobject.h b/libpyside/dynamicqmetaobject.h
new file mode 100644
index 000000000..a7fb3b6f2
--- /dev/null
+++ b/libpyside/dynamicqmetaobject.h
@@ -0,0 +1,72 @@
+/*
+* 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 DYNAMICQMETAOBJECT_H
+#define DYNAMICQMETAOBJECT_H
+
+#include <QMetaObject>
+#include <QLinkedList>
+#include <QByteArray>
+
+class QObject;
+
+namespace PySide
+{
+
+class DynamicQMetaObject
+{
+public:
+ DynamicQMetaObject(const QObject* object);
+ ~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();
+};
+
+}
+#endif
diff --git a/libpyside/proxyslot.cpp b/libpyside/proxyslot.cpp
index 59467056f..885232574 100644
--- a/libpyside/proxyslot.cpp
+++ b/libpyside/proxyslot.cpp
@@ -40,7 +40,7 @@
using namespace PySide;
-ProxySlot::ProxySlot(QObject* signalSource) : m_signalSource(signalSource)
+ProxySlot::ProxySlot(const QObject* signalSource) : m_metaObject(signalSource), m_signalSource(signalSource)
{
m_nextSlotIndex = m_signalSource->metaObject()->methodCount()-1;
}
diff --git a/libpyside/proxyslot.h b/libpyside/proxyslot.h
index 8e45eff6f..c2334f799 100644
--- a/libpyside/proxyslot.h
+++ b/libpyside/proxyslot.h
@@ -34,6 +34,7 @@
#include <QObject>
#include <QHash>
+#include "dynamicqmetaobject.h"
namespace PySide
{
@@ -43,8 +44,13 @@ class AbstractQObjectConnection;
class ProxySlot : public QObject
{
public:
- ProxySlot(QObject* signalSource);
+ 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
@@ -69,7 +75,8 @@ protected:
int qt_metacall(QMetaObject::Call call, int id, void **args);
private:
- QObject* m_signalSource;
+ DynamicQMetaObject m_metaObject;
+ const QObject* m_signalSource;
int m_nextSlotIndex;
// slot_index => connection_info, used by qt_metacall
// to recover the connection_info
diff --git a/libpyside/signalmanager.cpp b/libpyside/signalmanager.cpp
index 711465549..e9f9b7c2b 100644
--- a/libpyside/signalmanager.cpp
+++ b/libpyside/signalmanager.cpp
@@ -75,11 +75,16 @@ QStringList PySide::getArgsFromSignature(const char* signature)
struct SignalManager::SignalManagerPrivate
{
- QHash<QObject*, ProxySlot*> m_proxies;
+ QHash<const QObject*, ProxySlot*> m_proxies;
- ProxySlot* findProxy(QObject* signalSource)
+ ProxySlot* findProxy(const QObject* signalSource) const
{
- ProxySlot* proxy = m_proxies.value(signalSource);
+ return m_proxies.value(signalSource);
+ }
+
+ ProxySlot* getProxy(const QObject* signalSource)
+ {
+ ProxySlot* proxy = findProxy(signalSource);
if (!proxy) {
proxy = new ProxySlot(signalSource);
m_proxies[signalSource] = proxy;
@@ -110,7 +115,9 @@ bool SignalManager::connect(QObject* source, const char* signal, PyObject* callb
return false;
signal++;
- ProxySlot* proxy = m_d->findProxy(source);
+ 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);
}
@@ -132,7 +139,7 @@ bool SignalManager::connect(QObject* source, const char* signal, QObject* receiv
receiver, slot_index, type);
} else {
// We have a python slot or signal
- ProxySlot* proxy = m_d->findProxy(source);
+ ProxySlot* proxy = m_d->getProxy(source);
AbstractQObjectConnection* connection = 0;
retval = proxy->connect(connection);
}
@@ -142,18 +149,14 @@ bool SignalManager::connect(QObject* source, const char* signal, QObject* receiv
bool SignalManager::emitSignal(QObject* source, const char* signal, PyObject* args)
{
- if (checkSignal(signal))
+ if (!checkSignal(signal))
return false;
+ signal++;
int argsGiven = PySequence_Size(args);
- //search native signal
- int signalIndex = source->metaObject()->indexOfSignal(signal+1);
- if (signalIndex == -1) {
- // dynamic signal
- qDebug() << "Dynamic signal not implemented yet!";
- } else {
- // a C++ signal
+ int signalIndex = source->metaObject()->indexOfSignal(signal);
+ if (signalIndex != -1) {
QStringList argTypes = getArgsFromSignature(signal);
void* signalArgs[argsGiven+1];
@@ -166,7 +169,15 @@ bool SignalManager::emitSignal(QObject* source, const char* signal, PyObject* ar
return false;
}
-void PySide::SignalManager::removeProxySlot(QObject* signalSource)
+void PySide::SignalManager::removeProxySlot(const QObject* signalSource)
{
m_d->m_proxies.remove(signalSource);
}
+
+const QMetaObject* PySide::SignalManager::getMetaObject(const QObject* object) const
+{
+ ProxySlot* proxy = m_d->findProxy(object);
+ if (proxy)
+ return proxy->dynamicQMetaObject()->metaObject();
+ return 0;
+}
diff --git a/libpyside/signalmanager.h b/libpyside/signalmanager.h
index 515ac6153..4e6fe6d9f 100644
--- a/libpyside/signalmanager.h
+++ b/libpyside/signalmanager.h
@@ -54,7 +54,8 @@ public:
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);
bool emitSignal(QObject* source, const char* signal, PyObject* args);
- void removeProxySlot(QObject* signalSource);
+ void removeProxySlot(const QObject* signalSource);
+ const QMetaObject* getMetaObject(const QObject* object) const;
private:
struct SignalManagerPrivate;
SignalManagerPrivate* m_d;
diff --git a/libpyside/signalslotconnection.cpp b/libpyside/signalslotconnection.cpp
index 8f7ddf17c..f6391682e 100644
--- a/libpyside/signalslotconnection.cpp
+++ b/libpyside/signalslotconnection.cpp
@@ -59,21 +59,15 @@ SignalSlotConnection::~SignalSlotConnection()
void SignalSlotConnection::trigger(PyObject* args)
{
- int useSelf = m_receiver ? 1 : 0;
- int numArgs = PySequence_Size(args);
- PyObject* preparedArgs = PyTuple_New(numArgs + useSelf);
+ Q_ASSERT(PySequence_Size(args) >= m_numSlotArgs);
+ const int useSelf = m_receiver ? 1 : 0;
+
+ PyObject* preparedArgs = PyTuple_New(m_numSlotArgs);
if (m_receiver)
PyTuple_SetItem(preparedArgs, 0, m_receiver);
- for (int i = 0; i < numArgs; ++i)
+ for (int i = 0; i < m_numSlotArgs; ++i)
PyTuple_SET_ITEM(preparedArgs, i + useSelf, PyTuple_GET_ITEM(args, i));
- qDebug() << "num args: " << m_numSlotArgs;
- // sliceamento
-// if (m_num_slot_args != -1 && m_num_slot_args < python::len(args)) {
-// args = python::list(args.slice(0, m_num_slot_args));
-// }
- qDebug() << "Receiver" << m_receiver;
- qDebug() << "numargs" << numArgs;
PyObject* retval = PyObject_CallObject(m_function, preparedArgs);
if (retval) {
Py_DECREF(retval);
@@ -81,4 +75,5 @@ void SignalSlotConnection::trigger(PyObject* args)
qWarning(qPrintable(QString("Error calling slot ")+
PyString_AS_STRING(reinterpret_cast<PyCodeObject*>(PyFunction_GET_CODE(m_function))->co_name)));
}
+ Py_DECREF(preparedArgs);
}