From 4acabb3abd0ff109b9abeedb6832f5b1c3e0cc4e Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Fri, 5 Jun 2009 13:05:24 +0200 Subject: handle qreal properties correctly in the meta-object system When cross-compiling, it's possible that the size of qreal for moc itself (host platform) is different from the size of qreal on the target platform. Thus, we should not encode the metatype-id of qreal at moc time. Instead, use QMetaType::QReal in the generated code so that the the property flags are only derived at compile time. We also need to support the pesky QT_COORD_TYPE. In this case, qreal can be _any_ type (not just float or double), so we encode the property type as 0 and have a special check in QMetaProperty::type() that resolves the correct type at runtime. Reviewed-by: Simon Hausmann --- src/corelib/global/qglobal.h | 1 + src/corelib/kernel/qmetaobject.cpp | 5 +++++ src/corelib/kernel/qmetatype.cpp | 1 + src/corelib/kernel/qmetatype.h | 9 +++++++++ src/corelib/kernel/qobjectdefs.h | 2 +- src/tools/moc/generator.cpp | 20 +++++++++++++++----- src/tools/moc/outputrevision.h | 2 +- tests/auto/qobject/tst_qobject.cpp | 27 +++++++++++++++++++++++++++ 8 files changed, 60 insertions(+), 7 deletions(-) diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 3990c7d..a10b6d6 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -1004,6 +1004,7 @@ typedef int QNoImplicitBoolCast; #define QT_NO_FPU #endif +// This logic must match the one in qmetatype.h #if defined(QT_COORD_TYPE) typedef QT_COORD_TYPE qreal; #elif defined(QT_NO_FPU) || defined(QT_ARCH_ARM) || defined(QT_ARCH_WINDOWSCE) diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index b65f956..6f3316c 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -2003,6 +2003,11 @@ QVariant::Type QMetaProperty::type() const if (enumMetaTypeId == 0) return QVariant::Int; } +#ifdef QT_COORD_TYPE + // qreal metatype must be resolved at runtime. + if (strcmp(typeName(), "qreal") == 0) + return QVariant::Type(qMetaTypeId()); +#endif return QVariant::UserType; } diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index ce10bae..a0b954f 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -179,6 +179,7 @@ QT_BEGIN_NAMESPACE \omitvalue LastCoreExtType \omitvalue LastCoreType \omitvalue LastGuiType + \omitvalue QReal Additional types can be registered using Q_DECLARE_METATYPE(). diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 648f933..be8a667 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -86,6 +86,15 @@ public: UShort = 133, UChar = 134, Float = 135, QObjectStar = 136, QWidgetStar = 137, LastCoreExtType = 137 /* QWidgetStar */, +// This logic must match the one in qglobal.h +#if defined(QT_COORD_TYPE) + QReal = 0, +#elif defined(QT_NO_FPU) || defined(QT_ARCH_ARM) || defined(QT_ARCH_WINDOWSCE) + QReal = Float, +#else + QReal = Double, +#endif + User = 256 }; diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index 3a22323..f5d08ce 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -55,7 +55,7 @@ class QByteArray; class QString; #ifndef Q_MOC_OUTPUT_REVISION -#define Q_MOC_OUTPUT_REVISION 61 +#define Q_MOC_OUTPUT_REVISION 62 #endif // The following macros are our "extensions" to C++ diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index e94bb77..e4ad068 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -109,6 +109,14 @@ bool isVariantType(const char* type) return qvariant_nameToType(type) != 0; } +/*! + Returns true if the type is qreal. +*/ +static bool isQRealType(const char *type) +{ + return strcmp(type, "qreal") == 0; +} + Generator::Generator(ClassDef *classDef, const QList &metaTypes, FILE *outfile) : out(outfile), cdef(classDef), metaTypes(metaTypes) { @@ -545,7 +553,7 @@ void Generator::generateProperties() uint flags = Invalid; if (!isVariantType(p.type)) { flags |= EnumOrFlag; - } else { + } else if (!isQRealType(p.type)) { flags |= qvariant_nameToType(p.type) << 24; } if (!p.read.isEmpty()) @@ -589,10 +597,12 @@ void Generator::generateProperties() if (p.notifyId != -1) flags |= Notify; - fprintf(out, " %4d, %4d, 0x%.8x,\n", - strreg(p.name), - strreg(p.type), - flags); + fprintf(out, " %4d, %4d, ", + strreg(p.name), + strreg(p.type)); + if (!(flags >> 24) && isQRealType(p.type)) + fprintf(out, "(QMetaType::QReal << 24) | "); + fprintf(out, "0x%.8x,\n", flags); } if(cdef->notifyableProperties) { diff --git a/src/tools/moc/outputrevision.h b/src/tools/moc/outputrevision.h index 1e1d640..f577f6c 100644 --- a/src/tools/moc/outputrevision.h +++ b/src/tools/moc/outputrevision.h @@ -43,6 +43,6 @@ #define OUTPUTREVISION_H // if the output revision changes, you MUST change it in qobjectdefs.h too -enum { mocOutputRevision = 61 }; // moc format output revision +enum { mocOutputRevision = 62 }; // moc format output revision #endif // OUTPUTREVISION_H diff --git a/tests/auto/qobject/tst_qobject.cpp b/tests/auto/qobject/tst_qobject.cpp index 399d021..d76c7d4 100644 --- a/tests/auto/qobject/tst_qobject.cpp +++ b/tests/auto/qobject/tst_qobject.cpp @@ -106,6 +106,7 @@ private slots: void childDeletesItsSibling(); void dynamicProperties(); void floatProperty(); + void qrealProperty(); void property(); void recursiveSignalEmission(); void blockingQueuedConnection(); @@ -1113,6 +1114,7 @@ class PropertyObject : public QObject Q_PROPERTY(QVariant variant READ variant WRITE setVariant) Q_PROPERTY(CustomType* custom READ custom WRITE setCustom) Q_PROPERTY(float myFloat READ myFloat WRITE setMyFloat) + Q_PROPERTY(qreal myQReal READ myQReal WRITE setMyQReal) public: enum Alpha { @@ -1148,6 +1150,9 @@ public: void setMyFloat(float value) { m_float = value; } inline float myFloat() const { return m_float; } + void setMyQReal(qreal value) { m_qreal = value; } + qreal myQReal() const { return m_qreal; } + private: Alpha m_alpha; Priority m_priority; @@ -1156,6 +1161,7 @@ private: QVariant m_variant; CustomType *m_custom; float m_float; + qreal m_qreal; }; Q_DECLARE_METATYPE(PropertyObject::Priority) @@ -2348,6 +2354,27 @@ void tst_QObject::floatProperty() QVERIFY(qVariantValue(v) == 128.0f); } +void tst_QObject::qrealProperty() +{ + PropertyObject obj; + const int idx = obj.metaObject()->indexOfProperty("myQReal"); + QVERIFY(idx > 0); + QMetaProperty prop = obj.metaObject()->property(idx); + QVERIFY(prop.isValid()); + QVERIFY(prop.type() == uint(QMetaType::type("qreal"))); + QVERIFY(!prop.write(&obj, QVariant("Hello"))); + + QVERIFY(prop.write(&obj, qVariantFromValue(128.0f))); + QVariant v = prop.read(&obj); + QCOMPARE(v.userType(), qMetaTypeId()); + QVERIFY(qVariantValue(v) == 128.0); + + QVERIFY(prop.write(&obj, qVariantFromValue(double(127)))); + v = prop.read(&obj); + QCOMPARE(v.userType(), qMetaTypeId()); + QVERIFY(qVariantValue(v) == 127.0); +} + class DynamicPropertyObject : public PropertyObject { public: -- cgit v0.12