moc: support mapping pointers to member functions to indexes
This change adds QMetaObject::IndexOfMethod as a parameter to the qt_static_metacall function. It lets the moc generated code return the index of a signal or slot given its pointer to member function This is required to support the new connection syntax Change-Id: I39198c6699b5aa3599d3d282f7ac79b1e3684d33 Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
e9c7edddb5
commit
49bd825a96
@ -443,7 +443,8 @@ struct Q_CORE_EXPORT QMetaObject
|
|||||||
QueryPropertyStored,
|
QueryPropertyStored,
|
||||||
QueryPropertyEditable,
|
QueryPropertyEditable,
|
||||||
QueryPropertyUser,
|
QueryPropertyUser,
|
||||||
CreateInstance
|
CreateInstance,
|
||||||
|
IndexOfMethod
|
||||||
};
|
};
|
||||||
|
|
||||||
int static_metacall(Call, int, void **) const;
|
int static_metacall(Call, int, void **) const;
|
||||||
|
@ -954,6 +954,35 @@ void Generator::generateStaticMetacall()
|
|||||||
}
|
}
|
||||||
fprintf(out, " default: ;\n");
|
fprintf(out, " default: ;\n");
|
||||||
fprintf(out, " }\n");
|
fprintf(out, " }\n");
|
||||||
|
|
||||||
|
fprintf(out, " } else if (_c == QMetaObject::IndexOfMethod) {\n");
|
||||||
|
fprintf(out, " int *result = reinterpret_cast<int *>(_a[0]);\n");
|
||||||
|
fprintf(out, " void **func = reinterpret_cast<void **>(_a[1]);\n");
|
||||||
|
bool anythingUsed = false;
|
||||||
|
for (int methodindex = 0; methodindex < methodList.size(); ++methodindex) {
|
||||||
|
const FunctionDef &f = methodList.at(methodindex);
|
||||||
|
if (f.wasCloned || !f.inPrivateClass.isEmpty() || f.isStatic)
|
||||||
|
continue;
|
||||||
|
anythingUsed = true;
|
||||||
|
fprintf(out, " {\n");
|
||||||
|
fprintf(out, " typedef %s (%s::*_t)(",f.type.rawName.constData() , cdef->classname.constData());
|
||||||
|
for (int j = 0; j < f.arguments.count(); ++j) {
|
||||||
|
const ArgumentDef &a = f.arguments.at(j);
|
||||||
|
if (j)
|
||||||
|
fprintf(out, ", ");
|
||||||
|
fprintf(out, "%s", QByteArray(a.type.name + ' ' + a.rightType).constData());
|
||||||
|
}
|
||||||
|
if (f.isConst)
|
||||||
|
fprintf(out, ") const;\n");
|
||||||
|
else
|
||||||
|
fprintf(out, ");\n");
|
||||||
|
fprintf(out, " if (*reinterpret_cast<_t *>(func) == static_cast<_t>(&%s::%s)) {\n",
|
||||||
|
cdef->classname.constData(), f.name.constData());
|
||||||
|
fprintf(out, " *result = %d;\n", methodindex);
|
||||||
|
fprintf(out, " }\n }\n");
|
||||||
|
}
|
||||||
|
if (!anythingUsed)
|
||||||
|
fprintf(out, " Q_UNUSED(result);\n Q_UNUSED(func);\n");
|
||||||
fprintf(out, " }");
|
fprintf(out, " }");
|
||||||
needElse = true;
|
needElse = true;
|
||||||
}
|
}
|
||||||
|
@ -240,6 +240,7 @@ Type Moc::parseType()
|
|||||||
else if (lookup(0) == STAR)
|
else if (lookup(0) == STAR)
|
||||||
type.referenceType = Type::Pointer;
|
type.referenceType = Type::Pointer;
|
||||||
}
|
}
|
||||||
|
type.rawName = type.name;
|
||||||
// transform stupid things like 'const void' or 'void const' into 'void'
|
// transform stupid things like 'const void' or 'void const' into 'void'
|
||||||
if (isVoid && type.referenceType == Type::NoReference) {
|
if (isVoid && type.referenceType == Type::NoReference) {
|
||||||
type.name = "void";
|
type.name = "void";
|
||||||
@ -404,8 +405,11 @@ bool Moc::parseFunction(FunctionDef *def, bool inMacro)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// we don't support references as return types, it's too dangerous
|
// we don't support references as return types, it's too dangerous
|
||||||
if (def->type.referenceType == Type::Reference)
|
if (def->type.referenceType == Type::Reference) {
|
||||||
|
QByteArray rawName = def->type.rawName;
|
||||||
def->type = Type("void");
|
def->type = Type("void");
|
||||||
|
def->type.rawName = rawName;
|
||||||
|
}
|
||||||
|
|
||||||
def->normalizedType = normalizeType(def->type.name);
|
def->normalizedType = normalizeType(def->type.name);
|
||||||
|
|
||||||
|
@ -58,8 +58,12 @@ struct Type
|
|||||||
enum ReferenceType { NoReference, Reference, RValueReference, Pointer };
|
enum ReferenceType { NoReference, Reference, RValueReference, Pointer };
|
||||||
|
|
||||||
inline Type() : isVolatile(false), isScoped(false), firstToken(NOTOKEN), referenceType(NoReference) {}
|
inline Type() : isVolatile(false), isScoped(false), firstToken(NOTOKEN), referenceType(NoReference) {}
|
||||||
inline explicit Type(const QByteArray &_name) : name(_name), isVolatile(false), isScoped(false), firstToken(NOTOKEN), referenceType(NoReference) {}
|
inline explicit Type(const QByteArray &_name)
|
||||||
|
: name(_name), rawName(name), isVolatile(false), isScoped(false), firstToken(NOTOKEN), referenceType(NoReference) {}
|
||||||
QByteArray name;
|
QByteArray name;
|
||||||
|
//When used as a return type, the type name may be modified to remove the references.
|
||||||
|
// rawName is the type as found in the function signature
|
||||||
|
QByteArray rawName;
|
||||||
uint isVolatile : 1;
|
uint isVolatile : 1;
|
||||||
uint isScoped : 1;
|
uint isScoped : 1;
|
||||||
Token firstToken;
|
Token firstToken;
|
||||||
|
@ -174,6 +174,8 @@ private slots:
|
|||||||
void indexOfMethod_data();
|
void indexOfMethod_data();
|
||||||
void indexOfMethod();
|
void indexOfMethod();
|
||||||
|
|
||||||
|
void indexOfMethodPMF();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void value6Changed();
|
void value6Changed();
|
||||||
void value7Changed(const QString &);
|
void value7Changed(const QString &);
|
||||||
@ -290,6 +292,7 @@ void tst_QMetaObject::connectSlotsByName()
|
|||||||
|
|
||||||
class QtTestObject: public QObject
|
class QtTestObject: public QObject
|
||||||
{
|
{
|
||||||
|
friend class tst_QMetaObject;
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -1115,6 +1118,25 @@ void tst_QMetaObject::indexOfMethod()
|
|||||||
QCOMPARE(object->metaObject()->indexOfSignal(name), !isSignal ? -1 : idx);
|
QCOMPARE(object->metaObject()->indexOfSignal(name), !isSignal ? -1 : idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QMetaObject::indexOfMethodPMF()
|
||||||
|
{
|
||||||
|
#define INDEXOFMETHODPMF_HELPER(ObjectType, Name, Arguments) { \
|
||||||
|
int idx = -1; \
|
||||||
|
void (ObjectType::*signal)Arguments = &ObjectType::Name; \
|
||||||
|
void *signal_p = &signal; \
|
||||||
|
void *args[] = { &idx, signal_p, 0}; \
|
||||||
|
ObjectType::qt_static_metacall(0, QMetaObject::IndexOfMethod, 0, args); \
|
||||||
|
QCOMPARE(ObjectType::staticMetaObject.indexOfMethod(QMetaObject::normalizedSignature(#Name #Arguments)), \
|
||||||
|
ObjectType::staticMetaObject.methodOffset() + idx); \
|
||||||
|
}
|
||||||
|
|
||||||
|
INDEXOFMETHODPMF_HELPER(tst_QMetaObject, value7Changed, (const QString&))
|
||||||
|
INDEXOFMETHODPMF_HELPER(tst_QMetaObject, stdSet, ())
|
||||||
|
INDEXOFMETHODPMF_HELPER(QtTestObject, sl10, (QString,QString,QString,QString,QString,QString,QString,QString,QString,QString))
|
||||||
|
INDEXOFMETHODPMF_HELPER(QtTestObject, sig0, ())
|
||||||
|
INDEXOFMETHODPMF_HELPER(QtTestObject, testLongLong, (qint64, quint64))
|
||||||
|
INDEXOFMETHODPMF_HELPER(QtTestObject, testReference, (QString&))
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_MAIN(tst_QMetaObject)
|
QTEST_MAIN(tst_QMetaObject)
|
||||||
#include "tst_qmetaobject.moc"
|
#include "tst_qmetaobject.moc"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user