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:
parent
52c2a2cd0d
commit
ec7b01c24f
4 changed files with 58 additions and 52 deletions
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue