Fixed dynamic meta object to avoid empty meta method.

Empty meta methods cause a assert failure on QtDeclarative module.
Also removed the scoped pointer to avoid heap allocation when it's not
needed, as QByteArray is already implicity shared.
This commit is contained in:
Hugo Parente Lima 2010-12-01 15:34:44 -02:00
commit e20a97a480
4 changed files with 58 additions and 52 deletions

View file

@ -43,7 +43,7 @@
#define MAX_GLOBAL_SIGNALS_COUNT 500 #define MAX_GLOBAL_SIGNALS_COUNT 500
#define MAX_GLOBAL_SLOTS_COUNT 500 #define MAX_GLOBAL_SLOTS_COUNT 500
#define GLOBAL_RECEIVER_CLASS_NAME "__GlobalReceiver__" #define EMPTY_META_METHOD "0()"
using namespace PySide; using namespace PySide;
@ -79,7 +79,7 @@ public:
QByteArray m_className; QByteArray m_className;
void updateMetaObject(QMetaObject* metaObj); void updateMetaObject(QMetaObject* metaObj);
void writeMethodsData(QList<MethodData>& methods, unsigned int** data, QList<QByteArray>* strings, int* prtIndex, int maxCount, int nullIndex, int flags); void writeMethodsData(const QList<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)
@ -135,12 +135,12 @@ static bool isQRealType(const char *type)
/* /*
* Avoid API break keep this on cpp * Avoid API break keep this on cpp
*/ */
static int maxSlotsCount(const QByteArray& className) static inline int maxSlotsCount(const QByteArray& className)
{ {
return className == GLOBAL_RECEIVER_CLASS_NAME ? MAX_GLOBAL_SIGNALS_COUNT : MAX_SLOTS_COUNT; return className == GLOBAL_RECEIVER_CLASS_NAME ? MAX_GLOBAL_SIGNALS_COUNT : MAX_SLOTS_COUNT;
} }
static int maxSignalsCount(const QByteArray& className) static inline int maxSignalsCount(const QByteArray& className)
{ {
return className == GLOBAL_RECEIVER_CLASS_NAME ? MAX_GLOBAL_SIGNALS_COUNT : MAX_SIGNALS_COUNT; return className == GLOBAL_RECEIVER_CLASS_NAME ? MAX_GLOBAL_SIGNALS_COUNT : MAX_SIGNALS_COUNT;
} }
@ -198,50 +198,48 @@ uint PropertyData::flags() const
return flags; return flags;
} }
MethodData::MethodData(const char* signature, const char* type) // const QByteArray with EMPTY_META_METHOD, used to save some memory
const QByteArray MethodData::m_emptySig(EMPTY_META_METHOD);
MethodData::MethodData() : m_signature(m_emptySig)
{
}
MethodData::MethodData(const char* signature, const char* type) : m_signature(signature), m_type(type)
{ {
m_signature = QSharedPointer<QByteArray>(new QByteArray(signature));
m_type = QSharedPointer<QByteArray>(new QByteArray(type));
} }
void MethodData::clear() void MethodData::clear()
{ {
m_signature->clear(); m_signature = m_emptySig;
m_type->clear(); m_type.clear();
} }
bool MethodData::operator==(const MethodData& other) const bool MethodData::operator==(const MethodData& other) const
{ {
return *m_signature == other.signature(); return m_signature == other.signature();
} }
bool MethodData::operator==(const char* other) const bool MethodData::operator==(const char* other) const
{ {
return *m_signature == other; return m_signature == other;
} }
QByteArray MethodData::signature() const QByteArray MethodData::signature() const
{ {
if (!m_signature.isNull()) return m_signature;
return *m_signature;
else
return QByteArray();
} }
QByteArray MethodData::type() const QByteArray MethodData::type() const
{ {
if (!m_type.isNull()) { if (m_type == "void")
if (*m_type == "void")
return QByteArray();
return *m_type;
} else {
return QByteArray(); return QByteArray();
} return m_type;
} }
bool MethodData::isValid() const bool MethodData::isValid() const
{ {
return m_signature->size(); return m_signature.size();
} }
PropertyData::PropertyData() PropertyData::PropertyData()
@ -334,29 +332,27 @@ void DynamicQMetaObject::addSlot(const char* slot, const char* type)
if (index != -1) if (index != -1)
return; return;
int maxSlots = maxSlotsCount(m_d->m_className);
if (m_d->m_slots.size() >= maxSlots) {
qWarning() << "Fail to add dynamic slot to QObject. PySide support at most" << maxSlots << "dynamic slots.";
return;
}
//search for a empty space //search for a empty space
MethodData blank; MethodData blank;
index = m_d->m_slots.indexOf(blank); index = m_d->m_slots.indexOf(blank);
if (index != -1) { if (index != -1) {
m_d->m_slots[index] = MethodData(slot, type); m_d->m_slots[index] = MethodData(slot, type);
} else { } else if (m_d->m_slots.size() < maxSlotsCount(m_d->m_className)) {
m_d->m_slots << MethodData(slot, type); m_d->m_slots << MethodData(slot, type);
} else {
qWarning() << "Fail to add dynamic slot to QObject. PySide support at most" << maxSlotsCount(m_d->m_className) << "dynamic slots.";
return;
} }
m_d->updateMetaObject(this); m_d->updateMetaObject(this);
} }
void DynamicQMetaObject::removeSlot(uint index) void DynamicQMetaObject::removeSlot(uint index)
{ {
QMetaMethod m = method(index); const char* methodSig = method(index).signature();
foreach(MethodData md, m_d->m_slots) { QList<MethodData>::iterator it = m_d->m_slots.begin();
if (md.signature() == m.signature()) { for (; it != m_d->m_slots.end(); ++it) {
md.clear(); if (it->signature() == methodSig) {
it->clear();
m_d->updateMetaObject(this); m_d->updateMetaObject(this);
break; break;
} }
@ -460,7 +456,7 @@ void DynamicQMetaObject::removeSignal(uint index)
} }
} }
void DynamicQMetaObject::DynamicQMetaObjectPrivate::writeMethodsData(QList<MethodData>& methods, void DynamicQMetaObject::DynamicQMetaObjectPrivate::writeMethodsData(const QList<MethodData>& methods,
unsigned int** data, unsigned int** data,
QList<QByteArray>* strings, QList<QByteArray>* strings,
int* prtIndex, int* prtIndex,
@ -470,23 +466,28 @@ void DynamicQMetaObject::DynamicQMetaObjectPrivate::writeMethodsData(QList<Metho
{ {
int index = *prtIndex; int index = *prtIndex;
QList<MethodData>::iterator iMethod = methods.begin(); int emptyIndex = registerString(EMPTY_META_METHOD, strings);
for(int i=0; i < maxCount; i++) {
QByteArray mType; QList<MethodData>::const_iterator it = methods.begin();
if (iMethod != methods.end() && ((*iMethod).signature().size() > 0) ) {
(*data)[index++] = registerString((*iMethod).signature(), strings); // func name for (; it != methods.end(); ++it) {
mType = (*iMethod).type(); if (it->signature() != EMPTY_META_METHOD)
} else { (*data)[index++] = registerString(it->signature(), strings); // func name
(*data)[index++] = nullIndex; // func name else
} (*data)[index++] = emptyIndex; // func name
(*data)[index++] = nullIndex; // arguments (*data)[index++] = nullIndex; // arguments
(*data)[index++] = (mType.size() > 0 ? registerString(mType, strings) : nullIndex); // normalized type (*data)[index++] = (it->type().size() > 0 ? registerString(it->type(), strings) : nullIndex); // normalized type
(*data)[index++] = nullIndex; // tags (*data)[index++] = nullIndex; // tags
(*data)[index++] = flags; (*data)[index++] = flags;
if (iMethod != methods.end())
iMethod++;
} }
for (int i = methods.count(); i < maxCount; ++i) {
(*data)[index++] = emptyIndex; // func name
(*data)[index++] = nullIndex; // arguments
(*data)[index++] = nullIndex; // normalized type
(*data)[index++] = nullIndex; // tags
(*data)[index++] = flags;
}
*prtIndex = index; *prtIndex = index;
} }

View file

@ -25,9 +25,9 @@
#include <Python.h> #include <Python.h>
#include <QByteArray> #include <QByteArray>
#include <QSharedPointer>
#define PYSIDE_SLOT_LIST_ATTR "_slots" #define PYSIDE_SLOT_LIST_ATTR "_slots"
#define GLOBAL_RECEIVER_CLASS_NAME "__GlobalReceiver__"
struct PySideProperty; struct PySideProperty;
namespace PySide namespace PySide
@ -35,7 +35,11 @@ namespace PySide
class MethodData class MethodData
{ {
public: public:
MethodData(){} MethodData();
/**
* \param signature method signature
* \param type method return type
*/
MethodData(const char* signature, const char* type = 0); MethodData(const char* signature, const char* type = 0);
void clear(); void clear();
bool isValid() const; bool isValid() const;
@ -43,11 +47,11 @@ namespace PySide
QByteArray type() const; QByteArray type() const;
bool operator==(const MethodData& other) const; bool operator==(const MethodData& other) const;
bool operator==(const char* other) const; bool operator==(const char* other) const;
operator const char*() { return m_signature->data(); }
private: private:
QSharedPointer<QByteArray> m_signature; QByteArray m_signature;
QSharedPointer<QByteArray> m_type; QByteArray m_type;
static const QByteArray m_emptySig;
}; };
class PropertyData class PropertyData

View file

@ -21,6 +21,7 @@
*/ */
#include "globalreceiver.h" #include "globalreceiver.h"
#include "dynamicqmetaobject_p.h"
#include <QMetaMethod> #include <QMetaMethod>
#include <QDebug> #include <QDebug>
@ -32,7 +33,6 @@
#include "signalmanager.h" #include "signalmanager.h"
#define RECEIVER_DESTROYED_SLOT_NAME "__receiverDestroyed__(QObject*)" #define RECEIVER_DESTROYED_SLOT_NAME "__receiverDestroyed__(QObject*)"
#define GLOBAL_RECEIVER_CLASS_NAME "__GlobalReceiver__"
namespace PySide namespace PySide
{ {

View file

@ -25,6 +25,7 @@
#include <shiboken.h> #include <shiboken.h>
#include <QString> #include <QString>
#include <QMetaObject>
#define SLOT_DEC_NAME "Slot" #define SLOT_DEC_NAME "Slot"