Implemented support to properties on QMetaObject.
Reviewer: Hugo Parente Lima <hugo.lima@openbossa.org>,
Luciano Wolf <luciano.wolf@openbossa.org>
This commit is contained in:
parent
693ae6d6c4
commit
1c4ee915c0
11 changed files with 893 additions and 33 deletions
|
|
@ -6,6 +6,7 @@ signalmanager.cpp
|
||||||
globalreceiver.cpp
|
globalreceiver.cpp
|
||||||
qsignal.cpp
|
qsignal.cpp
|
||||||
qslot.cpp
|
qslot.cpp
|
||||||
|
qproperty.cpp
|
||||||
pyside.cpp
|
pyside.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -36,6 +37,7 @@ set(libpyside_HEADERS
|
||||||
signalmanager.h
|
signalmanager.h
|
||||||
pyside.h
|
pyside.h
|
||||||
qsignal.h
|
qsignal.h
|
||||||
|
qproperty.h
|
||||||
)
|
)
|
||||||
|
|
||||||
# create pkg-config file
|
# create pkg-config file
|
||||||
|
|
|
||||||
|
|
@ -43,11 +43,36 @@
|
||||||
#include <QMetaMethod>
|
#include <QMetaMethod>
|
||||||
|
|
||||||
#include "qsignal.h"
|
#include "qsignal.h"
|
||||||
|
#include "qproperty.h"
|
||||||
|
|
||||||
#define MAX_SIGNALS_COUNT 50
|
#define MAX_SIGNALS_COUNT 50
|
||||||
|
#define MAX_SLOTS_COUNT 50
|
||||||
|
|
||||||
using namespace PySide;
|
using namespace PySide;
|
||||||
|
|
||||||
|
enum PropertyFlags {
|
||||||
|
Invalid = 0x00000000,
|
||||||
|
Readable = 0x00000001,
|
||||||
|
Writable = 0x00000002,
|
||||||
|
Resettable = 0x00000004,
|
||||||
|
EnumOrFlag = 0x00000008,
|
||||||
|
StdCppSet = 0x00000100,
|
||||||
|
// Override = 0x00000200,
|
||||||
|
Constant = 0x00000400,
|
||||||
|
Final = 0x00000800,
|
||||||
|
Designable = 0x00001000,
|
||||||
|
ResolveDesignable = 0x00002000,
|
||||||
|
Scriptable = 0x00004000,
|
||||||
|
ResolveScriptable = 0x00008000,
|
||||||
|
Stored = 0x00010000,
|
||||||
|
ResolveStored = 0x00020000,
|
||||||
|
Editable = 0x00040000,
|
||||||
|
ResolveEditable = 0x00080000,
|
||||||
|
User = 0x00100000,
|
||||||
|
ResolveUser = 0x00200000,
|
||||||
|
Notify = 0x00400000
|
||||||
|
};
|
||||||
|
|
||||||
static int registerString(const QByteArray& s, QList<QByteArray>* strings)
|
static int registerString(const QByteArray& s, QList<QByteArray>* strings)
|
||||||
{
|
{
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
|
|
@ -61,6 +86,89 @@ static int registerString(const QByteArray& s, QList<QByteArray>* strings)
|
||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int qvariant_nameToType(const char* name)
|
||||||
|
{
|
||||||
|
if (!name)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (strcmp(name, "QVariant") == 0)
|
||||||
|
return 0xffffffff;
|
||||||
|
if (strcmp(name, "QCString") == 0)
|
||||||
|
return QMetaType::QByteArray;
|
||||||
|
if (strcmp(name, "Q_LLONG") == 0)
|
||||||
|
return QMetaType::LongLong;
|
||||||
|
if (strcmp(name, "Q_ULLONG") == 0)
|
||||||
|
return QMetaType::ULongLong;
|
||||||
|
if (strcmp(name, "QIconSet") == 0)
|
||||||
|
return QMetaType::QIcon;
|
||||||
|
|
||||||
|
uint tp = QMetaType::type(name);
|
||||||
|
return tp < QMetaType::User ? tp : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Returns true if the type is a QVariant types.
|
||||||
|
*/
|
||||||
|
static bool isVariantType(const char* type)
|
||||||
|
{
|
||||||
|
return qvariant_nameToType(type) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns true if the type is qreal.
|
||||||
|
*/
|
||||||
|
static bool isQRealType(const char *type)
|
||||||
|
{
|
||||||
|
return strcmp(type, "qreal") == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint PropertyData::flags() const
|
||||||
|
{
|
||||||
|
const char* typeName = type().data();
|
||||||
|
uint flags = Invalid;
|
||||||
|
if (!isVariantType(typeName))
|
||||||
|
flags |= EnumOrFlag;
|
||||||
|
else if (!isQRealType(typeName))
|
||||||
|
flags |= qvariant_nameToType(typeName) << 24;
|
||||||
|
|
||||||
|
if (qproperty_is_readble(m_data))
|
||||||
|
flags |= Readable;
|
||||||
|
|
||||||
|
if (qproperty_is_writable(m_data))
|
||||||
|
flags |= Writable;
|
||||||
|
|
||||||
|
if (qproperty_has_reset(m_data))
|
||||||
|
flags |= Resettable;
|
||||||
|
|
||||||
|
if (!qproperty_is_designable(m_data))
|
||||||
|
flags |= ResolveDesignable;
|
||||||
|
else
|
||||||
|
flags |= Designable;
|
||||||
|
|
||||||
|
if (!qproperty_is_scriptable(m_data))
|
||||||
|
flags |= ResolveScriptable;
|
||||||
|
else
|
||||||
|
flags |= Scriptable;
|
||||||
|
|
||||||
|
if (!qproperty_is_stored(m_data))
|
||||||
|
flags |= ResolveStored;
|
||||||
|
else
|
||||||
|
flags |= Stored;
|
||||||
|
|
||||||
|
if (!qproperty_is_user(m_data))
|
||||||
|
flags |= ResolveUser;
|
||||||
|
else
|
||||||
|
flags |= User;
|
||||||
|
|
||||||
|
if (qproperty_is_constant(m_data))
|
||||||
|
flags |= Constant;
|
||||||
|
|
||||||
|
if (qproperty_is_final(m_data))
|
||||||
|
flags |= Final;
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
MethodData::MethodData(const char* signature, const char* type)
|
MethodData::MethodData(const char* signature, const char* type)
|
||||||
{
|
{
|
||||||
m_signature = QSharedPointer<QByteArray>(new QByteArray(signature));
|
m_signature = QSharedPointer<QByteArray>(new QByteArray(signature));
|
||||||
|
|
@ -107,6 +215,39 @@ bool MethodData::isValid() const
|
||||||
return m_signature->size();
|
return m_signature->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PropertyData::PropertyData(const char* name, PyObject* data)
|
||||||
|
: m_name(name), m_data(data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray PropertyData::type() const
|
||||||
|
{
|
||||||
|
return QByteArray(qproperty_get_type(m_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool PropertyData::isValid() const
|
||||||
|
{
|
||||||
|
return !m_name.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray PropertyData::name() const
|
||||||
|
{
|
||||||
|
return m_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PropertyData::operator==(const PropertyData& other) const
|
||||||
|
{
|
||||||
|
return m_data == other.m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PropertyData::operator==(const char* name) const
|
||||||
|
{
|
||||||
|
return m_name == QString(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DynamicQMetaObject::DynamicQMetaObject(const char* className, const QMetaObject* metaObject)
|
DynamicQMetaObject::DynamicQMetaObject(const char* className, const QMetaObject* metaObject)
|
||||||
{
|
{
|
||||||
d.superdata = metaObject;
|
d.superdata = metaObject;
|
||||||
|
|
@ -153,6 +294,10 @@ void DynamicQMetaObject::addSlot(const char* slot, const char* type)
|
||||||
if (i != m_slots.end())
|
if (i != m_slots.end())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (m_slots.size() >= MAX_SLOTS_COUNT) {
|
||||||
|
qWarning() << "Fail to add dynamic slot to QObject. PySide support at most" << MAX_SLOTS_COUNT << "dynamic slots.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//search for a empty space
|
//search for a empty space
|
||||||
MethodData blank;
|
MethodData blank;
|
||||||
|
|
@ -177,6 +322,24 @@ void DynamicQMetaObject::removeSlot(uint index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DynamicQMetaObject::addProperty(const char* property, PyObject* data)
|
||||||
|
{
|
||||||
|
QLinkedList<PropertyData>::iterator i = qFind(m_properties.begin(), m_properties.end(), property);
|
||||||
|
if (i != m_properties.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
//search for a empty space
|
||||||
|
PropertyData blank;
|
||||||
|
i = qFind(m_properties.begin(), m_properties.end(), blank);
|
||||||
|
if (i != m_properties.end()) {
|
||||||
|
*i = PropertyData(property, data);
|
||||||
|
} else {
|
||||||
|
m_properties << PropertyData(property, data);
|
||||||
|
}
|
||||||
|
updateMetaObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DynamicQMetaObject* DynamicQMetaObject::createBasedOn(PyObject* pyObj, PyTypeObject* type, const QMetaObject* base)
|
DynamicQMetaObject* DynamicQMetaObject::createBasedOn(PyObject* pyObj, PyTypeObject* type, const QMetaObject* base)
|
||||||
{
|
{
|
||||||
PyObject* key;
|
PyObject* key;
|
||||||
|
|
@ -189,6 +352,11 @@ 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
|
||||||
|
if (value->ob_type == &QProperty_Type) {
|
||||||
|
mo->addProperty(PyString_AsString(key), value);
|
||||||
|
}
|
||||||
|
|
||||||
//Register signals
|
//Register signals
|
||||||
if (value->ob_type == &Signal_Type) {
|
if (value->ob_type == &Signal_Type) {
|
||||||
PyObject *attr = PyObject_GetAttr(pyObj, key);
|
PyObject *attr = PyObject_GetAttr(pyObj, key);
|
||||||
|
|
@ -234,6 +402,35 @@ void DynamicQMetaObject::removeSignal(uint index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DynamicQMetaObject::writeMethodsData(QLinkedList<MethodData>& methods,
|
||||||
|
unsigned int **data,
|
||||||
|
QList<QByteArray> *strings,
|
||||||
|
int *prtIndex,
|
||||||
|
int max_count,
|
||||||
|
int null_index,
|
||||||
|
int flags)
|
||||||
|
{
|
||||||
|
int index = *prtIndex;
|
||||||
|
|
||||||
|
QLinkedList<MethodData>::iterator iMethod = methods.begin();
|
||||||
|
for(int i=0; i < max_count; i++) {
|
||||||
|
QByteArray mType;
|
||||||
|
if (iMethod != methods.end() && ((*iMethod).signature().size() > 0) ) {
|
||||||
|
(*data)[index++] = registerString((*iMethod).signature(), strings); // func name
|
||||||
|
mType = (*iMethod).type();
|
||||||
|
iMethod++;
|
||||||
|
} else {
|
||||||
|
(*data)[index++] = null_index; // func name
|
||||||
|
}
|
||||||
|
(*data)[index++] = null_index; // arguments
|
||||||
|
(*data)[index++] = (mType.size() > 0 ? registerString(mType, strings) : null_index); // normalized type
|
||||||
|
(*data)[index++] = null_index; // tags
|
||||||
|
(*data)[index++] = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
*prtIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
void DynamicQMetaObject::updateMetaObject()
|
void DynamicQMetaObject::updateMetaObject()
|
||||||
{
|
{
|
||||||
// these values are from moc source code, generator.cpp:66
|
// these values are from moc source code, generator.cpp:66
|
||||||
|
|
@ -251,22 +448,23 @@ void DynamicQMetaObject::updateMetaObject()
|
||||||
};
|
};
|
||||||
|
|
||||||
uint n_signals = MAX_SIGNALS_COUNT;
|
uint n_signals = MAX_SIGNALS_COUNT;
|
||||||
uint n_methods = n_signals + m_slots.count();
|
uint n_methods = n_signals + MAX_SLOTS_COUNT;
|
||||||
|
uint n_properties = m_properties.size();
|
||||||
int header[] = {5, // revision
|
int header[] = {5, // revision
|
||||||
0, // class name index in m_metadata
|
0, // class name index in m_metadata
|
||||||
0, 0, // classinfo and classinfo index, not used by us
|
0, 0, // classinfo and classinfo index, not used by us
|
||||||
n_methods, 0, // method count and method list index
|
n_methods, 0, // method count and method list index
|
||||||
0, 0, // prop count and prop indexes
|
n_properties, 0, // prop count and prop indexes
|
||||||
0, 0, // enum count and enum index
|
0, 0, // enum count and enum index
|
||||||
0, 0, // constructors
|
0, 0, // constructors
|
||||||
MAX_SIGNALS_COUNT};
|
n_signals};
|
||||||
|
|
||||||
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[] d.data;
|
||||||
unsigned int* data;
|
unsigned int* data;
|
||||||
data = new unsigned int[HEADER_LENGHT + n_methods*5 + 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));
|
||||||
|
|
||||||
QList<QByteArray> strings;
|
QList<QByteArray> strings;
|
||||||
|
|
@ -275,35 +473,25 @@ void DynamicQMetaObject::updateMetaObject()
|
||||||
int index = HEADER_LENGHT;
|
int index = HEADER_LENGHT;
|
||||||
|
|
||||||
//write signals
|
//write signals
|
||||||
QLinkedList<MethodData>::iterator iSignal = m_signals.begin();
|
writeMethodsData(m_signals, &data, &strings, &index, MAX_SIGNALS_COUNT, NULL_INDEX, AccessPublic | MethodSignal);
|
||||||
for(int i=0; i < MAX_SIGNALS_COUNT; i++) {
|
|
||||||
QByteArray sigType;
|
|
||||||
if (iSignal != m_signals.end() && ((*iSignal).signature().size() > 0) ) {
|
|
||||||
data[index++] = registerString((*iSignal).signature(), &strings); // func name
|
|
||||||
sigType = (*iSignal).type();
|
|
||||||
iSignal++;
|
|
||||||
} else {
|
|
||||||
data[index++] = NULL_INDEX; // func name
|
|
||||||
}
|
|
||||||
data[index++] = NULL_INDEX; // arguments
|
|
||||||
data[index++] = (sigType.size() > 0 ? registerString(sigType, &strings) : NULL_INDEX); // normalized type
|
|
||||||
data[index++] = NULL_INDEX; // tags
|
|
||||||
data[index++] = AccessPublic | MethodSignal; // flags
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//write slots
|
//write slots
|
||||||
foreach(MethodData slot, m_slots) {
|
writeMethodsData(m_slots, &data, &strings, &index, MAX_SLOTS_COUNT, NULL_INDEX, AccessPublic | MethodSlot);
|
||||||
if (slot.isValid())
|
|
||||||
data[index++] = registerString(slot.signature(), &strings); // func name
|
if (m_properties.size())
|
||||||
|
data[7] = index;
|
||||||
|
|
||||||
|
//write properties
|
||||||
|
foreach(PropertyData pp, m_properties) {
|
||||||
|
if (pp.isValid())
|
||||||
|
data[index++] = registerString(pp.name(), &strings); // name
|
||||||
else
|
else
|
||||||
data[index++] = NULL_INDEX;
|
data[index++] = NULL_INDEX;
|
||||||
|
|
||||||
data[index++] = NULL_INDEX; // arguments
|
data[index++] = (pp.isValid() ? registerString(pp.type(), &strings) : NULL_INDEX); // normalized type
|
||||||
data[index++] = (slot.isValid() ? registerString(slot.type(), &strings) : NULL_INDEX); // normalized type
|
data[index++] = pp.flags(); //pp.flags(); //TODO: flags
|
||||||
data[index++] = NULL_INDEX; // tags
|
|
||||||
data[index++] = AccessPublic | MethodSlot; // flags
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data[index++] = 0; // the end
|
data[index++] = 0; // the end
|
||||||
|
|
||||||
// create the m_metadata string
|
// create the m_metadata string
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,23 @@ private:
|
||||||
QSharedPointer<QByteArray> m_type;
|
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:
|
||||||
|
|
@ -74,9 +91,11 @@ public:
|
||||||
|
|
||||||
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 removeSignal(uint idex);
|
void removeSignal(uint idex);
|
||||||
void removeSlot(uint index);
|
void removeSlot(uint index);
|
||||||
|
void removeProperty(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(PyObject* obj, PyTypeObject* type, const QMetaObject* base);
|
static DynamicQMetaObject* createBasedOn(PyObject* obj, PyTypeObject* type, const QMetaObject* base);
|
||||||
|
|
@ -84,9 +103,11 @@ public:
|
||||||
private:
|
private:
|
||||||
QLinkedList<MethodData> m_signals;
|
QLinkedList<MethodData> m_signals;
|
||||||
QLinkedList<MethodData> m_slots;
|
QLinkedList<MethodData> m_slots;
|
||||||
|
QLinkedList<PropertyData> m_properties;
|
||||||
QByteArray m_className;
|
QByteArray m_className;
|
||||||
|
|
||||||
void updateMetaObject();
|
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 inline void deleteDynamicQMetaObject(void* data)
|
||||||
|
|
|
||||||
|
|
@ -35,9 +35,11 @@
|
||||||
|
|
||||||
#include "pyside.h"
|
#include "pyside.h"
|
||||||
#include "signalmanager.h"
|
#include "signalmanager.h"
|
||||||
|
#include "qproperty.h"
|
||||||
|
|
||||||
extern "C" void init_signal(PyObject* module);
|
extern "C" void init_signal(PyObject* module);
|
||||||
extern "C" void init_slot(PyObject* module);
|
extern "C" void init_slot(PyObject* module);
|
||||||
|
extern "C" void init_qproperty(PyObject* module);
|
||||||
|
|
||||||
namespace PySide
|
namespace PySide
|
||||||
{
|
{
|
||||||
|
|
@ -46,6 +48,7 @@ void init(PyObject *module)
|
||||||
{
|
{
|
||||||
init_signal(module);
|
init_signal(module);
|
||||||
init_slot(module);
|
init_slot(module);
|
||||||
|
init_qproperty(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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
318
libpyside/qproperty.cpp
Normal file
318
libpyside/qproperty.cpp
Normal file
|
|
@ -0,0 +1,318 @@
|
||||||
|
/*
|
||||||
|
* 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 <shiboken.h>
|
||||||
|
#include <Python.h>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#include "qproperty.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define QPROPERTY_CLASS_NAME "QProperty"
|
||||||
|
|
||||||
|
namespace PySide
|
||||||
|
{
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyObject_HEAD
|
||||||
|
char* typeName;
|
||||||
|
PyObject* type;
|
||||||
|
PyObject* fget;
|
||||||
|
PyObject* fset;
|
||||||
|
PyObject* freset;
|
||||||
|
PyObject* fdel;
|
||||||
|
char* doc;
|
||||||
|
bool designable;
|
||||||
|
bool scriptable;
|
||||||
|
bool stored;
|
||||||
|
bool user;
|
||||||
|
bool constant;
|
||||||
|
bool final;
|
||||||
|
} QPropertyData;
|
||||||
|
|
||||||
|
static int qproperty_init(PyObject*, PyObject*, PyObject*);
|
||||||
|
static void qproperty_free(void*);
|
||||||
|
|
||||||
|
//aux
|
||||||
|
static char* translate_type_name(PyObject*);
|
||||||
|
|
||||||
|
PyTypeObject QProperty_Type = {
|
||||||
|
PyObject_HEAD_INIT(0)
|
||||||
|
0, /*ob_size*/
|
||||||
|
QPROPERTY_CLASS_NAME, /*tp_name*/
|
||||||
|
sizeof(QPropertyData), /*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, /*tp_flags*/
|
||||||
|
0, /*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)qproperty_init, /*tp_init */
|
||||||
|
0, /*tp_alloc */
|
||||||
|
PyType_GenericNew, /*tp_new */
|
||||||
|
qproperty_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 */
|
||||||
|
};
|
||||||
|
|
||||||
|
void init_qproperty(PyObject* module)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
QPropertyData *data = reinterpret_cast<QPropertyData*>(self);
|
||||||
|
data->designable = true;
|
||||||
|
data->scriptable = true;
|
||||||
|
data->stored = true;
|
||||||
|
|
||||||
|
static const char *kwlist[] = {"fget", "fset", "freset", "fdel", "doc",
|
||||||
|
"designable", "scriptable", "stored", "user",
|
||||||
|
"constant", "final", 0};
|
||||||
|
if (!PyArg_ParseTupleAndKeywords(args, kwds,
|
||||||
|
"O|OOOOsbbbbbb:QtCore.QProperty", (char**) kwlist,
|
||||||
|
&type, &data->fget, &data->fset, &data->freset,
|
||||||
|
&data->fdel, &data->doc, &data->designable,
|
||||||
|
&data->scriptable, &data->stored, &data->user,
|
||||||
|
&data->constant, &data->final))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!data->fset && data->fget)
|
||||||
|
data->constant = true;
|
||||||
|
|
||||||
|
data->typeName = translate_type_name(type);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void qproperty_free(void *self)
|
||||||
|
{
|
||||||
|
PyObject *pySelf = reinterpret_cast<PyObject*>(self);
|
||||||
|
QPropertyData *data = reinterpret_cast<QPropertyData*>(self);
|
||||||
|
|
||||||
|
free(data->typeName);
|
||||||
|
free(data->doc);
|
||||||
|
|
||||||
|
pySelf->ob_type->tp_base->tp_free(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isQPropertyType(PyObject* pyObj)
|
||||||
|
{
|
||||||
|
if (pyObj) {
|
||||||
|
return pyObj->ob_type == &QProperty_Type;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int qproperty_set(PyObject* self, PyObject* source, PyObject* value)
|
||||||
|
{
|
||||||
|
QPropertyData *data = reinterpret_cast<QPropertyData*>(self);
|
||||||
|
if (data->fset) {
|
||||||
|
Shiboken::AutoDecRef args(PyTuple_New(2));
|
||||||
|
PyTuple_SET_ITEM(args, 0, source);
|
||||||
|
PyTuple_SET_ITEM(args, 1, value);
|
||||||
|
Py_INCREF(source);
|
||||||
|
Py_INCREF(value);
|
||||||
|
Shiboken::AutoDecRef result(PyObject_CallObject(data->fset, args));
|
||||||
|
return (result.isNull() ? -1 : 0);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* qproperty_get(PyObject* self, PyObject* source)
|
||||||
|
{
|
||||||
|
QPropertyData *data = reinterpret_cast<QPropertyData*>(self);
|
||||||
|
if (data->fget) {
|
||||||
|
Shiboken::AutoDecRef args(PyTuple_New(1));
|
||||||
|
Py_INCREF(source);
|
||||||
|
PyTuple_SET_ITEM(args, 0, source);
|
||||||
|
PyObject *ret = PyObject_CallObject(data->fget, args);
|
||||||
|
if (!ret) {
|
||||||
|
PyErr_Print();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int qproperty_reset(PyObject* self, PyObject* source)
|
||||||
|
{
|
||||||
|
QPropertyData *data = reinterpret_cast<QPropertyData*>(self);
|
||||||
|
if (data->freset) {
|
||||||
|
Shiboken::AutoDecRef args(PyTuple_New(1));
|
||||||
|
Py_INCREF(source);
|
||||||
|
PyTuple_SET_ITEM(args, 0, source);
|
||||||
|
Shiboken::AutoDecRef result(PyObject_CallObject(data->freset, args));
|
||||||
|
return (result.isNull() ? -1 : 0);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char* qproperty_get_type(PyObject* self)
|
||||||
|
{
|
||||||
|
QPropertyData *data = reinterpret_cast<QPropertyData*>(self);
|
||||||
|
return data->typeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* qproperty_get_object(PyObject* source, PyObject* name)
|
||||||
|
{
|
||||||
|
if (PyObject_HasAttr(source, name)) {
|
||||||
|
PyObject* attr = PyObject_GenericGetAttr(source, name);
|
||||||
|
if (isQPropertyType(attr))
|
||||||
|
return attr;
|
||||||
|
Py_DECREF(attr);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* translate_type_name(PyObject* type)
|
||||||
|
{
|
||||||
|
if (PyType_Check(type)) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool qproperty_is_writable(PyObject* self)
|
||||||
|
{
|
||||||
|
QPropertyData *data = reinterpret_cast<QPropertyData*>(self);
|
||||||
|
return (data->fset != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool qproperty_has_reset(PyObject* self)
|
||||||
|
{
|
||||||
|
QPropertyData *data = reinterpret_cast<QPropertyData*>(self);
|
||||||
|
return (data->freset != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool qproperty_is_designable(PyObject* self)
|
||||||
|
{
|
||||||
|
QPropertyData *data = reinterpret_cast<QPropertyData*>(self);
|
||||||
|
return data->designable;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool qproperty_is_scriptable(PyObject* self)
|
||||||
|
{
|
||||||
|
QPropertyData *data = reinterpret_cast<QPropertyData*>(self);
|
||||||
|
return data->scriptable;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool qproperty_is_stored(PyObject* self)
|
||||||
|
{
|
||||||
|
QPropertyData *data = reinterpret_cast<QPropertyData*>(self);
|
||||||
|
return data->stored;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool qproperty_is_user(PyObject* self)
|
||||||
|
{
|
||||||
|
QPropertyData *data = reinterpret_cast<QPropertyData*>(self);
|
||||||
|
return data->user;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool qproperty_is_constant(PyObject* self)
|
||||||
|
{
|
||||||
|
QPropertyData *data = reinterpret_cast<QPropertyData*>(self);
|
||||||
|
return data->constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool qproperty_is_final(PyObject* self)
|
||||||
|
{
|
||||||
|
QPropertyData *data = reinterpret_cast<QPropertyData*>(self);
|
||||||
|
return data->final;
|
||||||
|
}
|
||||||
|
|
||||||
|
} //namespace PySide
|
||||||
187
libpyside/qproperty.h
Normal file
187
libpyside/qproperty.h
Normal file
|
|
@ -0,0 +1,187 @@
|
||||||
|
/*
|
||||||
|
* 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_PROPERTY_H
|
||||||
|
#define PYSIDE_PROPERTY_H
|
||||||
|
|
||||||
|
#include <pysidemacros.h>
|
||||||
|
#include <Python.h>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
namespace PySide
|
||||||
|
{
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
PyAPI_DATA(PyTypeObject) QProperty_Type;
|
||||||
|
}; //extern "C"
|
||||||
|
|
||||||
|
PYSIDE_API bool isQPropertyType(PyObject* pyObj);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function call set property function and pass value as arg
|
||||||
|
* This function does not check the property object type
|
||||||
|
*
|
||||||
|
* @param self The property object
|
||||||
|
* @param source The QObject witch has the property
|
||||||
|
* @param value The value to set in property
|
||||||
|
* @return Return 0 if ok or -1 if this function fail
|
||||||
|
**/
|
||||||
|
PYSIDE_API int qproperty_set(PyObject* self, PyObject* source, PyObject* value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function call get 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 the result of property get function or 0 if this fail
|
||||||
|
**/
|
||||||
|
PYSIDE_API PyObject* qproperty_get(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
|
||||||
|
*
|
||||||
|
* @param source The QObject object
|
||||||
|
* @param name The property name
|
||||||
|
* @return Return a new reference to property object
|
||||||
|
**/
|
||||||
|
PYSIDE_API PyObject* qproperty_get_object(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
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -229,10 +229,11 @@ PyObject* signal_instance_get_item(PyObject* self, PyObject* key)
|
||||||
void signalUpdateSource(PyObject* source)
|
void signalUpdateSource(PyObject* source)
|
||||||
{
|
{
|
||||||
Shiboken::AutoDecRef attrs(PyObject_Dir(source));
|
Shiboken::AutoDecRef attrs(PyObject_Dir(source));
|
||||||
|
|
||||||
for(int i = 0, i_max = PyList_GET_SIZE(attrs.object()); i < i_max; i++) {
|
for(int i = 0, i_max = PyList_GET_SIZE(attrs.object()); i < i_max; i++) {
|
||||||
PyObject *attrName = PyList_GET_ITEM(attrs.object(), i);
|
PyObject *attrName = PyList_GET_ITEM(attrs.object(), i);
|
||||||
Shiboken::AutoDecRef attr(PyObject_GetAttr(source, attrName));
|
Shiboken::AutoDecRef attr(PyObject_GetAttr((PyObject*)source->ob_type, attrName));
|
||||||
if (attr->ob_type == &Signal_Type) {
|
if (!attr.isNull() && (attr->ob_type == &Signal_Type)) {
|
||||||
Shiboken::AutoDecRef signalInstance(reinterpret_cast<PyObject*>(PyObject_New(SignalInstanceData, &SignalInstance_Type)));
|
Shiboken::AutoDecRef signalInstance(reinterpret_cast<PyObject*>(PyObject_New(SignalInstanceData, &SignalInstance_Type)));
|
||||||
signal_instance_initialize(signalInstance, attrName, reinterpret_cast<SignalData*>(attr.object()), source, 0);
|
signal_instance_initialize(signalInstance, attrName, reinterpret_cast<SignalData*>(attr.object()), source, 0);
|
||||||
PyObject_SetAttr(source, attrName, signalInstance);
|
PyObject_SetAttr(source, attrName, signalInstance);
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "signalmanager.h"
|
#include "signalmanager.h"
|
||||||
|
#include "qproperty.h"
|
||||||
|
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
|
@ -351,14 +352,87 @@ bool SignalManager::emitSignal(QObject* source, const char* signal, PyObject* ar
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PySide::SignalManager::qt_metacall(QObject* object, QMetaObject::Call call, int id, void** args)
|
int SignalManager::qt_metacall(QObject* object, QMetaObject::Call call, int id, void** args)
|
||||||
{
|
{
|
||||||
const QMetaObject* metaObject = object->metaObject();
|
const QMetaObject* metaObject = object->metaObject();
|
||||||
// only meta method invocation is supported right now.
|
PyObject* pp = 0;
|
||||||
|
PyObject* pp_name = 0;
|
||||||
|
QMetaProperty mp;
|
||||||
|
Shiboken::TypeResolver* typeResolver = 0;
|
||||||
|
PyObject* pySelf = Shiboken::BindingManager::instance().retrieveWrapper(object);
|
||||||
|
|
||||||
if (call != QMetaObject::InvokeMetaMethod) {
|
if (call != QMetaObject::InvokeMetaMethod) {
|
||||||
qWarning("Only meta method invocation is supported right now by PySide.");
|
mp = metaObject->property(id);
|
||||||
return id - metaObject->methodCount();
|
if (!mp.isValid())
|
||||||
|
return id - metaObject->methodCount();
|
||||||
|
|
||||||
|
pp_name = PyString_FromString(mp.name());
|
||||||
|
pp = qproperty_get_object(pySelf, pp_name);
|
||||||
|
if (!pp) {
|
||||||
|
qWarning("Invalid property.");
|
||||||
|
Py_XDECREF(pp_name);
|
||||||
|
return id - metaObject->methodCount();
|
||||||
|
}
|
||||||
|
printf("access to property: %s-%s\n", mp.name(), mp.typeName());
|
||||||
|
typeResolver = Shiboken::TypeResolver::get(mp.typeName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch(call) {
|
||||||
|
#ifndef QT_NO_PROPERTIES
|
||||||
|
case QMetaObject::ReadProperty:
|
||||||
|
{
|
||||||
|
PyObject* value = qproperty_get(pp, pySelf);
|
||||||
|
if (value) {
|
||||||
|
void *data = typeResolver->toCpp(value);
|
||||||
|
if (Shiboken::TypeResolver::getType(mp.typeName()) == Shiboken::TypeResolver::ObjectType)
|
||||||
|
args[0] = &data;
|
||||||
|
else
|
||||||
|
args[0] = data;
|
||||||
|
|
||||||
|
Py_DECREF(value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case QMetaObject::WriteProperty:
|
||||||
|
{
|
||||||
|
Shiboken::AutoDecRef value(typeResolver->toPython(args[0]));
|
||||||
|
qproperty_set(pp, pySelf, value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case QMetaObject::ResetProperty:
|
||||||
|
qproperty_reset(pp, pp_name);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QMetaObject::QueryPropertyDesignable:
|
||||||
|
case QMetaObject::QueryPropertyScriptable:
|
||||||
|
case QMetaObject::QueryPropertyStored:
|
||||||
|
case QMetaObject::QueryPropertyEditable:
|
||||||
|
case QMetaObject::QueryPropertyUser:
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case QMetaObject::InvokeMetaMethod:
|
||||||
|
id = call_method(object, id, args);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
qWarning("Unsupported meta invocation type.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (call == QMetaObject::InvokeMetaMethod)
|
||||||
|
id = id - metaObject->methodCount();
|
||||||
|
else
|
||||||
|
id = id - metaObject->propertyCount();
|
||||||
|
|
||||||
|
Py_XDECREF(pp);
|
||||||
|
Py_XDECREF(pp_name);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SignalManager::call_method(QObject* object, int id, void** args)
|
||||||
|
{
|
||||||
|
const QMetaObject* metaObject = object->metaObject();
|
||||||
QMetaMethod method = metaObject->method(id);
|
QMetaMethod method = metaObject->method(id);
|
||||||
|
|
||||||
if (method.methodType() == QMetaMethod::Signal) {
|
if (method.methodType() == QMetaMethod::Signal) {
|
||||||
|
|
@ -403,6 +477,7 @@ int PySide::SignalManager::qt_metacall(QObject* object, QMetaObject::Call call,
|
||||||
|
|
||||||
bool SignalManager::registerMetaMethod(QObject* source, const char* signature, QMetaMethod::MethodType type)
|
bool SignalManager::registerMetaMethod(QObject* source, const char* signature, QMetaMethod::MethodType type)
|
||||||
{
|
{
|
||||||
|
Q_ASSERT(source);
|
||||||
const QMetaObject* metaObject = source->metaObject();
|
const QMetaObject* metaObject = source->metaObject();
|
||||||
int methodIndex = metaObject->indexOfMethod(signature);
|
int methodIndex = metaObject->indexOfMethod(signature);
|
||||||
// Create the dynamic signal is needed
|
// Create the dynamic signal is needed
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,8 @@ 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);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,3 @@
|
||||||
PYSIDE_TEST(base_test.py)
|
PYSIDE_TEST(base_test.py)
|
||||||
PYSIDE_TEST(engine_test.py)
|
PYSIDE_TEST(engine_test.py)
|
||||||
|
PYSIDE_TEST(property_test.py)
|
||||||
|
|
|
||||||
62
tests/QtScript/property_test.py
Normal file
62
tests/QtScript/property_test.py
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from PySide.QtCore import QObject, QProperty, QCoreApplication
|
||||||
|
from PySide.QtScript import QScriptEngine
|
||||||
|
|
||||||
|
class MyObject(QObject):
|
||||||
|
def __init__(self, parent = None):
|
||||||
|
QObject.__init__(self, parent)
|
||||||
|
self._p = 100
|
||||||
|
|
||||||
|
def setX(self, value):
|
||||||
|
self._p = value
|
||||||
|
|
||||||
|
def getX(self):
|
||||||
|
return self._p
|
||||||
|
|
||||||
|
def resetX(self):
|
||||||
|
self._p = 100
|
||||||
|
|
||||||
|
def delX(self):
|
||||||
|
self._p = 0
|
||||||
|
|
||||||
|
x = QProperty(int, getX, setX, resetX, delX)
|
||||||
|
|
||||||
|
|
||||||
|
class QPropertyTest(unittest.TestCase):
|
||||||
|
|
||||||
|
def testSimple(self):
|
||||||
|
o = MyObject()
|
||||||
|
self.assertEqual(o.x, 100)
|
||||||
|
o.x = 42
|
||||||
|
self.assertEqual(o.x, 42)
|
||||||
|
|
||||||
|
def testHasProperty(self):
|
||||||
|
o = MyObject()
|
||||||
|
o.setProperty("x", 10)
|
||||||
|
self.assertEqual(o.x, 10)
|
||||||
|
self.assertEqual(o.property("x"), 10)
|
||||||
|
|
||||||
|
def testMetaProperty(self):
|
||||||
|
o = MyObject()
|
||||||
|
m = o.metaObject()
|
||||||
|
found = False
|
||||||
|
for i in range(m.propertyCount()):
|
||||||
|
mp = m.property(i)
|
||||||
|
if mp.name() == "x":
|
||||||
|
found = True
|
||||||
|
break
|
||||||
|
self.assert_(found)
|
||||||
|
|
||||||
|
def testScriptQProperty(self):
|
||||||
|
qapp = QCoreApplication([])
|
||||||
|
myEngine = QScriptEngine()
|
||||||
|
obj = MyObject()
|
||||||
|
scriptObj = myEngine.newQObject(obj)
|
||||||
|
myEngine.globalObject().setProperty("obj", scriptObj)
|
||||||
|
myEngine.evaluate("obj.x = 42")
|
||||||
|
self.assertEqual(scriptObj.property("x").toInt32(), 42)
|
||||||
|
self.assertEqual(obj.property("x"), 42)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue