Merge remote branch 'mainline/1.0'

Conflicts:
	CMakeLists.txt
This commit is contained in:
Hugo Parente Lima 2010-10-19 17:20:10 -02:00
commit 4a638ed634
26 changed files with 2639 additions and 755 deletions

View file

@ -68,9 +68,9 @@ if(AVOID_PROTECTED_HACK OR WIN32)
endif() endif()
set(BINDING_NAME PySide) set(BINDING_NAME PySide)
set(BINDING_API_MAJOR_VERSION "0") set(BINDING_API_MAJOR_VERSION "1")
set(BINDING_API_MINOR_VERSION "4") set(BINDING_API_MINOR_VERSION "0")
set(BINDING_API_MICRO_VERSION "2") set(BINDING_API_MICRO_VERSION "0")
set(BINDING_API_VERSION "${BINDING_API_MAJOR_VERSION}.${BINDING_API_MINOR_VERSION}.${BINDING_API_MICRO_VERSION}" CACHE STRING "PySide version" FORCE) set(BINDING_API_VERSION "${BINDING_API_MAJOR_VERSION}.${BINDING_API_MINOR_VERSION}.${BINDING_API_MICRO_VERSION}" CACHE STRING "PySide version" FORCE)
set(PYSIDE_QT_VERSION "${QT_VERSION_MAJOR}.${QT_VERSION_MINOR}" CACHE STRING "Qt version used to compile PySide" FORCE) set(PYSIDE_QT_VERSION "${QT_VERSION_MAJOR}.${QT_VERSION_MINOR}" CACHE STRING "Qt version used to compile PySide" FORCE)
if(ENABLE_VERSION_SUFFIX) if(ENABLE_VERSION_SUFFIX)

View file

@ -1962,42 +1962,28 @@
timer->setSingleShot(true); timer->setSingleShot(true);
timer->connect(timer, SIGNAL(timeout()), timer, SLOT(deleteLater())); timer->connect(timer, SIGNAL(timeout()), timer, SLOT(deleteLater()));
Shiboken::AutoDecRef result( if (PyObject_TypeCheck(%2, &PySideSignalInstanceType)) {
PyObject_CallMethod(pyTimer, PySideSignalInstanceData* signalInstance = reinterpret_cast<PySideSignalInstanceData*>(%2);
const_cast<char*>("connect"), Shiboken::AutoDecRef signalSignature(PyString_FromFormat("2%s", signalInstance->signature));
const_cast<char*>("OsO"), Shiboken::AutoDecRef result(
pyTimer, PyObject_CallMethod(pyTimer,
SIGNAL(timeout()), const_cast<char*>("connect"),
pyargs[1]) const_cast<char*>("OsOO"),
); pyTimer,
Shiboken::BindingManager::instance().destroyWrapper((Shiboken::SbkBaseWrapper *)pyTimer); SIGNAL(timeout()),
timer->start(%1); signalInstance->source,
</inject-code> signalSignature.object())
</add-function> );
<!-- Second argument is a PySide.QtCore.Signal. See bug #362. --> } else {
<add-function signature="singleShot(int, PyObject*)" static="yes"> Shiboken::AutoDecRef result(
<inject-code class="target" position="beginning"> PyObject_CallMethod(pyTimer,
if (!PyObject_TypeCheck(%2, &amp;PySide::SignalInstance_Type)) const_cast&lt;char*>("connect"),
goto Sbk%TYPEFunc_%FUNCTION_NAME_TypeError; const_cast&lt;char*>("OsO"),
pyTimer,
// %FUNCTION_NAME() - disable generation of c++ function call SIGNAL(timeout()),
Shiboken::AutoDecRef emptyTuple(PyTuple_New(0)); pyargs[1])
PyObject* pyTimer = Shiboken::SbkType&lt;QTimer>()->tp_new(Shiboken::SbkType&lt;QTimer>(), emptyTuple, 0); );
Shiboken::SbkType&lt;QTimer>()->tp_init(pyTimer, emptyTuple, 0); }
QTimer* timer = Converter&lt;QTimer*>::toCpp(pyTimer);
timer->setSingleShot(true);
timer->connect(timer, SIGNAL(timeout()), timer, SLOT(deleteLater()));
PySide::SignalInstanceData* signalInstance = reinterpret_cast&lt;PySide::SignalInstanceData*&gt;(%2);
Shiboken::AutoDecRef signalSignature(PyString_FromFormat("2%s", signalInstance->signature));
Shiboken::AutoDecRef result(
PyObject_CallMethod(pyTimer,
const_cast&lt;char*>("connect"),
const_cast&lt;char*>("OsOO"),
pyTimer,
SIGNAL(timeout()),
signalInstance->source,
signalSignature.object())
);
Shiboken::BindingManager::instance().destroyWrapper((Shiboken::SbkBaseWrapper *)pyTimer); Shiboken::BindingManager::instance().destroyWrapper((Shiboken::SbkBaseWrapper *)pyTimer);
timer->start(%1); timer->start(%1);
</inject-code> </inject-code>
@ -2698,9 +2684,9 @@
// since it refers to a name very tied to the generator implementation. // since it refers to a name very tied to the generator implementation.
// Check bug #362 for more information on this // Check bug #362 for more information on this
// http://bugs.openbossa.org/show_bug.cgi?id=362 // http://bugs.openbossa.org/show_bug.cgi?id=362
if (!PyObject_TypeCheck(%1, &amp;PySide::SignalInstance_Type)) if (!PyObject_TypeCheck(%1, &amp;PySideSignalInstanceType))
goto Sbk%TYPEFunc_%FUNCTION_NAME_TypeError; goto Sbk%TYPEFunc_%FUNCTION_NAME_TypeError;
PySide::SignalInstanceData* signalInstance = reinterpret_cast&lt;PySide::SignalInstanceData*&gt;(%1); PySideSignalInstanceData* signalInstance = reinterpret_cast&lt;PySideSignalInstanceData*&gt;(%1);
QObject* sender = %CONVERTTOCPP[QObject*](signalInstance->source); QObject* sender = %CONVERTTOCPP[QObject*](signalInstance->source);
%PYARG_0 = %CONVERTTOPYTHON[QSignalTransition*](%CPPSELF->%FUNCTION_NAME(sender, signalInstance->signature, %2)); %PYARG_0 = %CONVERTTOPYTHON[QSignalTransition*](%CPPSELF->%FUNCTION_NAME(sender, signalInstance->signature, %2));
</inject-code> </inject-code>

View file

@ -200,9 +200,6 @@
<object-type name="QNetworkCookieJar"/> <object-type name="QNetworkCookieJar"/>
<object-type name="QNetworkReply"> <object-type name="QNetworkReply">
<enum-type name="NetworkError"/> <enum-type name="NetworkError"/>
<modify-function signature="error()const">
<rename to="errorCode" />
</modify-function>
</object-type> </object-type>
<value-type name="QHostAddress" hash-function="qHash"> <value-type name="QHostAddress" hash-function="qHash">

View file

@ -21,17 +21,21 @@
*/ */
#include "dynamicqmetaobject.h" #include "dynamicqmetaobject.h"
#include "dynamicqmetaobject_p.h"
#include <QByteArray> #include <QByteArray>
#include <QString> #include <QString>
#include <QStringList> #include <QStringList>
#include <QList> #include <QList>
#include <QLinkedList>
#include <QObject> #include <QObject>
#include <cstring> #include <cstring>
#include <QDebug> #include <QDebug>
#include <QMetaMethod> #include <QMetaMethod>
#include "qsignal.h" #include "qsignal.h"
#include "qsignal_p.h"
#include "qproperty.h" #include "qproperty.h"
#include "qproperty_p.h"
#define MAX_SIGNALS_COUNT 50 #define MAX_SIGNALS_COUNT 50
#define MAX_SLOTS_COUNT 50 #define MAX_SLOTS_COUNT 50
@ -66,6 +70,18 @@ enum PropertyFlags {
Notify = 0x00400000 Notify = 0x00400000
}; };
class DynamicQMetaObject::DynamicQMetaObjectPrivate
{
public:
QLinkedList<MethodData> m_signals;
QLinkedList<MethodData> m_slots;
QLinkedList<PropertyData> m_properties;
QByteArray m_className;
void updateMetaObject(QMetaObject* metaObj);
void writeMethodsData(QLinkedList<MethodData>& methods, unsigned int** data, QList<QByteArray>* strings, int* prtIndex, int maxCount, int nullIndex, int flags);
};
static int registerString(const QByteArray& s, QList<QByteArray>* strings) static int registerString(const QByteArray& s, QList<QByteArray>* strings)
{ {
int idx = 0; int idx = 0;
@ -145,39 +161,39 @@ uint PropertyData::flags() const
else if (!isQRealType(typeName)) else if (!isQRealType(typeName))
flags |= qvariant_nameToType(typeName) << 24; flags |= qvariant_nameToType(typeName) << 24;
if (qproperty_is_readble(m_data)) if (qpropertyIsReadable(m_data))
flags |= Readable; flags |= Readable;
if (qproperty_is_writable(m_data)) if (qpropertyIsWritable(m_data))
flags |= Writable; flags |= Writable;
if (qproperty_has_reset(m_data)) if (qpropertyHasReset(m_data))
flags |= Resettable; flags |= Resettable;
if (!qproperty_is_designable(m_data)) if (!qpropertyIsDesignable(m_data))
flags |= ResolveDesignable; flags |= ResolveDesignable;
else else
flags |= Designable; flags |= Designable;
if (!qproperty_is_scriptable(m_data)) if (!qpropertyIsScriptable(m_data))
flags |= ResolveScriptable; flags |= ResolveScriptable;
else else
flags |= Scriptable; flags |= Scriptable;
if (!qproperty_is_stored(m_data)) if (!qpropertyIsStored(m_data))
flags |= ResolveStored; flags |= ResolveStored;
else else
flags |= Stored; flags |= Stored;
if (!qproperty_is_user(m_data)) if (!qpropertyIsUser(m_data))
flags |= ResolveUser; flags |= ResolveUser;
else else
flags |= User; flags |= User;
if (qproperty_is_constant(m_data)) if (qpropertyIsConstant(m_data))
flags |= Constant; flags |= Constant;
if (qproperty_is_final(m_data)) if (qpropertyIsFinal(m_data))
flags |= Final; flags |= Final;
return flags; return flags;
@ -241,7 +257,7 @@ PropertyData::PropertyData(const char* name, PyObject* data)
QByteArray PropertyData::type() const QByteArray PropertyData::type() const
{ {
return QByteArray(qproperty_get_type(m_data)); return QByteArray(qpropertyGetType(m_data));
} }
@ -266,76 +282,77 @@ bool PropertyData::operator==(const char* name) const
} }
DynamicQMetaObject::DynamicQMetaObject(const char* className, const QMetaObject* metaObject) DynamicQMetaObject::DynamicQMetaObject(const char* className, const QMetaObject* metaObject) : m_d(new DynamicQMetaObjectPrivate)
{ {
d.superdata = metaObject; d.superdata = metaObject;
d.stringdata = 0; d.stringdata = 0;
d.data = 0; d.data = 0;
d.extradata = 0; d.extradata = 0;
m_className = QByteArray(className); m_d->m_className = QByteArray(className);
updateMetaObject(); m_d->updateMetaObject(this);
} }
DynamicQMetaObject::~DynamicQMetaObject() DynamicQMetaObject::~DynamicQMetaObject()
{ {
delete[] d.stringdata; delete[] d.stringdata;
delete[] d.data; delete[] d.data;
delete m_d;
} }
void DynamicQMetaObject::addSignal(const char* signal, const char* type) void DynamicQMetaObject::addSignal(const char* signal, const char* type)
{ {
QLinkedList<MethodData>::iterator i = qFind(m_signals.begin(), m_signals.end(), signal); QLinkedList<MethodData>::iterator i = qFind(m_d->m_signals.begin(), m_d->m_signals.end(), signal);
if (i != m_signals.end()) if (i != m_d->m_signals.end())
return; return;
//search for a empty space //search for a empty space
MethodData blank; MethodData blank;
i = qFind(m_signals.begin(), m_signals.end(), blank); i = qFind(m_d->m_signals.begin(), m_d->m_signals.end(), blank);
if (i != m_signals.end()) { if (i != m_d->m_signals.end()) {
*i = MethodData(signal, type); *i = MethodData(signal, type);
updateMetaObject(); m_d->updateMetaObject(this);
return; return;
} }
int maxSignals = maxSignalsCount(m_className); int maxSignals = maxSignalsCount(m_d->m_className);
if (m_signals.size() >= maxSignals) { if (m_d->m_signals.size() >= maxSignals) {
qWarning() << "Fail to add dynamic signal to QObject. PySide support at most" << maxSignals << "dynamic signals."; qWarning() << "Fail to add dynamic signal to QObject. PySide support at most" << maxSignals << "dynamic signals.";
return; return;
} }
m_signals << MethodData(signal, type); m_d->m_signals << MethodData(signal, type);
updateMetaObject(); m_d->updateMetaObject(this);
} }
void DynamicQMetaObject::addSlot(const char* slot, const char* type) void DynamicQMetaObject::addSlot(const char* slot, const char* type)
{ {
QLinkedList<MethodData>::iterator i = qFind(m_slots.begin(), m_slots.end(), slot); QLinkedList<MethodData>::iterator i = qFind(m_d->m_slots.begin(), m_d->m_slots.end(), slot);
if (i != m_slots.end()) if (i != m_d->m_slots.end())
return; return;
int maxSlots = maxSlotsCount(m_className); int maxSlots = maxSlotsCount(m_d->m_className);
if (m_slots.size() >= maxSlots) { if (m_d->m_slots.size() >= maxSlots) {
qWarning() << "Fail to add dynamic slot to QObject. PySide support at most" << maxSlots << "dynamic slots."; qWarning() << "Fail to add dynamic slot to QObject. PySide support at most" << maxSlots << "dynamic slots.";
return; return;
} }
//search for a empty space //search for a empty space
MethodData blank; MethodData blank;
i = qFind(m_slots.begin(), m_slots.end(), blank); i = qFind(m_d->m_slots.begin(), m_d->m_slots.end(), blank);
if (i != m_slots.end()) if (i != m_d->m_slots.end())
*i = MethodData(slot, type); *i = MethodData(slot, type);
else else
m_slots << MethodData(slot, type); m_d->m_slots << MethodData(slot, type);
updateMetaObject(); m_d->updateMetaObject(this);
} }
void DynamicQMetaObject::removeSlot(uint index) void DynamicQMetaObject::removeSlot(uint index)
{ {
QMetaMethod m = method(index); QMetaMethod m = method(index);
foreach(MethodData md, m_slots) { foreach(MethodData md, m_d->m_slots) {
if (md.signature() == m.signature()) { if (md.signature() == m.signature()) {
md.clear(); md.clear();
updateMetaObject(); m_d->updateMetaObject(this);
break; break;
} }
} }
@ -343,19 +360,19 @@ void DynamicQMetaObject::removeSlot(uint index)
void DynamicQMetaObject::addProperty(const char* property, PyObject* data) void DynamicQMetaObject::addProperty(const char* property, PyObject* data)
{ {
QLinkedList<PropertyData>::iterator i = qFind(m_properties.begin(), m_properties.end(), property); QLinkedList<PropertyData>::iterator i = qFind(m_d->m_properties.begin(), m_d->m_properties.end(), property);
if (i != m_properties.end()) if (i != m_d->m_properties.end())
return; return;
//search for a empty space //search for a empty space
PropertyData blank; PropertyData blank;
i = qFind(m_properties.begin(), m_properties.end(), blank); i = qFind(m_d->m_properties.begin(), m_d->m_properties.end(), blank);
if (i != m_properties.end()) { if (i != m_d->m_properties.end()) {
*i = PropertyData(property, data); *i = PropertyData(property, data);
} else { } else {
m_properties << PropertyData(property, data); m_d->m_properties << PropertyData(property, data);
} }
updateMetaObject(); m_d->updateMetaObject(this);
} }
@ -372,19 +389,19 @@ DynamicQMetaObject* DynamicQMetaObject::createBasedOn(PyObject* pyObj, PyTypeObj
while (PyDict_Next(type->tp_dict, &pos, &key, &value)) { while (PyDict_Next(type->tp_dict, &pos, &key, &value)) {
//Register properties //Register properties
if (value->ob_type == &QProperty_Type) { if (value->ob_type == &PySideQPropertyType) {
mo->addProperty(PyString_AsString(key), value); mo->addProperty(PyString_AsString(key), value);
} }
//Register signals //Register signals
if (value->ob_type == &Signal_Type) { if (value->ob_type == &PySideSignalType) {
PyObject *attr = PyObject_GetAttr(pyObj, key); PyObject *attr = PyObject_GetAttr(pyObj, key);
SignalInstanceData *data = reinterpret_cast<SignalInstanceData*>(attr); PySideSignalInstanceData *data = reinterpret_cast<PySideSignalInstanceData*>(attr);
while(data) { while(data) {
int index = base->indexOfSignal(data->signature); int index = base->indexOfSignal(data->signature);
if (index == -1) if (index == -1)
mo->addSignal(data->signature); mo->addSignal(data->signature);
data = reinterpret_cast<SignalInstanceData*>(data->next); data = reinterpret_cast<PySideSignalInstanceData*>(data->next);
} }
} }
@ -412,37 +429,37 @@ 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);
foreach(MethodData md, m_signals) { foreach(MethodData md, m_d->m_signals) {
if (md.signature() == m.signature()) { if (md.signature() == m.signature()) {
md.clear(); md.clear();
updateMetaObject(); m_d->updateMetaObject(this);
break; break;
} }
} }
} }
void DynamicQMetaObject::writeMethodsData(QLinkedList<MethodData>& methods, void DynamicQMetaObject::DynamicQMetaObjectPrivate::writeMethodsData(QLinkedList<MethodData>& methods,
unsigned int **data, unsigned int** data,
QList<QByteArray> *strings, QList<QByteArray>* strings,
int *prtIndex, int* prtIndex,
int max_count, int maxCount,
int null_index, int nullIndex,
int flags) int flags)
{ {
int index = *prtIndex; int index = *prtIndex;
QLinkedList<MethodData>::iterator iMethod = methods.begin(); QLinkedList<MethodData>::iterator iMethod = methods.begin();
for(int i=0; i < max_count; i++) { for(int i=0; i < maxCount; i++) {
QByteArray mType; QByteArray mType;
if (iMethod != methods.end() && ((*iMethod).signature().size() > 0) ) { if (iMethod != methods.end() && ((*iMethod).signature().size() > 0) ) {
(*data)[index++] = registerString((*iMethod).signature(), strings); // func name (*data)[index++] = registerString((*iMethod).signature(), strings); // func name
mType = (*iMethod).type(); mType = (*iMethod).type();
} else { } else {
(*data)[index++] = null_index; // func name (*data)[index++] = nullIndex; // func name
} }
(*data)[index++] = null_index; // arguments (*data)[index++] = nullIndex; // arguments
(*data)[index++] = (mType.size() > 0 ? registerString(mType, strings) : null_index); // normalized type (*data)[index++] = (mType.size() > 0 ? registerString(mType, strings) : nullIndex); // normalized type
(*data)[index++] = null_index; // tags (*data)[index++] = nullIndex; // tags
(*data)[index++] = flags; (*data)[index++] = flags;
if (iMethod != methods.end()) if (iMethod != methods.end())
iMethod++; iMethod++;
@ -451,7 +468,7 @@ void DynamicQMetaObject::writeMethodsData(QLinkedList<MethodData>& methods,
*prtIndex = index; *prtIndex = index;
} }
void DynamicQMetaObject::updateMetaObject() void DynamicQMetaObject::DynamicQMetaObjectPrivate::updateMetaObject(QMetaObject* metaObj)
{ {
// these values are from moc source code, generator.cpp:66 // these values are from moc source code, generator.cpp:66
enum MethodFlags { enum MethodFlags {
@ -485,7 +502,7 @@ void DynamicQMetaObject::updateMetaObject()
const int HEADER_LENGHT = sizeof(header)/sizeof(int); const int HEADER_LENGHT = sizeof(header)/sizeof(int);
header[5] = HEADER_LENGHT; header[5] = HEADER_LENGHT;
// header size + 5 indexes per method + an ending zero // header size + 5 indexes per method + an ending zero
delete[] d.data; delete[] metaObj->d.data;
unsigned int* data; unsigned int* data;
data = new unsigned int[HEADER_LENGHT + n_methods*5 + n_properties*3 + 1]; data = new unsigned int[HEADER_LENGHT + n_methods*5 + n_properties*3 + 1];
std::memcpy(data, header, sizeof(header)); std::memcpy(data, header, sizeof(header));
@ -524,9 +541,14 @@ void DynamicQMetaObject::updateMetaObject()
str.append(char(0)); str.append(char(0));
} }
delete[] d.stringdata; delete[] metaObj->d.stringdata;
char* stringData = new char[str.count()]; char* stringData = new char[str.count()];
std::copy(str.begin(), str.end(), stringData); std::copy(str.begin(), str.end(), stringData);
d.data = data; metaObj->d.data = data;
d.stringdata = stringData; metaObj->d.stringdata = stringData;
}
void PySide::deleteDynamicQMetaObject(void* data)
{
delete reinterpret_cast<DynamicQMetaObject*>(data);
} }

View file

@ -26,59 +26,18 @@
#include "pysidemacros.h" #include "pysidemacros.h"
#include <Python.h> #include <Python.h>
#include <QMetaObject> #include <QMetaObject>
#include <QLinkedList>
#include <QByteArray>
#include <QSharedPointer>
#define PYSIDE_SLOT_LIST_ATTR "_slots"
class QObject;
namespace PySide namespace PySide
{ {
class MethodData
{
public:
MethodData(){}
MethodData(const char* signature, const char* type);
void clear();
bool isValid() const;
QByteArray signature() const;
QByteArray type() const;
bool operator==(const MethodData& other) const;
bool operator==(const char* other) const;
private:
QSharedPointer<QByteArray> m_signature;
QSharedPointer<QByteArray> m_type;
};
class PropertyData
{
public:
PropertyData();
PropertyData(const char*name, PyObject *data);
QByteArray name() const;
QByteArray type() const;
uint flags() const;
bool isValid() const;
bool operator==(const PropertyData& other) const;
bool operator==(const char* name) const;
private:
QByteArray m_name;
PyObject* m_data;
};
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, const char* type=0); void addSignal(const char* signal, const char* type = 0);
void addSlot(const char* slot, const char* type=0); void addSlot(const char* slot, const char* type = 0);
void addProperty(const char* property, PyObject* data); void addProperty(const char* property, PyObject* data);
void removeSignal(uint idex); void removeSignal(uint idex);
@ -89,19 +48,11 @@ public:
static DynamicQMetaObject* createBasedOn(PyObject* obj, PyTypeObject* type, const QMetaObject* base); static DynamicQMetaObject* createBasedOn(PyObject* obj, PyTypeObject* type, const QMetaObject* base);
private: private:
QLinkedList<MethodData> m_signals; class DynamicQMetaObjectPrivate;
QLinkedList<MethodData> m_slots; DynamicQMetaObjectPrivate* m_d;
QLinkedList<PropertyData> m_properties;
QByteArray m_className;
void updateMetaObject();
void writeMethodsData(QLinkedList<MethodData>& methods, unsigned int **data, QList<QByteArray> *strings, int *index, int max_count, int null_index, int flags);
}; };
PYSIDE_API inline void deleteDynamicQMetaObject(void* data) PYSIDE_API void deleteDynamicQMetaObject(void* data);
{
delete reinterpret_cast<DynamicQMetaObject*>(data);
}
} }
#endif #endif

View file

@ -0,0 +1,69 @@
/*
* This file is part of the PySide project.
*
* Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
*
* Contact: PySide team <contact@pyside.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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 library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef DYNAMICMETAPROPERTY_P_H
#define DYNAMICMETAPROPERTY_P_H
#include <Python.h>
#include <QByteArray>
#include <QSharedPointer>
#define PYSIDE_SLOT_LIST_ATTR "_slots"
namespace PySide
{
class MethodData
{
public:
MethodData(){}
MethodData(const char* signature, const char* type);
void clear();
bool isValid() const;
QByteArray signature() const;
QByteArray type() const;
bool operator==(const MethodData& other) const;
bool operator==(const char* other) const;
private:
QSharedPointer<QByteArray> m_signature;
QSharedPointer<QByteArray> m_type;
};
class PropertyData
{
public:
PropertyData();
PropertyData(const char* name, PyObject* data);
QByteArray name() const;
QByteArray type() const;
uint flags() const;
bool isValid() const;
bool operator==(const PropertyData& other) const;
bool operator==(const char* name) const;
private:
QByteArray m_name;
PyObject* m_data;
};
}
#endif

View file

@ -22,18 +22,17 @@
#include "pyside.h" #include "pyside.h"
#include "signalmanager.h"
#include "qproperty.h"
#include "qsignal.h"
#include <basewrapper.h> #include <basewrapper.h>
#include <conversions.h> #include <conversions.h>
#include <algorithm> #include <algorithm>
#include <cctype> #include <cctype>
#include <QStack> #include <QStack>
#include "signalmanager.h"
extern "C" void init_signal(PyObject* module); #include "qproperty_p.h"
extern "C" void init_slot(PyObject* module); #include "qproperty.h"
extern "C" void init_qproperty(PyObject* module); #include "qsignal.h"
#include "qsignal_p.h"
#include "qslot_p.h"
static QStack<PySide::CleanupFunction> cleanupFunctionList; static QStack<PySide::CleanupFunction> cleanupFunctionList;
@ -42,9 +41,9 @@ namespace PySide
void init(PyObject *module) void init(PyObject *module)
{ {
init_signal(module); initSignalSupport(module);
init_slot(module); initSlotSupport(module);
init_qproperty(module); initQProperty(module);
// Init signal manager, so it will register some meta types used by QVariant. // Init signal manager, so it will register some meta types used by QVariant.
SignalManager::instance(); SignalManager::instance();
} }
@ -69,13 +68,13 @@ bool fillQtProperties(PyObject* qObj, const QMetaObject* metaObj, PyObject* kwds
} else { } else {
PyObject* attr = PyObject_GenericGetAttr(qObj, key); PyObject* attr = PyObject_GenericGetAttr(qObj, key);
if (isQPropertyType(attr)) if (isQPropertyType(attr))
PySide::qproperty_set(attr, qObj, value); PySide::qpropertySet(attr, qObj, value);
} }
} else { } else {
propName.append("()"); propName.append("()");
if (metaObj->indexOfSignal(propName) != -1) { if (metaObj->indexOfSignal(propName) != -1) {
propName.prepend('2'); propName.prepend('2');
PySide::signal_connect(qObj, propName, value); PySide::signalConnect(qObj, propName, value);
} else { } else {
PyErr_Format(PyExc_AttributeError, "'%s' is not a Qt property or a signal", propName.constData()); PyErr_Format(PyExc_AttributeError, "'%s' is not a Qt property or a signal", propName.constData());
return false; return false;

View file

@ -25,17 +25,39 @@
#include <QDebug> #include <QDebug>
#include "qproperty.h" #include "qproperty.h"
#include "qproperty_p.h"
#include "dynamicqmetaobject_p.h"
#define QPROPERTY_CLASS_NAME "Property" #define QPROPERTY_CLASS_NAME "Property"
namespace PySide char* translateTypeName(PyObject* type)
{ {
if (PyType_Check(type)) {
char* typeName = 0;
if (type->ob_type == &Shiboken::SbkBaseWrapperType_Type) {
Shiboken::SbkBaseWrapperType* objType = reinterpret_cast<Shiboken::SbkBaseWrapperType*>(type);
typeName = strdup(objType->original_name);
} else {
//tp_name return the full name
Shiboken::AutoDecRef otypeName(PyObject_GetAttrString(type, "__name__"));
typeName = strdup(PyString_AS_STRING(otypeName.object()));
}
if (Shiboken::TypeResolver::getType(typeName) == Shiboken::TypeResolver::ObjectType) {
typeName = reinterpret_cast<char*>(realloc(typeName, strlen(typeName) + 1));
typeName = strcat(typeName, "*");
}
return typeName;
} else if (PyString_Check(type)) {
return strdup(PyString_AS_STRING(type));
}
return 0;
}
extern "C" extern "C"
{ {
typedef struct { struct PySideQPropertyData {
PyObject_HEAD PyObject_HEAD
char* typeName; char* typeName;
PyObject* type; PyObject* type;
@ -50,19 +72,16 @@ typedef struct {
bool user; bool user;
bool constant; bool constant;
bool final; bool final;
} QPropertyData; };
static int qproperty_init(PyObject*, PyObject*, PyObject*); static int qpropertyTpInit(PyObject*, PyObject*, PyObject*);
static void qproperty_free(void*); static void qpropertyFree(void*);
//aux PyTypeObject PySideQPropertyType = {
static char* translate_type_name(PyObject*);
PyTypeObject QProperty_Type = {
PyObject_HEAD_INIT(0) PyObject_HEAD_INIT(0)
0, /*ob_size*/ 0, /*ob_size*/
QPROPERTY_CLASS_NAME, /*tp_name*/ QPROPERTY_CLASS_NAME, /*tp_name*/
sizeof(QPropertyData), /*tp_basicsize*/ sizeof(PySideQPropertyData), /*tp_basicsize*/
0, /*tp_itemsize*/ 0, /*tp_itemsize*/
0, /*tp_dealloc*/ 0, /*tp_dealloc*/
0, /*tp_print*/ 0, /*tp_print*/
@ -95,10 +114,10 @@ PyTypeObject QProperty_Type = {
0, /*tp_descr_get */ 0, /*tp_descr_get */
0, /*tp_descr_set */ 0, /*tp_descr_set */
0, /*tp_dictoffset */ 0, /*tp_dictoffset */
(initproc)qproperty_init, /*tp_init */ qpropertyTpInit, /*tp_init */
0, /*tp_alloc */ 0, /*tp_alloc */
PyType_GenericNew, /*tp_new */ PyType_GenericNew, /*tp_new */
qproperty_free, /*tp_free */ qpropertyFree, /*tp_free */
0, /*tp_is_gc */ 0, /*tp_is_gc */
0, /*tp_bases */ 0, /*tp_bases */
0, /*tp_mro */ 0, /*tp_mro */
@ -108,21 +127,10 @@ PyTypeObject QProperty_Type = {
0, /*tp_del */ 0, /*tp_del */
}; };
void init_qproperty(PyObject* module) int qpropertyTpInit(PyObject* self, PyObject* args, PyObject* kwds)
{
if (PyType_Ready(&QProperty_Type) < 0)
return;
Py_INCREF(&QProperty_Type);
PyModule_AddObject(module, QPROPERTY_CLASS_NAME, ((PyObject*)&QProperty_Type));
}
} // extern "C"
int qproperty_init(PyObject* self, PyObject* args, PyObject* kwds)
{ {
PyObject* type = 0; PyObject* type = 0;
QPropertyData *data = reinterpret_cast<QPropertyData*>(self); PySideQPropertyData *data = reinterpret_cast<PySideQPropertyData*>(self);
data->designable = true; data->designable = true;
data->scriptable = true; data->scriptable = true;
data->stored = true; data->stored = true;
@ -141,14 +149,14 @@ int qproperty_init(PyObject* self, PyObject* args, PyObject* kwds)
if (!data->fset && data->fget) if (!data->fset && data->fget)
data->constant = true; data->constant = true;
data->typeName = translate_type_name(type); data->typeName = translateTypeName(type);
return 1; return 1;
} }
void qproperty_free(void *self) void qpropertyFree(void *self)
{ {
PyObject *pySelf = reinterpret_cast<PyObject*>(self); PyObject *pySelf = reinterpret_cast<PyObject*>(self);
QPropertyData *data = reinterpret_cast<QPropertyData*>(self); PySideQPropertyData *data = reinterpret_cast<PySideQPropertyData*>(self);
free(data->typeName); free(data->typeName);
free(data->doc); free(data->doc);
@ -156,17 +164,33 @@ void qproperty_free(void *self)
pySelf->ob_type->tp_base->tp_free(self); pySelf->ob_type->tp_base->tp_free(self);
} }
} // extern "C"
namespace PySide
{
void initQProperty(PyObject* module)
{
if (PyType_Ready(&PySideQPropertyType) < 0)
return;
Py_INCREF(&PySideQPropertyType);
PyModule_AddObject(module, QPROPERTY_CLASS_NAME, ((PyObject*)&PySideQPropertyType));
}
bool isQPropertyType(PyObject* pyObj) bool isQPropertyType(PyObject* pyObj)
{ {
if (pyObj) { if (pyObj) {
return pyObj->ob_type == &QProperty_Type; return pyObj->ob_type == &PySideQPropertyType;
} }
return false; return false;
} }
int qproperty_set(PyObject* self, PyObject* source, PyObject* value) int qpropertySet(PyObject* self, PyObject* source, PyObject* value)
{ {
QPropertyData *data = reinterpret_cast<QPropertyData*>(self); PySideQPropertyData *data = reinterpret_cast<PySideQPropertyData*>(self);
if (data->fset) { if (data->fset) {
Shiboken::AutoDecRef args(PyTuple_New(2)); Shiboken::AutoDecRef args(PyTuple_New(2));
PyTuple_SET_ITEM(args, 0, source); PyTuple_SET_ITEM(args, 0, source);
@ -181,9 +205,9 @@ int qproperty_set(PyObject* self, PyObject* source, PyObject* value)
return -1; return -1;
} }
PyObject* qproperty_get(PyObject* self, PyObject* source) PyObject* qpropertyGet(PyObject* self, PyObject* source)
{ {
QPropertyData *data = reinterpret_cast<QPropertyData*>(self); PySideQPropertyData *data = reinterpret_cast<PySideQPropertyData*>(self);
if (data->fget) { if (data->fget) {
Shiboken::AutoDecRef args(PyTuple_New(1)); Shiboken::AutoDecRef args(PyTuple_New(1));
Py_INCREF(source); Py_INCREF(source);
@ -193,9 +217,9 @@ PyObject* qproperty_get(PyObject* self, PyObject* source)
return 0; return 0;
} }
int qproperty_reset(PyObject* self, PyObject* source) int qpropertyReset(PyObject* self, PyObject* source)
{ {
QPropertyData *data = reinterpret_cast<QPropertyData*>(self); PySideQPropertyData *data = reinterpret_cast<PySideQPropertyData*>(self);
if (data->freset) { if (data->freset) {
Shiboken::AutoDecRef args(PyTuple_New(1)); Shiboken::AutoDecRef args(PyTuple_New(1));
Py_INCREF(source); Py_INCREF(source);
@ -207,13 +231,13 @@ int qproperty_reset(PyObject* self, PyObject* source)
} }
const char* qproperty_get_type(PyObject* self) const char* qpropertyGetType(PyObject* self)
{ {
QPropertyData *data = reinterpret_cast<QPropertyData*>(self); PySideQPropertyData *data = reinterpret_cast<PySideQPropertyData*>(self);
return data->typeName; return data->typeName;
} }
PyObject* qproperty_get_object(PyObject* source, PyObject* name) PyObject* qpropertyGetObject(PyObject* source, PyObject* name)
{ {
PyObject* attr = PyObject_GenericGetAttr(source, name); PyObject* attr = PyObject_GenericGetAttr(source, name);
if (attr && isQPropertyType(attr)) if (attr && isQPropertyType(attr))
@ -226,80 +250,57 @@ PyObject* qproperty_get_object(PyObject* source, PyObject* name)
return 0; return 0;
} }
char* translate_type_name(PyObject* type) bool qpropertyIsReadable(PyObject* self)
{ {
if (PyType_Check(type)) { PySideQPropertyData *data = reinterpret_cast<PySideQPropertyData*>(self);
char *typeName = NULL;
if (type->ob_type == &Shiboken::SbkBaseWrapperType_Type) {
Shiboken::SbkBaseWrapperType *objType = reinterpret_cast<Shiboken::SbkBaseWrapperType*>(type);
typeName = strdup(objType->original_name);
} else {
//tp_name return the full name
Shiboken::AutoDecRef otypeName(PyObject_GetAttrString(type, "__name__"));
typeName = strdup(PyString_AS_STRING(otypeName.object()));
}
if (Shiboken::TypeResolver::getType(typeName) == Shiboken::TypeResolver::ObjectType) {
typeName = reinterpret_cast<char*>(realloc(typeName, strlen(typeName) + 1));
typeName = strcat(typeName, "*");
}
return typeName;
} else if (PyString_Check(type)) {
return strdup(PyString_AS_STRING(type));
}
return 0;
}
bool qproperty_is_readble(PyObject* self)
{
QPropertyData *data = reinterpret_cast<QPropertyData*>(self);
return (data->fget != 0); return (data->fget != 0);
} }
bool qproperty_is_writable(PyObject* self) bool qpropertyIsWritable(PyObject* self)
{ {
QPropertyData *data = reinterpret_cast<QPropertyData*>(self); PySideQPropertyData *data = reinterpret_cast<PySideQPropertyData*>(self);
return (data->fset != 0); return (data->fset != 0);
} }
bool qproperty_has_reset(PyObject* self) bool qpropertyHasReset(PyObject* self)
{ {
QPropertyData *data = reinterpret_cast<QPropertyData*>(self); PySideQPropertyData *data = reinterpret_cast<PySideQPropertyData*>(self);
return (data->freset != 0); return (data->freset != 0);
} }
bool qproperty_is_designable(PyObject* self) bool qpropertyIsDesignable(PyObject* self)
{ {
QPropertyData *data = reinterpret_cast<QPropertyData*>(self); PySideQPropertyData *data = reinterpret_cast<PySideQPropertyData*>(self);
return data->designable; return data->designable;
} }
bool qproperty_is_scriptable(PyObject* self) bool qpropertyIsScriptable(PyObject* self)
{ {
QPropertyData *data = reinterpret_cast<QPropertyData*>(self); PySideQPropertyData *data = reinterpret_cast<PySideQPropertyData*>(self);
return data->scriptable; return data->scriptable;
} }
bool qproperty_is_stored(PyObject* self) bool qpropertyIsStored(PyObject* self)
{ {
QPropertyData *data = reinterpret_cast<QPropertyData*>(self); PySideQPropertyData *data = reinterpret_cast<PySideQPropertyData*>(self);
return data->stored; return data->stored;
} }
bool qproperty_is_user(PyObject* self) bool qpropertyIsUser(PyObject* self)
{ {
QPropertyData *data = reinterpret_cast<QPropertyData*>(self); PySideQPropertyData *data = reinterpret_cast<PySideQPropertyData*>(self);
return data->user; return data->user;
} }
bool qproperty_is_constant(PyObject* self) bool qpropertyIsConstant(PyObject* self)
{ {
QPropertyData *data = reinterpret_cast<QPropertyData*>(self); PySideQPropertyData *data = reinterpret_cast<PySideQPropertyData*>(self);
return data->constant; return data->constant;
} }
bool qproperty_is_final(PyObject* self) bool qpropertyIsFinal(PyObject* self)
{ {
QPropertyData *data = reinterpret_cast<QPropertyData*>(self); PySideQPropertyData *data = reinterpret_cast<PySideQPropertyData*>(self);
return data->final; return data->final;
} }

View file

@ -30,11 +30,6 @@
namespace PySide namespace PySide
{ {
extern "C"
{
extern PYSIDE_API PyTypeObject QProperty_Type;
}; //extern "C"
PYSIDE_API bool isQPropertyType(PyObject* pyObj); PYSIDE_API bool isQPropertyType(PyObject* pyObj);
/** /**
@ -46,7 +41,7 @@ PYSIDE_API bool isQPropertyType(PyObject* pyObj);
* @param value The value to set in property * @param value The value to set in property
* @return Return 0 if ok or -1 if this function fail * @return Return 0 if ok or -1 if this function fail
**/ **/
PYSIDE_API int qproperty_set(PyObject* self, PyObject* source, PyObject* value); PYSIDE_API int qpropertySet(PyObject* self, PyObject* source, PyObject* value);
/** /**
* This function call get property function * This function call get property function
@ -56,27 +51,7 @@ PYSIDE_API int qproperty_set(PyObject* self, PyObject* source, PyObject* value);
* @param source The QObject witch has the property * @param source The QObject witch has the property
* @return Return the result of property get function or 0 if this fail * @return Return the result of property get function or 0 if this fail
**/ **/
PYSIDE_API PyObject* qproperty_get(PyObject* self, PyObject* source); PYSIDE_API PyObject* qpropertyGet(PyObject* self, PyObject* source);
/**
* This function call reset property function
* This function does not check the property object type
*
* @param self The property object
* @param source The QObject witch has the property
* @return Return 0 if ok or -1 if this function fail
**/
PYSIDE_API int qproperty_reset(PyObject* self, PyObject* source);
/**
* This function return the property type
* This function does not check the property object type
*
* @param self The property object
* @return Return the property type name
**/
PYSIDE_API const char* qproperty_get_type(PyObject* self);
/** /**
* This function search in the source object for desired property * This function search in the source object for desired property
@ -85,90 +60,7 @@ PYSIDE_API const char* qproperty_get_type(PyObject* self);
* @param name The property name * @param name The property name
* @return Return a new reference to property object * @return Return a new reference to property object
**/ **/
PYSIDE_API PyObject* qproperty_get_object(PyObject* source, PyObject* name); PYSIDE_API PyObject* qpropertyGetObject(PyObject* source, PyObject* name);
/**
* This function check if property has read function
* This function does not check the property object type
*
* @param self The property object
* @return Return a boolean value
**/
PYSIDE_API bool qproperty_is_readble(PyObject* self);
/**
* This function check if property has write function
* This function does not check the property object type
*
* @param self The property object
* @return Return a boolean value
**/
PYSIDE_API bool qproperty_is_writable(PyObject* self);
/**
* This function check if property has reset function
* This function does not check the property object type
*
* @param self The property object
* @return Return a boolean value
**/
PYSIDE_API bool qproperty_has_reset(PyObject* self);
/**
* This function check if property has the flag DESIGNABLE setted
* This function does not check the property object type
*
* @param self The property object
* @return Return a boolean value
**/
PYSIDE_API bool qproperty_is_designable(PyObject* self);
/**
* This function check if property has the flag SCRIPTABLE setted
* This function does not check the property object type
*
* @param self The property object
* @return Return a boolean value
**/
PYSIDE_API bool qproperty_is_scriptable(PyObject* self);
/**
* This function check if property has the flag STORED setted
* This function does not check the property object type
*
* @param self The property object
* @return Return a boolean value
**/
PYSIDE_API bool qproperty_is_stored(PyObject* self);
/**
* This function check if property has the flag USER setted
* This function does not check the property object type
*
* @param self The property object
* @return Return a boolean value
**/
PYSIDE_API bool qproperty_is_user(PyObject* self);
/**
* This function check if property has the flag CONSTANT setted
* This function does not check the property object type
*
* @param self The property object
* @return Return a boolean value
**/
PYSIDE_API bool qproperty_is_constant(PyObject* self);
/**
* This function check if property has the flag FINAL setted
* This function does not check the property object type
*
* @param self The property object
* @return Return a boolean value
**/
PYSIDE_API bool qproperty_is_final(PyObject* self);
} //namespace PySide } //namespace PySide

144
libpyside/qproperty_p.h Normal file
View file

@ -0,0 +1,144 @@
/*
* This file is part of the PySide project.
*
* Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
*
* Contact: PySide team <contact@pyside.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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 library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef PYSIDE_QPROPERTY_P_H
#define PYSIDE_QPROPERTY_P_H
#include <Python.h>
extern "C"
{
extern PyTypeObject PySideQPropertyType;
}; //extern "C"
namespace PySide
{
/**
* Init PySide QProperty support system
*/
void initQProperty(PyObject* module);
/**
* This function call reset property function
* This function does not check the property object type
*
* @param self The property object
* @param source The QObject witch has the property
* @return Return 0 if ok or -1 if this function fail
**/
int qpropertyReset(PyObject* self, PyObject* source);
/**
* This function return the property type
* This function does not check the property object type
*
* @param self The property object
* @return Return the property type name
**/
const char* qpropertyGetType(PyObject* self);
/**
* This function check if property has read function
* This function does not check the property object type
*
* @param self The property object
* @return Return a boolean value
**/
bool qpropertyIsReadable(PyObject* self);
/**
* This function check if property has write function
* This function does not check the property object type
*
* @param self The property object
* @return Return a boolean value
**/
bool qpropertyIsWritable(PyObject* self);
/**
* This function check if property has reset function
* This function does not check the property object type
*
* @param self The property object
* @return Return a boolean value
**/
bool qpropertyHasReset(PyObject* self);
/**
* This function check if property has the flag DESIGNABLE setted
* This function does not check the property object type
*
* @param self The property object
* @return Return a boolean value
**/
bool qpropertyIsDesignable(PyObject* self);
/**
* This function check if property has the flag SCRIPTABLE setted
* This function does not check the property object type
*
* @param self The property object
* @return Return a boolean value
**/
bool qpropertyIsScriptable(PyObject* self);
/**
* This function check if property has the flag STORED setted
* This function does not check the property object type
*
* @param self The property object
* @return Return a boolean value
**/
bool qpropertyIsStored(PyObject* self);
/**
* This function check if property has the flag USER setted
* This function does not check the property object type
*
* @param self The property object
* @return Return a boolean value
**/
bool qpropertyIsUser(PyObject* self);
/**
* This function check if property has the flag CONSTANT setted
* This function does not check the property object type
*
* @param self The property object
* @return Return a boolean value
**/
bool qpropertyIsConstant(PyObject* self);
/**
* This function check if property has the flag FINAL setted
* This function does not check the property object type
*
* @param self The property object
* @return Return a boolean value
**/
bool qpropertyIsFinal(PyObject* self);
} // namespace PySide
#endif

View file

@ -25,181 +25,313 @@
#include <QDebug> #include <QDebug>
#include "qsignal.h" #include "qsignal.h"
#include "qsignal_p.h"
#include "signalmanager.h" #include "signalmanager.h"
#define SIGNAL_CLASS_NAME "Signal" #define SIGNAL_CLASS_NAME "Signal"
#define QT_SIGNAL_SENTINEL "2" #define QT_SIGNAL_SENTINEL "2"
struct SignalData;
namespace PySide namespace PySide
{ {
//aux
static char* signalBuildSignature(const char*, const char*);
static void signalAppendSignature(SignalData*, char*);
static void signalInstanceInitialize(PyObject*, PyObject*, SignalData*, PyObject *, int);
static char* signalParseSignature(PyObject*);
static PyObject* signalBuildQtCompatible(const char*);
}
extern "C" extern "C"
{ {
char* get_type_name(PyObject*); struct SignalData {
typedef struct {
PyObject_HEAD PyObject_HEAD
bool initialized; bool initialized;
char* signalName; char* signalName;
char** signatures; char** signatures;
int signaturesSize; int signaturesSize;
} SignalData; PyObject* homonymousMethod;
};
static int signal_init(PyObject*, PyObject*, PyObject*); static int signalTpInit(PyObject*, PyObject*, PyObject*);
static void signal_free(void*); static void signalFree(void*);
static void signal_instance_free(void*); static void signalInstanceFree(void*);
//methods //methods
static PyObject* signal_instance_connect(PyObject*, PyObject*, PyObject*); static PyObject* signalInstanceConnect(PyObject*, PyObject*, PyObject*);
static PyObject* signal_instance_disconnect(PyObject*, PyObject*); static PyObject* signalInstanceDisconnect(PyObject*, PyObject*);
static PyObject* signal_instance_emit(PyObject*, PyObject*); static PyObject* signalInstanceEmit(PyObject*, PyObject*);
static PyObject* signal_instance_get_item(PyObject*, PyObject*); static PyObject* signalInstanceGetItem(PyObject*, PyObject*);
//aux static PyObject* signalInstanceCall(PyObject* self, PyObject* args, PyObject* kw);
static char* signal_build_signature(const char*, const char*); static PyObject* signalCall(PyObject*, PyObject*, PyObject*);
static void signal_append_signature(SignalData*, char*);
static void signal_instance_initialize(PyObject*, PyObject*, SignalData*, PyObject *, int);
static char* signal_parse_signature(PyObject*);
static PyObject* signal_build_qt_compatible(const char*);
PyTypeObject Signal_Type = { PyTypeObject PySideSignalType = {
PyObject_HEAD_INIT(0) PyObject_HEAD_INIT(0)
0, /*ob_size*/ /*ob_size*/ 0,
"PySide.QtCore."SIGNAL_CLASS_NAME, /*tp_name*/ /*tp_name*/ "PySide.QtCore."SIGNAL_CLASS_NAME,
sizeof(SignalData), /*tp_basicsize*/ /*tp_basicsize*/ sizeof(SignalData),
0, /*tp_itemsize*/ /*tp_itemsize*/ 0,
0, /*tp_dealloc*/ /*tp_dealloc*/ &Shiboken::deallocWrapper,
0, /*tp_print*/ /*tp_print*/ 0,
0, /*tp_getattr*/ /*tp_getattr*/ 0,
0, /*tp_setattr*/ /*tp_setattr*/ 0,
0, /*tp_compare*/ /*tp_compare*/ 0,
0, /*tp_repr*/ /*tp_repr*/ 0,
0, /*tp_as_number*/ /*tp_as_number*/ 0,
0, /*tp_as_sequence*/ /*tp_as_sequence*/ 0,
0, /*tp_as_mapping*/ /*tp_as_mapping*/ 0,
0, /*tp_hash */ /*tp_hash*/ 0,
0, /*tp_call*/ /*tp_call*/ signalCall,
0, /*tp_str*/ /*tp_str*/ 0,
0, /*tp_getattro*/ /*tp_getattro*/ 0,
0, /*tp_setattro*/ /*tp_setattro*/ 0,
0, /*tp_as_buffer*/ /*tp_as_buffer*/ 0,
Py_TPFLAGS_DEFAULT, /*tp_flags*/ /*tp_flags*/ Py_TPFLAGS_DEFAULT,
SIGNAL_CLASS_NAME, /*tp_doc */ /*tp_doc*/ SIGNAL_CLASS_NAME,
0, /*tp_traverse */ /*tp_traverse*/ 0,
0, /*tp_clear */ /*tp_clear*/ 0,
0, /*tp_richcompare */ /*tp_richcompare*/ 0,
0, /*tp_weaklistoffset */ /*tp_weaklistoffset*/ 0,
0, /*tp_iter */ /*tp_iter*/ 0,
0, /*tp_iternext */ /*tp_iternext*/ 0,
0, /*tp_methods */ /*tp_methods*/ 0,
0, /*tp_members */ /*tp_members*/ 0,
0, /*tp_getset */ /*tp_getset*/ 0,
0, /*tp_base */ /*tp_base*/ 0,
0, /*tp_dict */ /*tp_dict*/ 0,
0, /*tp_descr_get */ /*tp_descr_get*/ 0,
0, /*tp_descr_set */ /*tp_descr_set*/ 0,
0, /*tp_dictoffset */ /*tp_dictoffset*/ 0,
signal_init, /*tp_init */ /*tp_init*/ signalTpInit,
0, /*tp_alloc */ /*tp_alloc*/ 0,
PyType_GenericNew, /*tp_new */ /*tp_new*/ PyType_GenericNew,
signal_free, /*tp_free */ /*tp_free*/ signalFree,
0, /*tp_is_gc */ /*tp_is_gc*/ 0,
0, /*tp_bases */ /*tp_bases*/ 0,
0, /*tp_mro */ /*tp_mro*/ 0,
0, /*tp_cache */ /*tp_cache*/ 0,
0, /*tp_subclasses */ /*tp_subclasses*/ 0,
0, /*tp_weaklist */ /*tp_weaklist*/ 0,
0, /*tp_del */ /*tp_del*/ 0,
}; };
static PyMethodDef SignalInstance_methods[] = { static PyMethodDef SignalInstance_methods[] = {
{"connect", (PyCFunction)signal_instance_connect, METH_VARARGS|METH_KEYWORDS, 0}, {"connect", (PyCFunction)signalInstanceConnect, METH_VARARGS|METH_KEYWORDS, 0},
{"disconnect", signal_instance_disconnect, METH_VARARGS, 0}, {"disconnect", signalInstanceDisconnect, METH_VARARGS, 0},
{"emit", signal_instance_emit, METH_VARARGS, 0}, {"emit", signalInstanceEmit, METH_VARARGS, 0},
{0} /* Sentinel */ {0} /* Sentinel */
}; };
static PyMappingMethods SignalInstance_as_mapping = { static PyMappingMethods SignalInstance_as_mapping = {
0, 0,
signal_instance_get_item, signalInstanceGetItem,
0 0
}; };
PyTypeObject SignalInstance_Type = { PyTypeObject PySideSignalInstanceType = {
PyObject_HEAD_INIT(0) PyObject_HEAD_INIT(0)
0, /*ob_size*/ /*ob_size*/ 0,
"PySide.QtCore."SIGNAL_CLASS_NAME, /*tp_name*/ /*tp_name*/ "PySide.QtCore."SIGNAL_CLASS_NAME,
sizeof(SignalInstanceData),/*tp_basicsize*/ /*tp_basicsize*/ sizeof(PySideSignalInstanceData),
0, /*tp_itemsize*/ /*tp_itemsize*/ 0,
0, /*tp_dealloc*/ /*tp_dealloc*/ 0,
0, /*tp_print*/ /*tp_print*/ 0,
0, /*tp_getattr*/ /*tp_getattr*/ 0,
0, /*tp_setattr*/ /*tp_setattr*/ 0,
0, /*tp_compare*/ /*tp_compare*/ 0,
0, /*tp_repr*/ /*tp_repr*/ 0,
0, /*tp_as_number*/ /*tp_as_number*/ 0,
0, /*tp_as_sequence*/ /*tp_as_sequence*/ 0,
&SignalInstance_as_mapping,/*tp_as_mapping*/ /*tp_as_mapping*/ &SignalInstance_as_mapping,
0, /*tp_hash */ /*tp_hash*/ 0,
0, /*tp_call*/ /*tp_call*/ signalInstanceCall,
0, /*tp_str*/ /*tp_str*/ 0,
0, /*tp_getattro*/ /*tp_getattro*/ 0,
0, /*tp_setattro*/ /*tp_setattro*/ 0,
0, /*tp_as_buffer*/ /*tp_as_buffer*/ 0,
Py_TPFLAGS_DEFAULT, /*tp_flags*/ /*tp_flags*/ Py_TPFLAGS_DEFAULT,
SIGNAL_CLASS_NAME, /*tp_doc */ /*tp_doc*/ SIGNAL_CLASS_NAME,
0, /*tp_traverse */ /*tp_traverse*/ 0,
0, /*tp_clear */ /*tp_clear*/ 0,
0, /*tp_richcompare */ /*tp_richcompare*/ 0,
0, /*tp_weaklistoffset */ /*tp_weaklistoffset*/ 0,
0, /*tp_iter */ /*tp_iter*/ 0,
0, /*tp_iternext */ /*tp_iternext*/ 0,
SignalInstance_methods, /*tp_methods */ /*tp_methods*/ SignalInstance_methods,
0, /*tp_members */ /*tp_members*/ 0,
0, /*tp_getset */ /*tp_getset*/ 0,
0, /*tp_base */ /*tp_base*/ 0,
0, /*tp_dict */ /*tp_dict*/ 0,
0, /*tp_descr_get */ /*tp_descr_get*/ 0,
0, /*tp_descr_set */ /*tp_descr_set*/ 0,
0, /*tp_dictoffset */ /*tp_dictoffset*/ 0,
0, /*tp_init */ /*tp_init*/ 0,
0, /*tp_alloc */ /*tp_alloc*/ 0,
PyType_GenericNew, /*tp_new */ /*tp_new*/ PyType_GenericNew,
signal_instance_free, /*tp_free */ /*tp_free*/ signalInstanceFree,
0, /*tp_is_gc */ /*tp_is_gc*/ 0,
0, /*tp_bases */ /*tp_bases*/ 0,
0, /*tp_mro */ /*tp_mro*/ 0,
0, /*tp_cache */ /*tp_cache*/ 0,
0, /*tp_subclasses */ /*tp_subclasses*/ 0,
0, /*tp_weaklist */ /*tp_weaklist*/ 0,
0, /*tp_del */ /*tp_del*/ 0,
}; };
int signalTpInit(PyObject* self, PyObject* args, PyObject* kwds)
void init_signal(PyObject* module)
{ {
if (PyType_Ready(&Signal_Type) < 0) static PyObject *emptyTuple = 0;
return; static const char *kwlist[] = {"name", 0};
char* argName = 0;
Py_INCREF(&Signal_Type); if (emptyTuple == 0)
PyModule_AddObject(module, SIGNAL_CLASS_NAME, ((PyObject*)&Signal_Type)); emptyTuple = PyTuple_New(0);
if (PyType_Ready(&SignalInstance_Type) < 0) if (!PyArg_ParseTupleAndKeywords(emptyTuple, kwds,
return; "|s:QtCore."SIGNAL_CLASS_NAME, (char**) kwlist, &argName))
return 0;
Py_INCREF(&SignalInstance_Type); bool tupledArgs = false;
SignalData *data = reinterpret_cast<SignalData*>(self);
if (argName) {
data->signalName = strdup(argName);
}
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) && !PyString_Check(arg)) {
tupledArgs = true;
PySide::signalAppendSignature(data, PySide::signalParseSignature(arg));
}
}
if (!tupledArgs)
PySide::signalAppendSignature(data, PySide::signalParseSignature(args));
return 1;
} }
void signalFree(void *self)
} // extern "C"
PyObject* signal_instance_get_item(PyObject* self, PyObject* key)
{ {
SignalInstanceData* data = reinterpret_cast<SignalInstanceData*>(self); PyObject *pySelf = reinterpret_cast<PyObject*>(self);
char* sigKey = signal_parse_signature(key); SignalData *data = reinterpret_cast<SignalData*>(self);
char* sig = signal_build_signature(data->signalName, sigKey);
for(int i = 0, i_max = data->signaturesSize; i < i_max; i++) {
if (data->signatures[i])
free(data->signatures[i]);
}
free(data->signatures);
free(data->signalName);
data->initialized = 0;
data->signaturesSize = 0;
Py_XDECREF(data->homonymousMethod);
data->homonymousMethod = 0;
pySelf->ob_type->tp_base->tp_free(self);
}
void signalInstanceFree(void* self)
{
PyObject *pySelf = reinterpret_cast<PyObject*>(self);
PySideSignalInstanceData *data = reinterpret_cast<PySideSignalInstanceData*>(self);
free(data->signalName);
free(data->signature);
Py_XDECREF(data->homonymousMethod);
if (data->next) {
Py_DECREF(data->next);
data->next = 0;
}
pySelf->ob_type->tp_base->tp_free(self);
}
PyObject* signalInstanceConnect(PyObject* self, PyObject* args, PyObject* kwds)
{
PyObject *slot = 0;
PyObject *type = 0;
static const char *kwlist[] = {"slot", "type", 0};
if (!PyArg_ParseTupleAndKeywords(args, kwds,
"O|O:"SIGNAL_CLASS_NAME, (char**) kwlist, &slot, &type))
return 0;
PySideSignalInstanceData *source = reinterpret_cast<PySideSignalInstanceData*>(self);
Shiboken::AutoDecRef pyArgs(PyList_New(0));
bool match = false;
if (slot->ob_type == &PySideSignalInstanceType) {
PySideSignalInstanceData *sourceWalk = source;
PySideSignalInstanceData *targetWalk;
//find best match
while(sourceWalk && !match) {
targetWalk = reinterpret_cast<PySideSignalInstanceData*>(slot);
while(targetWalk && !match) {
if (QMetaObject::checkConnectArgs(sourceWalk->signature, targetWalk->signature)) {
PyList_Append(pyArgs, sourceWalk->source);
Shiboken::AutoDecRef sourceSignature(PySide::signalBuildQtCompatible(sourceWalk->signature));
PyList_Append(pyArgs, sourceSignature);
PyList_Append(pyArgs, targetWalk->source);
Shiboken::AutoDecRef targetSignature(PySide::signalBuildQtCompatible(targetWalk->signature));
PyList_Append(pyArgs, targetSignature);
match = true;
}
targetWalk = reinterpret_cast<PySideSignalInstanceData*>(targetWalk->next);
}
sourceWalk = reinterpret_cast<PySideSignalInstanceData*>(sourceWalk->next);
}
} else {
//try the first signature
PyList_Append(pyArgs, source->source);
Shiboken::AutoDecRef signature(PySide::signalBuildQtCompatible(source->signature));
PyList_Append(pyArgs, signature);
PyList_Append(pyArgs, slot);
match = true;
}
if (type)
PyList_Append(pyArgs, type);
if (match) {
Shiboken::AutoDecRef tupleArgs(PyList_AsTuple(pyArgs));
Shiboken::AutoDecRef pyMethod(PyObject_GetAttrString(source->source, "connect"));
return PyObject_CallObject(pyMethod, tupleArgs);
}
return 0;
}
PyObject* signalInstanceEmit(PyObject* self, PyObject* args)
{
PySideSignalInstanceData *source = reinterpret_cast<PySideSignalInstanceData*>(self);
Shiboken::AutoDecRef pyArgs(PyList_New(0));
Shiboken::AutoDecRef sourceSignature(PySide::signalBuildQtCompatible(source->signature));
PyList_Append(pyArgs, sourceSignature);
for(Py_ssize_t i = 0, max = PyTuple_Size(args); 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);
}
PyObject* signalInstanceGetItem(PyObject* self, PyObject* key)
{
PySideSignalInstanceData* data = reinterpret_cast<PySideSignalInstanceData*>(self);
char* sigKey = PySide::signalParseSignature(key);
char* sig = PySide::signalBuildSignature(data->signalName, sigKey);
free(sigKey); free(sigKey);
const char* sigName = data->signalName; const char* sigName = data->signalName;
@ -210,7 +342,7 @@ PyObject* signal_instance_get_item(PyObject* self, PyObject* key)
Py_INCREF(result); Py_INCREF(result);
return result; return result;
} }
data = reinterpret_cast<SignalInstanceData*>(data->next); data = reinterpret_cast<PySideSignalInstanceData*>(data->next);
} }
PyErr_Format(PyExc_IndexError, "Signature %s not found for signal: %s", sig, sigName); PyErr_Format(PyExc_IndexError, "Signature %s not found for signal: %s", sig, sigName);
free(sig); free(sig);
@ -218,6 +350,100 @@ PyObject* signal_instance_get_item(PyObject* self, PyObject* key)
return 0; return 0;
} }
PyObject* signalInstanceDisconnect(PyObject* self, PyObject* args)
{
PySideSignalInstanceData *source = reinterpret_cast<PySideSignalInstanceData*>(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 == &PySideSignalInstanceType) {
PySideSignalInstanceData *target = reinterpret_cast<PySideSignalInstanceData*>(slot);
if (QMetaObject::checkConnectArgs(source->signature, target->signature)) {
PyList_Append(pyArgs, source->source);
Shiboken::AutoDecRef source_signature(PySide::signalBuildQtCompatible(source->signature));
PyList_Append(pyArgs, source_signature);
PyList_Append(pyArgs, target->source);
Shiboken::AutoDecRef target_signature(PySide::signalBuildQtCompatible(target->signature));
PyList_Append(pyArgs, target_signature);
match = true;
}
} else {
//try the first signature
PyList_Append(pyArgs, source->source);
Shiboken::AutoDecRef signature(PySide::signalBuildQtCompatible(source->signature));
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* signalCall(PyObject* self, PyObject* args, PyObject* kw)
{
SignalData* signalData = reinterpret_cast<SignalData*>(self);
if (!signalData->homonymousMethod) {
PyErr_SetString(PyExc_TypeError, "native Qt signal is not callable");
return 0;
}
descrgetfunc getDescriptor = signalData->homonymousMethod->ob_type->tp_descr_get;
Shiboken::AutoDecRef homonymousMethod(getDescriptor(signalData->homonymousMethod, 0, 0));
if (PyCFunction_GET_FLAGS(homonymousMethod.object()) & METH_STATIC)
return PyCFunction_Call(homonymousMethod, args, kw);
ternaryfunc callFunc = signalData->homonymousMethod->ob_type->tp_call;
return callFunc(homonymousMethod, args, kw);
}
PyObject* signalInstanceCall(PyObject* self, PyObject* args, PyObject* kw)
{
PySideSignalInstanceData* signalData = reinterpret_cast<PySideSignalInstanceData*>(self);
if (!signalData->homonymousMethod) {
PyErr_SetString(PyExc_TypeError, "native Qt signal is not callable");
return 0;
}
descrgetfunc getDescriptor = signalData->homonymousMethod->ob_type->tp_descr_get;
Shiboken::AutoDecRef homonymousMethod(getDescriptor(signalData->homonymousMethod, signalData->source, 0));
return PyCFunction_Call(homonymousMethod, args, kw);
}
} // extern "C"
namespace PySide
{
void initSignalSupport(PyObject* module)
{
if (PyType_Ready(&PySideSignalType) < 0)
return;
Py_INCREF(&PySideSignalType);
PyModule_AddObject(module, SIGNAL_CLASS_NAME, ((PyObject*)&PySideSignalType));
if (PyType_Ready(&PySideSignalInstanceType) < 0)
return;
Py_INCREF(&PySideSignalInstanceType);
}
void signalUpdateSource(PyObject* source) void signalUpdateSource(PyObject* source)
{ {
Shiboken::AutoDecRef attrs(PyObject_Dir(source)); Shiboken::AutoDecRef attrs(PyObject_Dir(source));
@ -225,15 +451,15 @@ void signalUpdateSource(PyObject* source)
for(int i = 0, iMax = PyList_GET_SIZE(attrs.object()); i < iMax; ++i) { for(int i = 0, iMax = PyList_GET_SIZE(attrs.object()); i < iMax; ++i) {
PyObject *attrName = PyList_GET_ITEM(attrs.object(), i); PyObject *attrName = PyList_GET_ITEM(attrs.object(), i);
Shiboken::AutoDecRef attr(PyObject_GetAttr(reinterpret_cast<PyObject*>(source->ob_type), attrName)); Shiboken::AutoDecRef attr(PyObject_GetAttr(reinterpret_cast<PyObject*>(source->ob_type), attrName));
if (!attr.isNull() && attr->ob_type == &Signal_Type) { if (!attr.isNull() && attr->ob_type == &PySideSignalType) {
Shiboken::AutoDecRef signalInstance((PyObject*)PyObject_New(SignalInstanceData, &SignalInstance_Type)); Shiboken::AutoDecRef signalInstance((PyObject*)PyObject_New(PySideSignalInstanceData, &PySideSignalInstanceType));
signal_instance_initialize(signalInstance, attrName, reinterpret_cast<SignalData*>(attr.object()), source, 0); signalInstanceInitialize(signalInstance, attrName, reinterpret_cast<SignalData*>(attr.object()), source, 0);
PyObject_SetAttr(source, attrName, signalInstance); PyObject_SetAttr(source, attrName, signalInstance);
} }
} }
} }
char* get_type_name(PyObject* type) char* getTypeName(PyObject* type)
{ {
if (PyType_Check(type)) { if (PyType_Check(type)) {
char *typeName = NULL; char *typeName = NULL;
@ -264,22 +490,22 @@ char* get_type_name(PyObject* type)
return 0; return 0;
} }
char* signal_build_signature(const char *name, const char *signature) char* signalBuildSignature(const char *name, const char *signature)
{ {
QString signal; QString signal;
signal.sprintf("%s(%s)", name, signature); signal.sprintf("%s(%s)", name, signature);
return strdup(QMetaObject::normalizedSignature(signal.toAscii())); return strdup(QMetaObject::normalizedSignature(signal.toAscii()));
} }
char* signal_parse_signature(PyObject *args) char* signalParseSignature(PyObject *args)
{ {
char *signature = 0; char *signature = 0;
if (args && (PyString_Check(args) || (!PySequence_Check(args) && (args != Py_None)))) if (args && (PyString_Check(args) || (!PySequence_Check(args) && (args != Py_None))))
return get_type_name(args); return getTypeName(args);
for(Py_ssize_t i = 0, i_max = PySequence_Size(args); i < i_max; i++) { for(Py_ssize_t i = 0, i_max = PySequence_Size(args); i < i_max; i++) {
Shiboken::AutoDecRef arg(PySequence_ITEM(args, i)); Shiboken::AutoDecRef arg(PySequence_ITEM(args, i));
char* typeName = get_type_name(arg); char* typeName = getTypeName(arg);
if (typeName) { if (typeName) {
if (signature) { if (signature) {
signature = reinterpret_cast<char*>(realloc(signature, (strlen(signature) + 1 + strlen(typeName)) * sizeof(char*))); signature = reinterpret_cast<char*>(realloc(signature, (strlen(signature) + 1 + strlen(typeName)) * sizeof(char*)));
@ -294,7 +520,7 @@ char* signal_parse_signature(PyObject *args)
return signature; return signature;
} }
void signal_append_signature(SignalData* self, char* signature) void signalAppendSignature(SignalData* self, char* signature)
{ {
self->signaturesSize++; self->signaturesSize++;
@ -306,75 +532,9 @@ void signal_append_signature(SignalData* self, char* signature)
self->signatures[self->signaturesSize-1] = signature; self->signatures[self->signaturesSize-1] = signature;
} }
int signal_init(PyObject* self, PyObject* args, PyObject* kwds) void signalInstanceInitialize(PyObject* instance, PyObject* name, SignalData* data, PyObject* source, int index)
{ {
static PyObject *emptyTuple = 0; PySideSignalInstanceData *self = reinterpret_cast<PySideSignalInstanceData*>(instance);
static const char *kwlist[] = {"name", 0};
char* argName = 0;
if (emptyTuple == 0)
emptyTuple = PyTuple_New(0);
if (!PyArg_ParseTupleAndKeywords(emptyTuple, kwds,
"|s:QtCore."SIGNAL_CLASS_NAME, (char**) kwlist, &argName))
return 0;
bool tupledArgs = false;
SignalData *data = reinterpret_cast<SignalData*>(self);
if (argName) {
data->signalName = strdup(argName);
}
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) && !PyString_Check(arg)) {
tupledArgs = true;
signal_append_signature(data, signal_parse_signature(arg));
}
}
if (!tupledArgs)
signal_append_signature(data, signal_parse_signature(args));
return 1;
}
void signal_free(void *self)
{
PyObject *pySelf = reinterpret_cast<PyObject*>(self);
SignalData *data = reinterpret_cast<SignalData*>(self);
for(int i = 0, i_max = data->signaturesSize; i < i_max; i++) {
if (data->signatures[i])
free(data->signatures[i]);
}
free(data->signatures);
free(data->signalName);
data->initialized = 0;
data->signaturesSize = 0;
pySelf->ob_type->tp_base->tp_free(self);
}
void signal_instance_free(void* self)
{
PyObject *pySelf = reinterpret_cast<PyObject*>(self);
SignalInstanceData *data = reinterpret_cast<SignalInstanceData*>(self);
free(data->signalName);
free(data->signature);
if (data->next) {
Py_XDECREF(data->next);
data->next = 0;
}
pySelf->ob_type->tp_base->tp_free(self);
}
void signal_instance_initialize(PyObject* instance, PyObject* name, SignalData* data, PyObject* source, int index)
{
SignalInstanceData *self = reinterpret_cast<SignalInstanceData*>(instance);
self->next = 0; self->next = 0;
if (data->signalName) if (data->signalName)
self->signalName = strdup(data->signalName); self->signalName = strdup(data->signalName);
@ -382,75 +542,21 @@ void signal_instance_initialize(PyObject* instance, PyObject* name, SignalData*
self->signalName = strdup(PyString_AsString(name)); self->signalName = strdup(PyString_AsString(name));
self->source = source; self->source = source;
self->signature = signal_build_signature(self->signalName, data->signatures[index]); self->signature = signalBuildSignature(self->signalName, data->signatures[index]);
self->homonymousMethod = 0;
if (data->homonymousMethod) {
self->homonymousMethod = data->homonymousMethod;
Py_INCREF(self->homonymousMethod);
}
index++; index++;
if (index < data->signaturesSize) { if (index < data->signaturesSize) {
self->next = reinterpret_cast<PyObject*>(PyObject_New(SignalInstanceData, &SignalInstance_Type)); self->next = reinterpret_cast<PyObject*>(PyObject_New(PySideSignalInstanceData, &PySideSignalInstanceType));
signal_instance_initialize(self->next, name, data, source, index); signalInstanceInitialize(self->next, name, data, source, index);
} }
} }
PyObject* signal_instance_connect(PyObject* self, PyObject* args, PyObject* kwds) bool signalConnect(PyObject* source, const char* signal, PyObject* callback)
{
PyObject *slot = 0;
PyObject *type = 0;
static const char *kwlist[] = {"slot", "type", 0};
if (!PyArg_ParseTupleAndKeywords(args, kwds,
"O|O:"SIGNAL_CLASS_NAME, (char**) kwlist, &slot, &type))
return 0;
SignalInstanceData *source = reinterpret_cast<SignalInstanceData*>(self);
Shiboken::AutoDecRef pyArgs(PyList_New(0));
bool match = false;
if (slot->ob_type == &SignalInstance_Type) {
SignalInstanceData *sourceWalk = source;
SignalInstanceData *targetWalk;
//find best match
while(sourceWalk && !match) {
targetWalk = reinterpret_cast<SignalInstanceData*>(slot);
while(targetWalk && !match) {
if (QMetaObject::checkConnectArgs(sourceWalk->signature, targetWalk->signature)) {
PyList_Append(pyArgs, sourceWalk->source);
Shiboken::AutoDecRef sourceSignature(signal_build_qt_compatible(sourceWalk->signature));
PyList_Append(pyArgs, sourceSignature);
PyList_Append(pyArgs, targetWalk->source);
Shiboken::AutoDecRef targetSignature(signal_build_qt_compatible(targetWalk->signature));
PyList_Append(pyArgs, targetSignature);
match = true;
}
targetWalk = reinterpret_cast<SignalInstanceData*>(targetWalk->next);
}
sourceWalk = reinterpret_cast<SignalInstanceData*>(sourceWalk->next);
}
} else {
//try the first signature
PyList_Append(pyArgs, source->source);
Shiboken::AutoDecRef signature(signal_build_qt_compatible(source->signature));
PyList_Append(pyArgs, signature);
PyList_Append(pyArgs, slot);
match = true;
}
if (type)
PyList_Append(pyArgs, type);
if (match) {
Shiboken::AutoDecRef tupleArgs(PyList_AsTuple(pyArgs));
Shiboken::AutoDecRef pyMethod(PyObject_GetAttrString(source->source, "connect"));
return PyObject_CallObject(pyMethod, tupleArgs);
}
return 0;
}
bool signal_connect(PyObject* source, const char* signal, PyObject* callback)
{ {
Shiboken::AutoDecRef pyMethod(PyObject_GetAttrString(source, "connect")); Shiboken::AutoDecRef pyMethod(PyObject_GetAttrString(source, "connect"));
if (pyMethod.isNull()) if (pyMethod.isNull())
@ -461,81 +567,22 @@ bool signal_connect(PyObject* source, const char* signal, PyObject* callback)
return PyObject_CallObject(pyMethod, pyArgs); return PyObject_CallObject(pyMethod, pyArgs);
} }
PyObject* signal_instance_disconnect(PyObject* self, PyObject* args)
{
SignalInstanceData *source = reinterpret_cast<SignalInstanceData*>(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 == &SignalInstance_Type) {
SignalInstanceData *target = reinterpret_cast<SignalInstanceData*>(slot);
if (QMetaObject::checkConnectArgs(source->signature, target->signature)) {
PyList_Append(pyArgs, source->source);
Shiboken::AutoDecRef source_signature(signal_build_qt_compatible(source->signature));
PyList_Append(pyArgs, source_signature);
PyList_Append(pyArgs, target->source);
Shiboken::AutoDecRef target_signature(signal_build_qt_compatible(target->signature));
PyList_Append(pyArgs, target_signature);
match = true;
}
} else {
//try the first signature
PyList_Append(pyArgs, source->source);
Shiboken::AutoDecRef signature(signal_build_qt_compatible(source->signature));
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* signal_instance_emit(PyObject* self, PyObject* args)
{
SignalInstanceData *source = reinterpret_cast<SignalInstanceData*>(self);
Shiboken::AutoDecRef pyArgs(PyList_New(0));
Shiboken::AutoDecRef source_signature(signal_build_qt_compatible(source->signature));
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);
}
PyObject* signalNew(const char* name, ...) PyObject* signalNew(const char* name, ...)
{ {
va_list listSignatures; va_list listSignatures;
char* sig = 0; char* sig = 0;
SignalData* self = PyObject_New(SignalData, &Signal_Type); SignalData* self = PyObject_New(SignalData, &PySideSignalType);
self->signalName = strdup(name); self->signalName = strdup(name);
self->signaturesSize = 0; self->signaturesSize = 0;
self->signatures = 0; self->signatures = 0;
self->initialized = 0; self->initialized = 0;
self->homonymousMethod = 0;
va_start(listSignatures, name); va_start(listSignatures, name);
sig = va_arg(listSignatures, char*); sig = va_arg(listSignatures, char*);
while(sig != NULL) { while(sig != NULL) {
signal_append_signature(self, strdup(sig)); signalAppendSignature(self, strdup(sig));
sig = va_arg(listSignatures, char*); sig = va_arg(listSignatures, char*);
} }
@ -545,7 +592,7 @@ PyObject* signalNew(const char* name, ...)
} }
PyObject* signal_build_qt_compatible(const char* signature) PyObject* signalBuildQtCompatible(const char* signature)
{ {
char* qtSignature; char* qtSignature;
qtSignature = reinterpret_cast<char*>(malloc(strlen(signature)+2)); qtSignature = reinterpret_cast<char*>(malloc(strlen(signature)+2));
@ -555,5 +602,15 @@ PyObject* signal_build_qt_compatible(const char* signature)
return ret; return ret;
} }
void addSignalToWrapper(Shiboken::SbkBaseWrapperType* wrapperType, const char* signalName, PyObject* signal)
{
PyObject* typeDict = wrapperType->super.ht_type.tp_dict;
PyObject* homonymousMethod;
if ((homonymousMethod = PyDict_GetItemString(typeDict, signalName))) {
Py_INCREF(homonymousMethod);
reinterpret_cast<SignalData*>(signal)->homonymousMethod = homonymousMethod;
}
PyDict_SetItemString(typeDict, signalName, signal);
}
} //namespace PySide } //namespace PySide

View file

@ -27,28 +27,32 @@
#include <Python.h> #include <Python.h>
#include <QObject> #include <QObject>
namespace PySide namespace Shiboken
{ {
struct SbkBaseWrapperType;
struct SignalInstanceData }
{
PyObject_HEAD
char* signalName;
char* signature;
PyObject* source;
PyObject* next;
};
extern "C" extern "C"
{ {
extern PYSIDE_API PyTypeObject Signal_Type; extern PYSIDE_API PyTypeObject PySideSignalInstanceType;
extern PYSIDE_API PyTypeObject SignalInstance_Type;
struct PySideSignalInstanceData
{
PyObject_HEAD
char* signalName;
char* signature;
PyObject* source;
PyObject* homonymousMethod;
PyObject* next;
};
}; //extern "C" }; //extern "C"
namespace PySide
{
PYSIDE_API PyObject* signalNew(const char* name, ...); PYSIDE_API PyObject* signalNew(const char* name, ...);
PYSIDE_API void signalUpdateSource(PyObject* source); PYSIDE_API void signalUpdateSource(PyObject* source);
PYSIDE_API bool signal_connect(PyObject* source, const char* signal, PyObject* callback); PYSIDE_API void addSignalToWrapper(Shiboken::SbkBaseWrapperType* wrapperType, const char* signalName, PyObject* signal);
} //namespace PySide } //namespace PySide

40
libpyside/qsignal_p.h Normal file
View file

@ -0,0 +1,40 @@
/*
* This file is part of the PySide project.
*
* Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
*
* Contact: PySide team <contact@pyside.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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 library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef PYSIDE_QSIGNAL_P_H
#define PYSIDE_QSIGNAL_P_H
#include <Python.h>
extern "C"
{
extern PyTypeObject PySideSignalType;
}; //extern "C"
namespace PySide
{
bool signalConnect(PyObject* source, const char* signal, PyObject* callback);
char* getTypeName(PyObject*);
void initSignalSupport(PyObject* module);
} //namespace PySide
#endif

View file

@ -21,9 +21,9 @@
*/ */
#include <shiboken.h> #include <shiboken.h>
#include <dynamicqmetaobject.h>
#include <QString> #include <QString>
#include "dynamicqmetaobject_p.h"
#include "qsignal_p.h"
#define SLOT_DEC_NAME "Slot" #define SLOT_DEC_NAME "Slot"
@ -38,15 +38,11 @@ typedef struct
extern "C" extern "C"
{ {
static int slot_init(PyObject*, PyObject*, PyObject*); static int slotTpInit(PyObject*, PyObject*, PyObject*);
static PyObject* slot_call(PyObject*, PyObject*, PyObject*); static PyObject* slotCall(PyObject*, PyObject*, PyObject*);
//external qsignal.cpp
extern char* get_type_name(PyObject*);
// Class Definition ----------------------------------------------- // Class Definition -----------------------------------------------
static PyTypeObject Slot_Type = { static PyTypeObject PySideSlotType = {
PyObject_HEAD_INIT(NULL) PyObject_HEAD_INIT(NULL)
0, /*ob_size*/ 0, /*ob_size*/
"PySide.QtCore."SLOT_DEC_NAME, /*tp_name*/ "PySide.QtCore."SLOT_DEC_NAME, /*tp_name*/
@ -62,7 +58,7 @@ static PyTypeObject Slot_Type = {
0, /*tp_as_sequence*/ 0, /*tp_as_sequence*/
0, /*tp_as_mapping*/ 0, /*tp_as_mapping*/
0, /*tp_hash */ 0, /*tp_hash */
slot_call, /*tp_call*/ slotCall, /*tp_call*/
0, /*tp_str*/ 0, /*tp_str*/
0, /*tp_getattro*/ 0, /*tp_getattro*/
0, /*tp_setattro*/ 0, /*tp_setattro*/
@ -83,7 +79,7 @@ static PyTypeObject Slot_Type = {
0, /*tp_descr_get */ 0, /*tp_descr_get */
0, /*tp_descr_set */ 0, /*tp_descr_set */
0, /*tp_dictoffset */ 0, /*tp_dictoffset */
(initproc)slot_init, /*tp_init */ slotTpInit, /*tp_init */
0, /*tp_alloc */ 0, /*tp_alloc */
PyType_GenericNew, /*tp_new */ PyType_GenericNew, /*tp_new */
0, /*tp_free */ 0, /*tp_free */
@ -96,19 +92,7 @@ static PyTypeObject Slot_Type = {
0, /*tp_del */ 0, /*tp_del */
}; };
void init_slot(PyObject *module) int slotTpInit(PyObject *self, PyObject *args, PyObject *kw)
{
if (PyType_Ready(&Slot_Type) < 0)
return;
Py_INCREF(&Slot_Type);
PyModule_AddObject(module, SLOT_DEC_NAME, ((PyObject*)&Slot_Type));
}
} // extern "C"
int slot_init(PyObject *self, PyObject *args, PyObject *kw)
{ {
static PyObject *emptyTuple = 0; static PyObject *emptyTuple = 0;
static const char *kwlist[] = {"name", "result", 0}; static const char *kwlist[] = {"name", "result", 0};
@ -124,7 +108,7 @@ int slot_init(PyObject *self, PyObject *args, PyObject *kw)
SlotData *data = reinterpret_cast<SlotData*>(self); SlotData *data = reinterpret_cast<SlotData*>(self);
for(Py_ssize_t i = 0, i_max = PyTuple_Size(args); i < i_max; i++) { for(Py_ssize_t i = 0, i_max = PyTuple_Size(args); i < i_max; i++) {
PyObject *argType = PyTuple_GET_ITEM(args, i); PyObject *argType = PyTuple_GET_ITEM(args, i);
char *typeName = get_type_name(argType); char *typeName = PySide::getTypeName(argType);
if (typeName) { if (typeName) {
if (data->args) { if (data->args) {
data->args = reinterpret_cast<char*>(realloc(data->args, (strlen(data->args) + 1 + strlen(typeName)) * sizeof(char*))); data->args = reinterpret_cast<char*>(realloc(data->args, (strlen(data->args) + 1 + strlen(typeName)) * sizeof(char*)));
@ -141,14 +125,14 @@ int slot_init(PyObject *self, PyObject *args, PyObject *kw)
data->slotName = strdup(argName); data->slotName = strdup(argName);
if (argResult) if (argResult)
data->resultType = get_type_name(argResult); data->resultType = PySide::getTypeName(argResult);
else else
data->resultType = strdup("void"); data->resultType = strdup("void");
return 1; return 1;
} }
PyObject* slot_call(PyObject* self, PyObject* args, PyObject* kw) PyObject* slotCall(PyObject* self, PyObject* args, PyObject* kw)
{ {
static PyObject* pySlotName = 0; static PyObject* pySlotName = 0;
PyObject* callback; PyObject* callback;
@ -194,3 +178,18 @@ PyObject* slot_call(PyObject* self, PyObject* args, PyObject* kw)
return callback; return callback;
} }
} // extern "C"
namespace PySide
{
void initSlotSupport(PyObject* module)
{
if (PyType_Ready(&PySideSlotType) < 0)
return;
Py_INCREF(&PySideSlotType);
PyModule_AddObject(module, SLOT_DEC_NAME, ((PyObject*)&PySideSlotType));
}
} // namespace PySide

32
libpyside/qslot_p.h Normal file
View file

@ -0,0 +1,32 @@
/*
* This file is part of the PySide project.
*
* Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
*
* Contact: PySide team <contact@pyside.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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 library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef PYSIDE_SLOT_P_H
#define PYSIDE_SLOT_P_H
#include <Python.h>
namespace PySide
{
void initSlotSupport(PyObject* module);
}
#endif

View file

@ -21,8 +21,6 @@
*/ */
#include "signalmanager.h" #include "signalmanager.h"
#include "qproperty.h"
#include "pyside.h"
#include <QHash> #include <QHash>
#include <QStringList> #include <QStringList>
@ -35,6 +33,10 @@
#include <basewrapper.h> #include <basewrapper.h>
#include <conversions.h> #include <conversions.h>
#include "qproperty.h"
#include "qproperty_p.h"
#include "pyside.h"
#if QSLOT_CODE != 1 || QSIGNAL_CODE != 2 #if QSLOT_CODE != 1 || QSIGNAL_CODE != 2
#error QSLOT_CODE and/or QSIGNAL_CODE changed! change the hardcoded stuff to the correct value! #error QSLOT_CODE and/or QSIGNAL_CODE changed! change the hardcoded stuff to the correct value!
#endif #endif
@ -46,6 +48,8 @@
namespace PySide { namespace PySide {
static int callMethod(QObject* object, int id, void** args);
PyObjectWrapper::PyObjectWrapper() PyObjectWrapper::PyObjectWrapper()
:m_me(Py_None) :m_me(Py_None)
{ {
@ -363,7 +367,7 @@ int SignalManager::qt_metacall(QObject* object, QMetaObject::Call call, int id,
return id - metaObject->methodCount(); return id - metaObject->methodCount();
pp_name = PyString_FromString(mp.name()); pp_name = PyString_FromString(mp.name());
pp = qproperty_get_object(pySelf, pp_name); pp = qpropertyGetObject(pySelf, pp_name);
if (!pp) { if (!pp) {
qWarning("Invalid property."); qWarning("Invalid property.");
Py_XDECREF(pp_name); Py_XDECREF(pp_name);
@ -376,7 +380,7 @@ int SignalManager::qt_metacall(QObject* object, QMetaObject::Call call, int id,
#ifndef QT_NO_PROPERTIES #ifndef QT_NO_PROPERTIES
case QMetaObject::ReadProperty: case QMetaObject::ReadProperty:
{ {
PyObject* value = qproperty_get(pp, pySelf); PyObject* value = qpropertyGet(pp, pySelf);
if (value) { if (value) {
void *data = typeResolver->toCpp(value); void *data = typeResolver->toCpp(value);
if (Shiboken::TypeResolver::getType(mp.typeName()) == Shiboken::TypeResolver::ObjectType) if (Shiboken::TypeResolver::getType(mp.typeName()) == Shiboken::TypeResolver::ObjectType)
@ -394,12 +398,12 @@ int SignalManager::qt_metacall(QObject* object, QMetaObject::Call call, int id,
case QMetaObject::WriteProperty: case QMetaObject::WriteProperty:
{ {
Shiboken::AutoDecRef value(typeResolver->toPython(args[0])); Shiboken::AutoDecRef value(typeResolver->toPython(args[0]));
qproperty_set(pp, pySelf, value); qpropertySet(pp, pySelf, value);
break; break;
} }
case QMetaObject::ResetProperty: case QMetaObject::ResetProperty:
qproperty_reset(pp, pp_name); qpropertyReset(pp, pp_name);
break; break;
case QMetaObject::QueryPropertyDesignable: case QMetaObject::QueryPropertyDesignable:
@ -410,7 +414,7 @@ int SignalManager::qt_metacall(QObject* object, QMetaObject::Call call, int id,
break; break;
#endif #endif
case QMetaObject::InvokeMetaMethod: case QMetaObject::InvokeMetaMethod:
id = call_method(object, id, args); id = callMethod(object, id, args);
break; break;
default: default:
@ -427,7 +431,7 @@ int SignalManager::qt_metacall(QObject* object, QMetaObject::Call call, int id,
return id; return id;
} }
int SignalManager::call_method(QObject* object, int id, void** args) static int PySide::callMethod(QObject* object, int id, void** args)
{ {
const QMetaObject* metaObject = object->metaObject(); const QMetaObject* metaObject = object->metaObject();
QMetaMethod method = metaObject->method(id); QMetaMethod method = metaObject->method(id);

View file

@ -82,8 +82,6 @@ private:
// disable copy // disable copy
SignalManager(const SignalManager&); SignalManager(const SignalManager&);
SignalManager operator=(const SignalManager&); SignalManager operator=(const SignalManager&);
static int call_method(QObject* object, int id, void** args);
}; };
} }

View file

@ -6,8 +6,8 @@ else()
endif() endif()
if(WIN32) if(WIN32)
set(TEST_PYTHONPATH "${CMAKE_BINARY_DIR};${CMAKE_SOURCE_DIR}/tests/util") set(TEST_PYTHONPATH "${CMAKE_BINARY_DIR};${CMAKE_SOURCE_DIR}/tests/util;${testbinding_BINARY_DIR}")
set(TEST_LIBRARY_PATH "${libpyside_BINARY_DIR};$ENV{PATH}") set(TEST_LIBRARY_PATH "${libpyside_BINARY_DIR};${pysidetest_BINARY_DIR};$ENV{PATH}")
set(LIBRARY_PATH_VAR "PATH") set(LIBRARY_PATH_VAR "PATH")
string(REPLACE "\\" "/" TEST_PYTHONPATH "${TEST_PYTHONPATH}") string(REPLACE "\\" "/" TEST_PYTHONPATH "${TEST_PYTHONPATH}")
string(REPLACE "\\" "/" TEST_LIBRARY_PATH "${TEST_LIBRARY_PATH}") string(REPLACE "\\" "/" TEST_LIBRARY_PATH "${TEST_LIBRARY_PATH}")
@ -15,8 +15,8 @@ else()
string(REPLACE ";" "\\;" TEST_PYTHONPATH "${TEST_PYTHONPATH}") string(REPLACE ";" "\\;" TEST_PYTHONPATH "${TEST_PYTHONPATH}")
string(REPLACE ";" "\\;" TEST_LIBRARY_PATH "${TEST_LIBRARY_PATH}") string(REPLACE ";" "\\;" TEST_LIBRARY_PATH "${TEST_LIBRARY_PATH}")
else() else()
set(TEST_PYTHONPATH "${CMAKE_BINARY_DIR}:${CMAKE_SOURCE_DIR}/tests/util") set(TEST_PYTHONPATH "${CMAKE_BINARY_DIR}:${CMAKE_SOURCE_DIR}/tests/util:${testbinding_BINARY_DIR}")
set(TEST_LIBRARY_PATH "${libpyside_BINARY_DIR}:$ENV{LD_LIBRARY_PATH}") set(TEST_LIBRARY_PATH "${libpyside_BINARY_DIR}:${pysidetest_BINARY_DIR}:$ENV{LD_LIBRARY_PATH}")
set(LIBRARY_PATH_VAR "LD_LIBRARY_PATH") set(LIBRARY_PATH_VAR "LD_LIBRARY_PATH")
endif() endif()
@ -35,7 +35,7 @@ else()
elseif(${ARGC} EQUAL 2) elseif(${ARGC} EQUAL 2)
set(EXPECT_TO_FAIL ${ARGV1}) set(EXPECT_TO_FAIL ${ARGV1})
else() else()
message(WARNING "Ivalid call of macro PYSIDE_TEST") message(WARNING "Invalid call of macro PYSIDE_TEST")
endif() endif()
set(TEST_CMD ${XVFB_EXEC} ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/${ARGV0}") set(TEST_CMD ${XVFB_EXEC} ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/${ARGV0}")
add_test(${TEST_NAME} ${TEST_CMD}) add_test(${TEST_NAME} ${TEST_CMD})
@ -59,6 +59,7 @@ else()
endif () endif ()
add_subdirectory(signals) add_subdirectory(signals)
add_subdirectory(pysidetest)
TEST_QT_MODULE(QT_QTCORE_FOUND QtCore) TEST_QT_MODULE(QT_QTCORE_FOUND QtCore)
TEST_QT_MODULE(QT_QTGUI_FOUND QtGui) TEST_QT_MODULE(QT_QTGUI_FOUND QtGui)
TEST_QT_MODULE(QT_QTNETWORK_FOUND QtNetwork) TEST_QT_MODULE(QT_QTNETWORK_FOUND QtNetwork)

View file

@ -0,0 +1,71 @@
project(pysidetest)
project(testbinding)
cmake_minimum_required(VERSION 2.6)
find_package(Qt4 4.5.0 REQUIRED)
find_package(PythonLibs REQUIRED)
find_package(PythonInterpWithDebug REQUIRED)
find_package(GeneratorRunner 0.6 REQUIRED)
find_package(Shiboken 0.5 REQUIRED)
set(QT_USE_QTCORE 1)
include(${QT_USE_FILE})
add_definitions(${QT_DEFINITIONS})
add_definitions(-DQT_SHARED)
add_definitions(-DRXX_ALLOCATOR_INIT_0)
set(pysidetest_SRC
testobject.cpp
)
set(pysidetest_MOC_HEADERS
testobject.h
)
qt4_wrap_cpp(pysidetest_MOC_SRC ${pysidetest_MOC_HEADERS})
set(testbinding_SRC
${CMAKE_CURRENT_BINARY_DIR}/testbinding/testobject_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/testbinding/testbinding_module_wrapper.cpp
)
set(GENERATOR_EXTRA_FLAGS --generatorSet=shiboken --enable-parent-ctor-heuristic --enable-pyside-extensions --enable-return-value-heuristic)
add_custom_command(OUTPUT ${testbinding_SRC}
COMMAND ${GENERATORRUNNER_BINARY} ${GENERATOR_EXTRA_FLAGS}
${CMAKE_CURRENT_SOURCE_DIR}/global.h
--include-paths=${CMAKE_CURRENT_SOURCE_DIR}:${QT_INCLUDE_DIR}:${QT_QTCORE_INCLUDE_DIR}
--typesystem-paths=${CMAKE_CURRENT_SOURCE_DIR}:${pyside_SOURCE_DIR}:${QtCore_SOURCE_DIR}
--output-directory=${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/typesystem_pysidetest.xml
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Running generator for test binding..."
)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
${QT_INCLUDE_DIR}
${QT_QTCORE_INCLUDE_DIR}
${SHIBOKEN_INCLUDE_DIR}
${QtCore_BINARY_DIR}/PySide/QtCore
${libpyside_SOURCE_DIR}
${PYTHON_INCLUDE_PATH})
add_library(pysidetest SHARED ${pysidetest_SRC} ${pysidetest_MOC_SRC})
target_link_libraries(pysidetest ${QT_QTCORE_LIBRARY})
add_library(testbinding MODULE ${testbinding_SRC})
set_property(TARGET testbinding PROPERTY PREFIX "")
target_link_libraries(testbinding
pysidetest
pyside
${PYTHON_LIBRARIES}
${SHIBOKEN_LIBRARY}
${QT_QTCORE_LIBRARY}
${SBK_PYTHON_LIBRARIES})
add_dependencies(testbinding pyside QtCore libpyside pysidetest)
PYSIDE_TEST(homonymoussignalandmethod_test.py)

View file

@ -0,0 +1,2 @@
#include "pyside_global.h"
#include "testobject.h"

View file

@ -0,0 +1,53 @@
#!/usr/bin/python
import unittest
from testbinding import TestObject
'''Tests the behaviour of homonymous signals and slots.'''
class HomonymousSignalAndMethodTest(unittest.TestCase):
def setUp(self):
self.value = 123
self.called = False
self.obj = TestObject(self.value)
def tearDown(self):
del self.value
del self.called
del self.obj
def testIdValueSignalEmission(self):
def callback(idValue):
self.assertEqual(idValue, self.value)
self.obj.idValue.connect(callback)
self.obj.emitIdValueSignal()
def testStaticMethodDoubleSignalEmission(self):
def callback():
self.called = True
self.obj.staticMethodDouble.connect(callback)
self.obj.emitStaticMethodDoubleSignal()
self.assert_(self.called)
def testSignalNotCallable(self):
self.assertRaises(TypeError, self.obj.justASignal)
def testCallingInstanceMethodWithArguments(self):
self.assertRaises(TypeError, TestObject.idValue, 1)
def testCallingInstanceMethodWithoutArguments(self):
self.assertRaises(TypeError, TestObject.idValue)
def testHomonymousSignalAndMethod(self):
self.assertEqual(self.obj.idValue(), self.value)
def testHomonymousSignalAndStaticMethod(self):
self.assertEqual(TestObject.staticMethodDouble(3), 6)
def testHomonymousSignalAndStaticMethodFromInstance(self):
self.assertEqual(self.obj.staticMethodDouble(4), 8)
if __name__ == '__main__':
unittest.main()

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,7 @@
{
local:
_ZSt*;
_ZNSt*;
_ZNSs*;
_ZNKSt*;
};

View file

@ -0,0 +1,14 @@
#include "testobject.h"
void
TestObject::emitIdValueSignal()
{
emit idValue(m_idValue);
}
void
TestObject::emitStaticMethodDoubleSignal()
{
emit staticMethodDouble();
}

View file

@ -0,0 +1,28 @@
#ifndef TESTOBJECT_H
#define TESTOBJECT_H
#include <QObject>
#include "pysidemacros.h"
class PYSIDE_API TestObject : public QObject
{
Q_OBJECT
public:
TestObject(int idValue, QObject* parent = 0) : QObject(parent), m_idValue(idValue) {}
int idValue() const { return m_idValue; }
static int staticMethodDouble(int value) { return value * 2; }
void emitIdValueSignal();
void emitStaticMethodDoubleSignal();
signals:
void idValue(int newValue);
void justASignal();
void staticMethodDouble();
private:
int m_idValue;
};
#endif // TESTOBJECT_H

View file

@ -0,0 +1,6 @@
<?xml version="1.0"?>
<typesystem package="testbinding">
<load-typesystem name="typesystem_core.xml" generate="no" />
<object-type name="TestObject" />
</typesystem>