Implemented support to modify slot return type.
Included method type in DynamicQMetaObject metadata. Moved Signal/Slot objet to libpyside. Create unittest to signal class. Implemented disconnection function. Fixed emit method on signal object
This commit is contained in:
parent
d2a6f35ef9
commit
c5fd4d4830
11 changed files with 710 additions and 48 deletions
|
|
@ -718,9 +718,11 @@
|
||||||
<enum-type name="QMetaMethod::MethodType"/>
|
<enum-type name="QMetaMethod::MethodType"/>
|
||||||
|
|
||||||
<!--signal/slot-->
|
<!--signal/slot-->
|
||||||
<inject-code class="native" position="beginning" file="glue/qslot.cpp" />
|
|
||||||
<inject-code class="target" position="end">
|
<inject-code class="target" position="end">
|
||||||
init_slot(module);
|
PySide::init(module);
|
||||||
|
</inject-code>
|
||||||
|
<inject-code class="native" position="beginning">
|
||||||
|
#include <pyside.h>
|
||||||
</inject-code>
|
</inject-code>
|
||||||
|
|
||||||
<object-type name="QAbstractTableModel">
|
<object-type name="QAbstractTableModel">
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,9 @@ set(libpyside_SRC
|
||||||
dynamicqmetaobject.cpp
|
dynamicqmetaobject.cpp
|
||||||
signalmanager.cpp
|
signalmanager.cpp
|
||||||
globalreceiver.cpp
|
globalreceiver.cpp
|
||||||
|
qsignal.cpp
|
||||||
|
qslot.cpp
|
||||||
|
pyside.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
|
@ -31,6 +34,7 @@ set(libpyside_HEADERS
|
||||||
pysideconversions.h
|
pysideconversions.h
|
||||||
pysidemacros.h
|
pysidemacros.h
|
||||||
signalmanager.h
|
signalmanager.h
|
||||||
|
pyside.h
|
||||||
)
|
)
|
||||||
|
|
||||||
# create pkg-config file
|
# create pkg-config file
|
||||||
|
|
|
||||||
|
|
@ -35,12 +35,15 @@
|
||||||
#include "dynamicqmetaobject.h"
|
#include "dynamicqmetaobject.h"
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <QStringList>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QMetaMethod>
|
#include <QMetaMethod>
|
||||||
|
|
||||||
|
#include "qsignal.h"
|
||||||
|
|
||||||
#define MAX_SIGNALS_COUNT 50
|
#define MAX_SIGNALS_COUNT 50
|
||||||
|
|
||||||
using namespace PySide;
|
using namespace PySide;
|
||||||
|
|
@ -58,11 +61,32 @@ static int registerString(const QByteArray& s, QList<QByteArray>* strings)
|
||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clearItem(QLinkedList<QByteArray> &l, const QByteArray &value)
|
MethodData::MethodData(const char *signature, const char *type)
|
||||||
|
: m_signature(signature), m_type(type)
|
||||||
{
|
{
|
||||||
QLinkedList<QByteArray>::iterator i = qFind(l.begin(), l.end(), value);
|
}
|
||||||
if (i != l.end())
|
|
||||||
*i = QByteArray();
|
void MethodData::clear()
|
||||||
|
{
|
||||||
|
m_signature.clear();
|
||||||
|
m_type.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MethodData::operator==(const MethodData &other) const
|
||||||
|
{
|
||||||
|
return m_signature == other.signature();
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray MethodData::signature() const
|
||||||
|
{
|
||||||
|
return m_signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray MethodData::type() const
|
||||||
|
{
|
||||||
|
if (m_type == "void")
|
||||||
|
return QByteArray("");
|
||||||
|
return m_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicQMetaObject::DynamicQMetaObject(const char *className, const QMetaObject* metaObject)
|
DynamicQMetaObject::DynamicQMetaObject(const char *className, const QMetaObject* metaObject)
|
||||||
|
|
@ -81,13 +105,13 @@ DynamicQMetaObject::~DynamicQMetaObject()
|
||||||
delete[] d.data;
|
delete[] d.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DynamicQMetaObject::addSignal(const char* signal)
|
void DynamicQMetaObject::addSignal(const char *signal, const char *type)
|
||||||
{
|
{
|
||||||
//search for a empty space
|
//search for a empty space
|
||||||
QByteArray blank;
|
MethodData blank;
|
||||||
QLinkedList<QByteArray>::iterator i = qFind(m_signals.begin(), m_signals.end(), blank);
|
QLinkedList<MethodData>::iterator i = qFind(m_signals.begin(), m_signals.end(), blank);
|
||||||
if (i != m_signals.end()) {
|
if (i != m_signals.end()) {
|
||||||
*i = QByteArray(signal);
|
*i = MethodData(signal, type);
|
||||||
updateMetaObject();
|
updateMetaObject();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -97,19 +121,19 @@ void DynamicQMetaObject::addSignal(const char* signal)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_signals << QByteArray(signal);
|
m_signals << MethodData(signal, type);
|
||||||
updateMetaObject();
|
updateMetaObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DynamicQMetaObject::addSlot(const char* slot)
|
void DynamicQMetaObject::addSlot(const char *slot, const char *type)
|
||||||
{
|
{
|
||||||
//search for a empty space
|
//search for a empty space
|
||||||
QByteArray blank;
|
MethodData blank;
|
||||||
QLinkedList<QByteArray>::iterator i = qFind(m_slots.begin(), m_slots.end(), blank);
|
QLinkedList<MethodData>::iterator i = qFind(m_slots.begin(), m_slots.end(), blank);
|
||||||
if (i != m_slots.end()) {
|
if (i != m_slots.end()) {
|
||||||
*i = QByteArray(slot);
|
*i = MethodData(slot, type);
|
||||||
} else {
|
} else {
|
||||||
m_slots << QByteArray(slot);
|
m_slots << MethodData(slot, type);
|
||||||
}
|
}
|
||||||
updateMetaObject();
|
updateMetaObject();
|
||||||
}
|
}
|
||||||
|
|
@ -117,13 +141,16 @@ void DynamicQMetaObject::addSlot(const char* slot)
|
||||||
void DynamicQMetaObject::removeSlot(uint index)
|
void DynamicQMetaObject::removeSlot(uint index)
|
||||||
{
|
{
|
||||||
QMetaMethod m = method(index);
|
QMetaMethod m = method(index);
|
||||||
if (m_slots.contains(m.signature())) {
|
foreach(MethodData md, m_slots) {
|
||||||
clearItem(m_slots, m.signature());
|
if (md.signature() == m.signature()) {
|
||||||
updateMetaObject();
|
md.clear();
|
||||||
|
updateMetaObject();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicQMetaObject* DynamicQMetaObject::createBasedOn(PyTypeObject *type, const QMetaObject *base)
|
DynamicQMetaObject* DynamicQMetaObject::createBasedOn(PyObject *pyObj, PyTypeObject *type, const QMetaObject *base)
|
||||||
{
|
{
|
||||||
PyObject *key, *value;
|
PyObject *key, *value;
|
||||||
Py_ssize_t pos = 0;
|
Py_ssize_t pos = 0;
|
||||||
|
|
@ -133,14 +160,30 @@ DynamicQMetaObject* DynamicQMetaObject::createBasedOn(PyTypeObject *type, const
|
||||||
DynamicQMetaObject *mo = new PySide::DynamicQMetaObject(className.toAscii(), base);
|
DynamicQMetaObject *mo = new PySide::DynamicQMetaObject(className.toAscii(), base);
|
||||||
|
|
||||||
while (PyDict_Next(type->tp_dict, &pos, &key, &value)) {
|
while (PyDict_Next(type->tp_dict, &pos, &key, &value)) {
|
||||||
|
|
||||||
|
//Register signals
|
||||||
|
if (value->ob_type == &PySideSignal_Type) {
|
||||||
|
SignalData *data = reinterpret_cast<SignalData*>(value);
|
||||||
|
|
||||||
|
for(int i=0, i_max=data->signatures_size; i < i_max; i++) {
|
||||||
|
mo->addSignal(data->signatures[i]);
|
||||||
|
printf("QObject with signal:[%s][%s]\n",
|
||||||
|
PyString_AS_STRING(PyObject_Str(key)), data->signatures[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!PyFunction_Check(value))
|
if (!PyFunction_Check(value))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
//Register Slots
|
||||||
if (PyObject_HasAttrString(value, PYSIDE_SLOT_LIST_ATTR)) {
|
if (PyObject_HasAttrString(value, PYSIDE_SLOT_LIST_ATTR)) {
|
||||||
PyObject *signature_list = PyObject_GetAttrString(value, PYSIDE_SLOT_LIST_ATTR);
|
PyObject *signature_list = PyObject_GetAttrString(value, PYSIDE_SLOT_LIST_ATTR);
|
||||||
for(Py_ssize_t i=0, i_max=PyList_Size(signature_list); i < i_max; i++) {
|
for(Py_ssize_t i=0, i_max=PyList_Size(signature_list); i < i_max; i++) {
|
||||||
PyObject *signature = PyList_GET_ITEM(signature_list, i);
|
PyObject *signature = PyList_GET_ITEM(signature_list, i);
|
||||||
mo->addSlot(PyString_AsString(signature));
|
QString sig(PyString_AsString(signature));
|
||||||
|
//slot the slot type and signature
|
||||||
|
QStringList slotInfo = sig.split(" ", QString::SkipEmptyParts);
|
||||||
|
mo->addSlot(slotInfo[1].toAscii(), slotInfo[0].toAscii());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -151,9 +194,12 @@ void DynamicQMetaObject::removeSignal(uint index)
|
||||||
{
|
{
|
||||||
//Current Qt implementation does not support runtime remove signal
|
//Current Qt implementation does not support runtime remove signal
|
||||||
QMetaMethod m = method(index);
|
QMetaMethod m = method(index);
|
||||||
if (m_signals.contains(m.signature())) {
|
foreach(MethodData md, m_signals) {
|
||||||
clearItem(m_signals, m.signature());
|
if (md.signature() == m.signature()) {
|
||||||
updateMetaObject();
|
md.clear();
|
||||||
|
updateMetaObject();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -198,26 +244,28 @@ void DynamicQMetaObject::updateMetaObject()
|
||||||
int index = HEADER_LENGHT;
|
int index = HEADER_LENGHT;
|
||||||
|
|
||||||
//write signals
|
//write signals
|
||||||
QLinkedList<QByteArray>::iterator iSignal = m_signals.begin();
|
QLinkedList<MethodData>::iterator iSignal = m_signals.begin();
|
||||||
for(int i=0; i < MAX_SIGNALS_COUNT; i++) {
|
for(int i=0; i < MAX_SIGNALS_COUNT; i++) {
|
||||||
|
QByteArray sigType;
|
||||||
if (iSignal != m_signals.end()) {
|
if (iSignal != m_signals.end()) {
|
||||||
data[index++] = registerString(*iSignal, &strings); // func name
|
data[index++] = registerString((*iSignal).signature(), &strings); // func name
|
||||||
|
sigType = (*iSignal).type();
|
||||||
iSignal++;
|
iSignal++;
|
||||||
} else {
|
} else {
|
||||||
data[index++] = NULL_INDEX; // func name
|
data[index++] = NULL_INDEX; // func name
|
||||||
}
|
}
|
||||||
data[index++] = NULL_INDEX; // arguments
|
data[index++] = NULL_INDEX; // arguments
|
||||||
data[index++] = NULL_INDEX; // normalized type
|
data[index++] = (sigType.size() > 0 ? registerString(sigType, &strings) : NULL_INDEX); // normalized type
|
||||||
data[index++] = NULL_INDEX; // tags
|
data[index++] = NULL_INDEX; // tags
|
||||||
data[index++] = AccessPublic | MethodSignal; // flags
|
data[index++] = AccessPublic | MethodSignal; // flags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//write slots
|
//write slots
|
||||||
foreach(QByteArray slot, m_slots) {
|
foreach(MethodData slot, m_slots) {
|
||||||
data[index++] = registerString(slot, &strings); // func name
|
data[index++] = registerString(slot.signature(), &strings); // func name
|
||||||
data[index++] = NULL_INDEX; // arguments
|
data[index++] = NULL_INDEX; // arguments
|
||||||
data[index++] = NULL_INDEX; // normalized type
|
data[index++] = (slot.type().size() > 0 ? registerString(slot.type(), &strings) : NULL_INDEX); // normalized type
|
||||||
data[index++] = NULL_INDEX; // tags
|
data[index++] = NULL_INDEX; // tags
|
||||||
data[index++] = AccessPublic | MethodSlot; // flags
|
data[index++] = AccessPublic | MethodSlot; // flags
|
||||||
}
|
}
|
||||||
|
|
@ -225,8 +273,8 @@ void DynamicQMetaObject::updateMetaObject()
|
||||||
|
|
||||||
// create the m_metadata string
|
// create the m_metadata string
|
||||||
QByteArray str;
|
QByteArray str;
|
||||||
foreach(QByteArray signature, strings) {
|
foreach(QByteArray field, strings) {
|
||||||
str.append(signature);
|
str.append(field);
|
||||||
str.append(char(0));
|
str.append(char(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,24 +48,39 @@ class QObject;
|
||||||
namespace PySide
|
namespace PySide
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class MethodData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MethodData(){}
|
||||||
|
MethodData(const char *signature, const char *type);
|
||||||
|
void clear();
|
||||||
|
QByteArray signature() const;
|
||||||
|
QByteArray type() const;
|
||||||
|
bool operator==(const MethodData &other) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QByteArray m_signature;
|
||||||
|
QByteArray m_type;
|
||||||
|
};
|
||||||
|
|
||||||
class PYSIDE_API DynamicQMetaObject : public QMetaObject
|
class PYSIDE_API DynamicQMetaObject : public QMetaObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DynamicQMetaObject(const char* className, const QMetaObject* metaObject);
|
DynamicQMetaObject(const char* className, const QMetaObject* metaObject);
|
||||||
~DynamicQMetaObject();
|
~DynamicQMetaObject();
|
||||||
|
|
||||||
void addSignal(const char* signal);
|
void addSignal(const char* signal, const char* type=0);
|
||||||
void addSlot(const char* slot);
|
void addSlot(const char* slot, const char* type=0);
|
||||||
|
|
||||||
void removeSignal(uint idex);
|
void removeSignal(uint idex);
|
||||||
void removeSlot(uint index);
|
void removeSlot(uint index);
|
||||||
|
|
||||||
//Retrieve Python metadata to create QMetaObject (class name, signals, slot)
|
//Retrieve Python metadata to create QMetaObject (class name, signals, slot)
|
||||||
static DynamicQMetaObject *createBasedOn(PyTypeObject *obj, const QMetaObject* base);
|
static DynamicQMetaObject *createBasedOn(PyObject *obj, PyTypeObject *type, const QMetaObject* base);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QLinkedList<QByteArray> m_signals;
|
QLinkedList<MethodData> m_signals;
|
||||||
QLinkedList<QByteArray> m_slots;
|
QLinkedList<MethodData> m_slots;
|
||||||
QByteArray m_className;
|
QByteArray m_className;
|
||||||
|
|
||||||
void updateMetaObject();
|
void updateMetaObject();
|
||||||
|
|
|
||||||
51
libpyside/pyside.cpp
Normal file
51
libpyside/pyside.cpp
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* 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 "pyside.h"
|
||||||
|
|
||||||
|
extern "C" PyAPI_FUNC(void) init_signal(PyObject* module);
|
||||||
|
extern "C" PyAPI_FUNC(void) init_slot(PyObject* module);
|
||||||
|
|
||||||
|
namespace PySide
|
||||||
|
{
|
||||||
|
|
||||||
|
void init(PyObject *module)
|
||||||
|
{
|
||||||
|
init_signal(module);
|
||||||
|
init_slot(module);
|
||||||
|
}
|
||||||
|
|
||||||
|
} //namespace PySide
|
||||||
|
|
||||||
50
libpyside/pyside.h
Normal file
50
libpyside/pyside.h
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* 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 PYSIDE_H
|
||||||
|
#define PYSIDE_H
|
||||||
|
|
||||||
|
#include <Python.h>
|
||||||
|
#include <pysidemacros.h>
|
||||||
|
|
||||||
|
namespace PySide
|
||||||
|
{
|
||||||
|
|
||||||
|
PYSIDE_API void init(PyObject *module);
|
||||||
|
|
||||||
|
} //namespace PySide
|
||||||
|
|
||||||
|
|
||||||
|
#endif // PYSIDE_H
|
||||||
|
|
||||||
413
libpyside/qsignal.cpp
Normal file
413
libpyside/qsignal.cpp
Normal file
|
|
@ -0,0 +1,413 @@
|
||||||
|
#define protected public
|
||||||
|
|
||||||
|
#include <shiboken.h>
|
||||||
|
#include <Python.h>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#include "qsignal.h"
|
||||||
|
#include "signalmanager.h"
|
||||||
|
|
||||||
|
#define SIGNAL_CLASS_NAME "Signal"
|
||||||
|
|
||||||
|
namespace PySide
|
||||||
|
{
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
|
||||||
|
static int qsignal_init(PyObject*, PyObject*, PyObject*);
|
||||||
|
static void qsignal_free(void*);
|
||||||
|
static void qsignal_instance_free(void*);
|
||||||
|
|
||||||
|
//methods
|
||||||
|
static PyObject* qsignal_instance_connect(PyObject *self, PyObject *args, PyObject *kw);
|
||||||
|
static PyObject* qsignal_instance_disconnect(PyObject *self, PyObject *args);
|
||||||
|
static PyObject* qsignal_instance_emit(PyObject *self, PyObject *args);
|
||||||
|
|
||||||
|
//aux
|
||||||
|
static char* qsignal_build_signature(const char *name, const char *signature);
|
||||||
|
static const char* qsignal_get_type_name(PyObject *type);
|
||||||
|
static void qsignal_append_signature(SignalData *self, PyObject *args);
|
||||||
|
static void qsignal_instance_initialize(PyObject *instance, SignalData *data, PyObject *source);
|
||||||
|
|
||||||
|
PyTypeObject PySideSignal_Type = {
|
||||||
|
PyObject_HEAD_INIT(0)
|
||||||
|
0, /*ob_size*/
|
||||||
|
SIGNAL_CLASS_NAME, /*tp_name*/
|
||||||
|
sizeof(SignalData), /*tp_basicsize*/
|
||||||
|
0, /*tp_itemsize*/
|
||||||
|
0, /*tp_dealloc*/
|
||||||
|
0, /*tp_print*/
|
||||||
|
0, /*tp_getattr*/
|
||||||
|
0, /*tp_setattr*/
|
||||||
|
0, /*tp_compare*/
|
||||||
|
0, /*tp_repr*/
|
||||||
|
0, /*tp_as_number*/
|
||||||
|
0, /*tp_as_sequence*/
|
||||||
|
0, /*tp_as_mapping*/
|
||||||
|
0, /*tp_hash */
|
||||||
|
0, /*tp_call*/
|
||||||
|
0, /*tp_str*/
|
||||||
|
0, /*tp_getattro*/
|
||||||
|
0, /*tp_setattro*/
|
||||||
|
0, /*tp_as_buffer*/
|
||||||
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
|
||||||
|
SIGNAL_CLASS_NAME, /*tp_doc */
|
||||||
|
0, /*tp_traverse */
|
||||||
|
0, /*tp_clear */
|
||||||
|
0, /*tp_richcompare */
|
||||||
|
0, /*tp_weaklistoffset */
|
||||||
|
0, /*tp_iter */
|
||||||
|
0, /*tp_iternext */
|
||||||
|
0, /*tp_methods */
|
||||||
|
0, /*tp_members */
|
||||||
|
0, /*tp_getset */
|
||||||
|
0, /*tp_base */
|
||||||
|
0, /*tp_dict */
|
||||||
|
0, /*tp_descr_get */
|
||||||
|
0, /*tp_descr_set */
|
||||||
|
0, /*tp_dictoffset */
|
||||||
|
(initproc)qsignal_init, /*tp_init */
|
||||||
|
0, /*tp_alloc */
|
||||||
|
PyType_GenericNew, /*tp_new */
|
||||||
|
qsignal_free, /*tp_free */
|
||||||
|
0, /*tp_is_gc */
|
||||||
|
0, /*tp_bases */
|
||||||
|
0, /*tp_mro */
|
||||||
|
0, /*tp_cache */
|
||||||
|
0, /*tp_subclasses */
|
||||||
|
0, /*tp_weaklist */
|
||||||
|
0, /*tp_del */
|
||||||
|
};
|
||||||
|
|
||||||
|
static PyMethodDef PySideQtSignalInstance_methods[] = {
|
||||||
|
{"connect", (PyCFunction)qsignal_instance_connect, METH_VARARGS|METH_KEYWORDS},
|
||||||
|
{"disconnect", (PyCFunction)qsignal_instance_disconnect, METH_VARARGS},
|
||||||
|
{"emit", (PyCFunction)qsignal_instance_emit, METH_VARARGS},
|
||||||
|
{NULL} /* Sentinel */
|
||||||
|
};
|
||||||
|
|
||||||
|
PyTypeObject PySideSignalInstance_Type = {
|
||||||
|
PyObject_HEAD_INIT(0)
|
||||||
|
0, /*ob_size*/
|
||||||
|
SIGNAL_CLASS_NAME, /*tp_name*/
|
||||||
|
sizeof(SignalData), /*tp_basicsize*/
|
||||||
|
0, /*tp_itemsize*/
|
||||||
|
0, /*tp_dealloc*/
|
||||||
|
0, /*tp_print*/
|
||||||
|
0, /*tp_getattr*/
|
||||||
|
0, /*tp_setattr*/
|
||||||
|
0, /*tp_compare*/
|
||||||
|
0, /*tp_repr*/
|
||||||
|
0, /*tp_as_number*/
|
||||||
|
0, /*tp_as_sequence*/
|
||||||
|
0, /*tp_as_mapping*/
|
||||||
|
0, /*tp_hash */
|
||||||
|
0, /*tp_call*/
|
||||||
|
0, /*tp_str*/
|
||||||
|
0, /*tp_getattro*/
|
||||||
|
0, /*tp_setattro*/
|
||||||
|
0, /*tp_as_buffer*/
|
||||||
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
|
||||||
|
SIGNAL_CLASS_NAME"I", /*tp_doc */
|
||||||
|
0, /*tp_traverse */
|
||||||
|
0, /*tp_clear */
|
||||||
|
0, /*tp_richcompare */
|
||||||
|
0, /*tp_weaklistoffset */
|
||||||
|
0, /*tp_iter */
|
||||||
|
0, /*tp_iternext */
|
||||||
|
PySideQtSignalInstance_methods, /*tp_methods */
|
||||||
|
0, /*tp_members */
|
||||||
|
0, /*tp_getset */
|
||||||
|
&PySideSignal_Type, /*tp_base */
|
||||||
|
0, /*tp_dict */
|
||||||
|
0, /*tp_descr_get */
|
||||||
|
0, /*tp_descr_set */
|
||||||
|
0, /*tp_dictoffset */
|
||||||
|
0, /*tp_init */
|
||||||
|
0, /*tp_alloc */
|
||||||
|
PyType_GenericNew, /*tp_new */
|
||||||
|
qsignal_instance_free, /*tp_free */
|
||||||
|
0, /*tp_is_gc */
|
||||||
|
0, /*tp_bases */
|
||||||
|
0, /*tp_mro */
|
||||||
|
0, /*tp_cache */
|
||||||
|
0, /*tp_subclasses */
|
||||||
|
0, /*tp_weaklist */
|
||||||
|
0, /*tp_del */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
PyAPI_FUNC(void) init_signal(PyObject* module)
|
||||||
|
{
|
||||||
|
if (PyType_Ready(&PySideSignal_Type) < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Py_INCREF(&PySideSignal_Type);
|
||||||
|
PyModule_AddObject(module, SIGNAL_CLASS_NAME, ((PyObject*)&PySideSignal_Type));
|
||||||
|
|
||||||
|
if (PyType_Ready(&PySideSignalInstance_Type) < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Py_INCREF(&PySideSignalInstance_Type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // extern "C"
|
||||||
|
|
||||||
|
void signal_update_source(PyObject *source)
|
||||||
|
{
|
||||||
|
PyObject *key, *value;
|
||||||
|
Py_ssize_t pos = 0;
|
||||||
|
PyTypeObject *obType = source->ob_type;
|
||||||
|
|
||||||
|
while (PyDict_Next(obType->tp_dict, &pos, &key, &value)) {
|
||||||
|
|
||||||
|
if (value->ob_type == &PySideSignal_Type) {
|
||||||
|
PyObject *signal_instance = (PyObject*)PyObject_New(SignalData, &PySideSignalInstance_Type);
|
||||||
|
|
||||||
|
qsignal_instance_initialize(signal_instance, reinterpret_cast<SignalData*>(value), source);
|
||||||
|
|
||||||
|
PyObject_SetAttr(source, key, signal_instance);
|
||||||
|
Py_DECREF(signal_instance);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* qsignal_get_type_name(PyObject *type)
|
||||||
|
{
|
||||||
|
if (PyType_Check(type)) {
|
||||||
|
//tp_name return the full name
|
||||||
|
Shiboken::AutoDecRef type_name(PyObject_GetAttrString(type, "__name__"));
|
||||||
|
return PyString_AS_STRING((PyObject*)type_name);
|
||||||
|
} else if (PyString_Check(type)) {
|
||||||
|
return PyString_AS_STRING(type);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
char* qsignal_build_signature(const char *name, const char *signature)
|
||||||
|
{
|
||||||
|
QString signal;
|
||||||
|
signal.sprintf("2%s(%s)", name, (signature ? signature : "()"));
|
||||||
|
return strdup(QMetaObject::normalizedSignature(signal.toAscii()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void qsignal_append_signature(SignalData *self, PyObject *args)
|
||||||
|
{
|
||||||
|
char *signature = 0;
|
||||||
|
for(Py_ssize_t i=0, i_max=PySequence_Size(args); i < i_max; i++) {
|
||||||
|
Shiboken::AutoDecRef arg(PySequence_ITEM(args, i));
|
||||||
|
const char *type_name = qsignal_get_type_name(arg);
|
||||||
|
if (strlen(type_name) > 0) {
|
||||||
|
if (signature) {
|
||||||
|
signature = strcat(signature, ",");
|
||||||
|
signature = strcat(signature, type_name);
|
||||||
|
} else {
|
||||||
|
signature = strdup(type_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self->signatures_size++;
|
||||||
|
if (self->signatures_size > 1) {
|
||||||
|
self->signatures = (char**) realloc(self->signatures, sizeof(char**) * self->signatures_size);
|
||||||
|
} else {
|
||||||
|
self->signatures = (char**) malloc(sizeof(char**));
|
||||||
|
}
|
||||||
|
self->signatures[self->signatures_size -1] = qsignal_build_signature(self->signal_name, signature);
|
||||||
|
printf("registred signature:[%d][%s]\n", self->signatures_size -1, self->signatures[self->signatures_size -1]);
|
||||||
|
free(signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
int qsignal_init(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
|
{
|
||||||
|
static PyObject *emptyTuple = 0;
|
||||||
|
static const char *kwlist[] = {"name", 0};
|
||||||
|
char* arg_name = 0;
|
||||||
|
|
||||||
|
if (emptyTuple == 0)
|
||||||
|
emptyTuple = PyTuple_New(0);
|
||||||
|
|
||||||
|
if (!PyArg_ParseTupleAndKeywords(emptyTuple, kwds,
|
||||||
|
"|s:QtCore."SIGNAL_CLASS_NAME, (char**) kwlist, &arg_name))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
bool tupled_args = false;
|
||||||
|
SignalData *data = reinterpret_cast<SignalData*>(self);
|
||||||
|
if (arg_name)
|
||||||
|
data->signal_name = strdup(arg_name);
|
||||||
|
|
||||||
|
for(Py_ssize_t i=0, i_max=PyTuple_Size(args); i < i_max; i++) {
|
||||||
|
PyObject *arg = PyTuple_GET_ITEM(args, i);
|
||||||
|
if (PySequence_Check(arg)) {
|
||||||
|
tupled_args = true;
|
||||||
|
qsignal_append_signature(data, arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tupled_args)
|
||||||
|
qsignal_append_signature(data, args);
|
||||||
|
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void qsignal_free(void *self)
|
||||||
|
{
|
||||||
|
PyObject *pySelf = reinterpret_cast<PyObject*>(self);
|
||||||
|
SignalData *data = reinterpret_cast<SignalData*>(self);
|
||||||
|
|
||||||
|
//keep the data to instance
|
||||||
|
if (!data->initialized)
|
||||||
|
qsignal_instance_free(self);
|
||||||
|
|
||||||
|
pySelf->ob_type->tp_free (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qsignal_instance_free(void *self)
|
||||||
|
{
|
||||||
|
PyObject *pySelf = reinterpret_cast<PyObject*>(self);
|
||||||
|
SignalData *data = reinterpret_cast<SignalData*>(self);
|
||||||
|
free(data->signatures[0]);
|
||||||
|
for(int i=1, i_max=data->signatures_size; i < i_max; i++) {
|
||||||
|
free(data->signatures[i]);
|
||||||
|
}
|
||||||
|
free(data->signatures);
|
||||||
|
free(data->signal_name);
|
||||||
|
data->initialized = false;
|
||||||
|
|
||||||
|
pySelf->ob_type->tp_free (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qsignal_instance_initialize(PyObject *instance, SignalData *data, PyObject *source)
|
||||||
|
{
|
||||||
|
SignalData *self = reinterpret_cast<SignalData*>(instance);
|
||||||
|
self->signal_name = data->signal_name;
|
||||||
|
self->signatures_size = data->signatures_size;
|
||||||
|
self->signatures = data->signatures;
|
||||||
|
self->initialized = true;
|
||||||
|
self->source = source;
|
||||||
|
data->initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* qsignal_instance_connect(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
|
{
|
||||||
|
PyObject *slot;
|
||||||
|
PyObject *type;
|
||||||
|
static const char *kwlist[] = {"type", 0};
|
||||||
|
|
||||||
|
if (!PyArg_ParseTupleAndKeywords(args, kwds,
|
||||||
|
"O|O:"SIGNAL_CLASS_NAME, (char**) kwlist, &slot, &type))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
SignalData *source = reinterpret_cast<SignalData*>(self);
|
||||||
|
Shiboken::AutoDecRef pyArgs(PyList_New(0));
|
||||||
|
|
||||||
|
bool match = false;
|
||||||
|
if (slot->ob_type == &PySideSignal_Type) {
|
||||||
|
SignalData *target = reinterpret_cast<SignalData*>(slot);
|
||||||
|
for(int s, s_max=source->signatures_size; s < s_max; s++) {
|
||||||
|
for(int t, t_max=target->signatures_size; t < t_max; t++) {
|
||||||
|
if (QMetaObject::checkConnectArgs(source->signatures[s], target->signatures[t])) {
|
||||||
|
PyList_Append(pyArgs, source->source);
|
||||||
|
Shiboken::AutoDecRef source_signature(PyString_FromString(source->signatures[s]));
|
||||||
|
PyList_Append(pyArgs, source_signature);
|
||||||
|
|
||||||
|
PyList_Append(pyArgs, target->source);
|
||||||
|
Shiboken::AutoDecRef target_signature(PyString_FromString(source->signatures[s]));
|
||||||
|
PyList_Append(pyArgs, target_signature);
|
||||||
|
match = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (match) break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//try the first signature
|
||||||
|
PyList_Append(pyArgs, source->source);
|
||||||
|
Shiboken::AutoDecRef signature(PyString_FromString(source->signatures[0]));
|
||||||
|
PyList_Append(pyArgs, signature);
|
||||||
|
|
||||||
|
PyList_Append(pyArgs, slot);
|
||||||
|
match = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
Shiboken::AutoDecRef tupleArgs(PyList_AsTuple(pyArgs));
|
||||||
|
Shiboken::AutoDecRef pyMethod(PyObject_GetAttrString(source->source, "connect"));
|
||||||
|
return PyObject_CallObject(pyMethod, tupleArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* qsignal_instance_disconnect(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
SignalData *source = reinterpret_cast<SignalData*>(self);
|
||||||
|
Shiboken::AutoDecRef pyArgs(PyList_New(0));
|
||||||
|
|
||||||
|
PyObject *slot;
|
||||||
|
if PyTuple_Check(args)
|
||||||
|
slot = PyTuple_GET_ITEM(args, 0);
|
||||||
|
else
|
||||||
|
slot = args;
|
||||||
|
|
||||||
|
bool match = false;
|
||||||
|
if (slot->ob_type == &PySideSignal_Type) {
|
||||||
|
SignalData *target = reinterpret_cast<SignalData*>(slot);
|
||||||
|
for(int s, s_max=source->signatures_size; s < s_max; s++) {
|
||||||
|
for(int t, t_max=target->signatures_size; t < t_max; t++) {
|
||||||
|
if (QMetaObject::checkConnectArgs(source->signatures[s], target->signatures[t])) {
|
||||||
|
PyList_Append(pyArgs, source->source);
|
||||||
|
Shiboken::AutoDecRef source_signature(PyString_FromString(source->signatures[s]));
|
||||||
|
PyList_Append(pyArgs, source_signature);
|
||||||
|
|
||||||
|
PyList_Append(pyArgs, target->source);
|
||||||
|
Shiboken::AutoDecRef target_signature(PyString_FromString(source->signatures[s]));
|
||||||
|
PyList_Append(pyArgs, target_signature);
|
||||||
|
match = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (match) break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//try the first signature
|
||||||
|
PyList_Append(pyArgs, source->source);
|
||||||
|
Shiboken::AutoDecRef signature(PyString_FromString(source->signatures[0]));
|
||||||
|
PyList_Append(pyArgs, signature);
|
||||||
|
|
||||||
|
PyList_Append(pyArgs, slot);
|
||||||
|
match = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
Shiboken::AutoDecRef tupleArgs(PyList_AsTuple(pyArgs));
|
||||||
|
Shiboken::AutoDecRef pyMethod(PyObject_GetAttrString(source->source, "disconnect"));
|
||||||
|
return PyObject_CallObject(pyMethod, tupleArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* qsignal_instance_emit(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
SignalData *source = reinterpret_cast<SignalData*>(self);
|
||||||
|
|
||||||
|
Shiboken::AutoDecRef pyArgs(PyList_New(0));
|
||||||
|
Shiboken::AutoDecRef source_signature(PyString_FromString(source->signatures[0]));
|
||||||
|
|
||||||
|
PyList_Append(pyArgs, source_signature);
|
||||||
|
for(Py_ssize_t i=0, i_max=PyTuple_Size(args); i < i_max; i++)
|
||||||
|
PyList_Append(pyArgs, PyTuple_GetItem(args, i));
|
||||||
|
|
||||||
|
Shiboken::AutoDecRef pyMethod(PyObject_GetAttrString(source->source, "emit"));
|
||||||
|
|
||||||
|
Shiboken::AutoDecRef tupleArgs(PyList_AsTuple(pyArgs));
|
||||||
|
return PyObject_CallObject(pyMethod, tupleArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
} //namespace PySide
|
||||||
29
libpyside/qsignal.h
Normal file
29
libpyside/qsignal.h
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef QSIGNAL_H
|
||||||
|
#define QSIGNAL_H
|
||||||
|
|
||||||
|
#include <pysidemacros.h>
|
||||||
|
#include <Python.h>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
namespace PySide
|
||||||
|
{
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyObject_HEAD
|
||||||
|
bool initialized;
|
||||||
|
char *signal_name;
|
||||||
|
char **signatures;
|
||||||
|
int signatures_size;
|
||||||
|
PyObject *source;
|
||||||
|
} SignalData;
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
PyAPI_DATA(PyTypeObject) PySideSignal_Type;
|
||||||
|
PyAPI_DATA(PyTypeObject) PySideSignalInstance_Type;
|
||||||
|
}; //extern "C"
|
||||||
|
|
||||||
|
PYSIDE_API void signal_update_source(PyObject *source);
|
||||||
|
|
||||||
|
} //namespace PySide
|
||||||
|
#endif
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
#include <signalmanager.h>
|
#include <shiboken.h>
|
||||||
#include <dynamicqmetaobject.h>
|
#include <dynamicqmetaobject.h>
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
#define SLOT_DEC_NAME "Slot"
|
#define SLOT_DEC_NAME "Slot"
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
|
|
@ -67,10 +70,6 @@ static PyTypeObject PySideSlot_Type = {
|
||||||
0, /*tp_del */
|
0, /*tp_del */
|
||||||
};
|
};
|
||||||
|
|
||||||
static PyMethodDef PySideQtSlot_methods[] = {
|
|
||||||
{NULL} /* Sentinel */
|
|
||||||
};
|
|
||||||
|
|
||||||
PyAPI_FUNC(void) init_slot(PyObject* module)
|
PyAPI_FUNC(void) init_slot(PyObject* module)
|
||||||
{
|
{
|
||||||
if (PyType_Ready(&PySideSlot_Type) < 0)
|
if (PyType_Ready(&PySideSlot_Type) < 0)
|
||||||
|
|
@ -86,7 +85,6 @@ PyAPI_FUNC(void) init_slot(PyObject* module)
|
||||||
static const char* qslot_get_type_name(PyObject *type)
|
static const char* qslot_get_type_name(PyObject *type)
|
||||||
{
|
{
|
||||||
if (PyType_Check(type)) {
|
if (PyType_Check(type)) {
|
||||||
PyTypeObject *obj_type = (PyTypeObject*)(type);
|
|
||||||
//tp_name return the full name
|
//tp_name return the full name
|
||||||
Shiboken::AutoDecRef type_name(PyObject_GetAttrString(type, "__name__"));
|
Shiboken::AutoDecRef type_name(PyObject_GetAttrString(type, "__name__"));
|
||||||
return PyString_AS_STRING((PyObject*)type_name);
|
return PyString_AS_STRING((PyObject*)type_name);
|
||||||
|
|
@ -106,7 +104,7 @@ static int qslot_init(PyObject *self, PyObject *args, PyObject *kw)
|
||||||
if (emptyTuple == 0)
|
if (emptyTuple == 0)
|
||||||
emptyTuple = PyTuple_New(0);
|
emptyTuple = PyTuple_New(0);
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(emptyTuple, kw, "|sN:QtCore."SLOT_DEC_NAME, (char**) kwlist, &arg_name, &arg_result))
|
if (!PyArg_ParseTupleAndKeywords(emptyTuple, kw, "|sO:QtCore."SLOT_DEC_NAME, (char**) kwlist, &arg_name, &arg_result))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
SlotData *data = reinterpret_cast<SlotData*>(self);
|
SlotData *data = reinterpret_cast<SlotData*>(self);
|
||||||
|
|
@ -128,6 +126,8 @@ static int qslot_init(PyObject *self, PyObject *args, PyObject *kw)
|
||||||
|
|
||||||
if (arg_result)
|
if (arg_result)
|
||||||
data->result_type = strdup(qslot_get_type_name(arg_result));
|
data->result_type = strdup(qslot_get_type_name(arg_result));
|
||||||
|
else
|
||||||
|
data->result_type = strdup("void");
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -147,7 +147,7 @@ static PyObject* qslot_call(PyObject *self, PyObject *args, PyObject *kw)
|
||||||
}
|
}
|
||||||
|
|
||||||
QString signature;
|
QString signature;
|
||||||
signature.sprintf("%s(%s)",data->slot_name, data->args);
|
signature.sprintf("%s %s(%s)", data->result_type, data->slot_name, data->args);
|
||||||
|
|
||||||
PyObject *pySignature = PyString_FromString(QMetaObject::normalizedSignature(signature.toAscii()));
|
PyObject *pySignature = PyString_FromString(QMetaObject::normalizedSignature(signature.toAscii()));
|
||||||
PyObject *signature_list = 0;
|
PyObject *signature_list = 0;
|
||||||
|
|
@ -24,8 +24,12 @@ class MyObject(QObject):
|
||||||
def foo(self):
|
def foo(self):
|
||||||
self._slotCalledCount = self._slotCalledCount + 1
|
self._slotCalledCount = self._slotCalledCount + 1
|
||||||
|
|
||||||
@Slot(QString)
|
@Slot(QString, int)
|
||||||
def mySlot4(self, a):
|
def mySlot4(self, a, b):
|
||||||
|
self._slotCalledCount = self._slotCalledCount + 1
|
||||||
|
|
||||||
|
@Slot(result=int)
|
||||||
|
def mySlot5(self):
|
||||||
self._slotCalledCount = self._slotCalledCount + 1
|
self._slotCalledCount = self._slotCalledCount + 1
|
||||||
|
|
||||||
class StaticMetaObjectTest(unittest.TestCase):
|
class StaticMetaObjectTest(unittest.TestCase):
|
||||||
|
|
@ -37,7 +41,7 @@ class StaticMetaObjectTest(unittest.TestCase):
|
||||||
self.assert_(m.indexOfSlot('mySlot2(int)') > 0)
|
self.assert_(m.indexOfSlot('mySlot2(int)') > 0)
|
||||||
self.assert_(m.indexOfSlot('mySlot2(QString)') > 0)
|
self.assert_(m.indexOfSlot('mySlot2(QString)') > 0)
|
||||||
self.assert_(m.indexOfSlot('mySlot3()') > 0)
|
self.assert_(m.indexOfSlot('mySlot3()') > 0)
|
||||||
self.assert_(m.indexOfSlot('mySlot4(QString)') > 0)
|
self.assert_(m.indexOfSlot('mySlot4(QString,int)') > 0)
|
||||||
|
|
||||||
def testEmission(self):
|
def testEmission(self):
|
||||||
o = MyObject()
|
o = MyObject()
|
||||||
|
|
@ -45,5 +49,12 @@ class StaticMetaObjectTest(unittest.TestCase):
|
||||||
o.emit(SIGNAL("mySignal()"))
|
o.emit(SIGNAL("mySignal()"))
|
||||||
self.assert_(o._slotCalledCount == 1)
|
self.assert_(o._slotCalledCount == 1)
|
||||||
|
|
||||||
|
def testResult(self):
|
||||||
|
o = MyObject()
|
||||||
|
mo = o.metaObject()
|
||||||
|
i = mo.indexOfSlot('mySlot5()')
|
||||||
|
m = mo.method(i)
|
||||||
|
self.assertEqual(m.typeName(), "int")
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
||||||
39
tests/signals/signal_object_test.py
Normal file
39
tests/signals/signal_object_test.py
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
import functools
|
||||||
|
|
||||||
|
from PySide.QtCore import *
|
||||||
|
|
||||||
|
class MyObject(QObject):
|
||||||
|
sig1 = Signal()
|
||||||
|
sig2 = Signal(int, name='rangeChanged')
|
||||||
|
|
||||||
|
|
||||||
|
@Slot(int)
|
||||||
|
def myRange(self, r):
|
||||||
|
print "Range changed:", r
|
||||||
|
|
||||||
|
|
||||||
|
def slot1(self):
|
||||||
|
self._called = True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class SignalObjectTest(unittest.TestCase):
|
||||||
|
|
||||||
|
def testsingleConnect(self):
|
||||||
|
o = MyObject()
|
||||||
|
o.sig1.connect(o.slot1)
|
||||||
|
o.sig1.emit()
|
||||||
|
self.assert_(o._called)
|
||||||
|
|
||||||
|
def testSignatureParse(self):
|
||||||
|
o = MyObject()
|
||||||
|
o.sig2.connect(o.myRange)
|
||||||
|
o.sig2.emit(10)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue