Add a d-pointer to DynamicMetaObject.
This break the ABI.
This commit is contained in:
parent
6b8d262b40
commit
15b0e9aa2b
5 changed files with 138 additions and 100 deletions
|
|
@ -21,10 +21,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#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>
|
||||||
|
|
@ -66,6 +68,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;
|
||||||
|
|
@ -266,76 +280,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 +358,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -412,37 +427,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 +466,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 +500,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 +539,9 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,13 +48,8 @@ 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 inline void deleteDynamicQMetaObject(void* data)
|
||||||
|
|
|
||||||
69
libpyside/dynamicqmetaobject_p.h
Normal file
69
libpyside/dynamicqmetaobject_p.h
Normal 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
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#include "qproperty.h"
|
#include "qproperty.h"
|
||||||
|
#include "dynamicqmetaobject_p.h"
|
||||||
|
|
||||||
#define QPROPERTY_CLASS_NAME "Property"
|
#define QPROPERTY_CLASS_NAME "Property"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <shiboken.h>
|
#include <shiboken.h>
|
||||||
#include <dynamicqmetaobject.h>
|
#include "dynamicqmetaobject_p.h"
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue