Add a d-pointer to DynamicMetaObject.

This break the ABI.
This commit is contained in:
Hugo Parente Lima 2010-10-06 14:49:12 -03:00
commit 15b0e9aa2b
5 changed files with 138 additions and 100 deletions

View file

@ -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;
} }

View file

@ -26,51 +26,10 @@
#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:
@ -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)

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

@ -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"

View file

@ -21,7 +21,7 @@
*/ */
#include <shiboken.h> #include <shiboken.h>
#include <dynamicqmetaobject.h> #include "dynamicqmetaobject_p.h"
#include <QString> #include <QString>