From 78e1a866ba5d594233db80f7aab88331db237d3a Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Wed, 17 Mar 2010 01:29:17 +0100 Subject: Implement Q_PRIVATE_PROPERTY that allows you to declare properties where the read/write are in the d pointer. Works like Q_PRIVATE_SLOT. Reviewed-by:olivier Reviewed-by:akennedy Reviewed-by:warwick allison --- src/corelib/kernel/qobjectdefs.h | 2 ++ src/tools/moc/generator.cpp | 43 ++++++++++++++++++--------- src/tools/moc/keywords.cpp | 30 ++++++++++++++----- src/tools/moc/moc.cpp | 44 +++++++++++++++++++++++---- src/tools/moc/moc.h | 4 ++- src/tools/moc/token.cpp | 1 + src/tools/moc/token.h | 1 + src/tools/moc/util/generate_keywords.cpp | 2 +- tests/auto/moc/tst_moc.cpp | 51 ++++++++++++++++++++++++++++++++ 9 files changed, 150 insertions(+), 28 deletions(-) diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index 8ed7f3f..f496354 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -78,6 +78,7 @@ class QString; #define Q_CLASSINFO(name, value) #define Q_INTERFACES(x) #define Q_PROPERTY(text) +#define Q_PRIVATE_PROPERTY(d, text) #define Q_OVERRIDE(text) #define Q_ENUMS(x) #define Q_FLAGS(x) @@ -178,6 +179,7 @@ private: #define Q_CLASSINFO(name, value) Q_CLASSINFO(name, value) #define Q_INTERFACES(x) Q_INTERFACES(x) #define Q_PROPERTY(text) Q_PROPERTY(text) +#define Q_PRIVATE_PROPERTY(d, text) Q_PRIVATE_PROPERTY(d, text) #define Q_OVERRIDE(text) Q_OVERRIDE(text) #define Q_ENUMS(x) Q_ENUMS(x) #define Q_FLAGS(x) Q_FLAGS(x) diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index 982d95f5..ff8029b 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -738,18 +738,23 @@ void Generator::generateMetacall() const PropertyDef &p = cdef->propertyList.at(propindex); if (p.read.isEmpty()) continue; + QByteArray prefix; + if (p.inPrivateClass.size()) { + prefix = p.inPrivateClass; + prefix.append("->"); + } if (p.gspec == PropertyDef::PointerSpec) - fprintf(out, " case %d: _a[0] = const_cast(reinterpret_cast(%s())); break;\n", - propindex, p.read.constData()); + fprintf(out, " case %d: _a[0] = const_cast(reinterpret_cast(%s%s())); break;\n", + propindex, prefix.constData(), p.read.constData()); else if (p.gspec == PropertyDef::ReferenceSpec) - fprintf(out, " case %d: _a[0] = const_cast(reinterpret_cast(&%s())); break;\n", - propindex, p.read.constData()); + fprintf(out, " case %d: _a[0] = const_cast(reinterpret_cast(&%s%s())); break;\n", + propindex, prefix.constData(), p.read.constData()); else if (cdef->enumDeclarations.value(p.type, false)) - fprintf(out, " case %d: *reinterpret_cast(_v) = QFlag(%s()); break;\n", - propindex, p.read.constData()); + fprintf(out, " case %d: *reinterpret_cast(_v) = QFlag(%s%s()); break;\n", + propindex, prefix.constData(), p.read.constData()); else - fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s(); break;\n", - propindex, p.type.constData(), p.read.constData()); + fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s(); break;\n", + propindex, p.type.constData(), prefix.constData(), p.read.constData()); } fprintf(out, " }\n"); } @@ -768,12 +773,17 @@ void Generator::generateMetacall() const PropertyDef &p = cdef->propertyList.at(propindex); if (p.write.isEmpty()) continue; + QByteArray prefix; + if (p.inPrivateClass.size()) { + prefix = p.inPrivateClass; + prefix.append("->"); + } if (cdef->enumDeclarations.value(p.type, false)) { - fprintf(out, " case %d: %s(QFlag(*reinterpret_cast(_v))); break;\n", - propindex, p.write.constData()); + fprintf(out, " case %d: %s%s(QFlag(*reinterpret_cast(_v))); break;\n", + propindex, prefix.constData(), p.write.constData()); } else { - fprintf(out, " case %d: %s(*reinterpret_cast< %s*>(_v)); break;\n", - propindex, p.write.constData(), p.type.constData()); + fprintf(out, " case %d: %s%s(*reinterpret_cast< %s*>(_v)); break;\n", + propindex, prefix.constData(), p.write.constData(), p.type.constData()); } } fprintf(out, " }\n"); @@ -791,8 +801,13 @@ void Generator::generateMetacall() const PropertyDef &p = cdef->propertyList.at(propindex); if (!p.reset.endsWith(')')) continue; - fprintf(out, " case %d: %s; break;\n", - propindex, p.reset.constData()); + QByteArray prefix; + if (p.inPrivateClass.size()) { + prefix = p.inPrivateClass; + prefix.append("->"); + } + fprintf(out, " case %d: %s%s; break;\n", + propindex, prefix.constData(), p.reset.constData()); } fprintf(out, " }\n"); } diff --git a/src/tools/moc/keywords.cpp b/src/tools/moc/keywords.cpp index abc6be0..df1ba0d 100644 --- a/src/tools/moc/keywords.cpp +++ b/src/tools/moc/keywords.cpp @@ -43,12 +43,12 @@ // DO NOT EDIT. static const short keyword_trans[][128] = { - {0,0,0,0,0,0,0,0,0,525,522,0,0,0,0,0, + {0,0,0,0,0,0,0,0,0,533,530,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 525,252,523,526,0,38,239,524,25,26,236,234,30,235,27,237, + 533,252,531,534,0,38,239,532,25,26,236,234,30,235,27,237, 22,22,22,22,22,22,22,22,22,22,34,41,23,39,24,43, 0,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,21,8,8,8,8,8,8,8,8,8,31,527,32,238,8, + 8,21,8,8,8,8,8,8,8,8,8,31,535,32,238,8, 0,1,2,3,4,5,6,7,8,9,8,8,10,11,12,13, 14,8,15,16,17,18,19,20,8,8,8,36,245,37,248,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -190,7 +190,7 @@ static const short keyword_trans[][128] = { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,42,0,0,0,28,0, - 530,530,530,530,530,530,530,530,530,530,0,0,0,0,0,0, + 538,538,538,538,538,538,538,538,538,538,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -349,7 +349,7 @@ static const short keyword_trans[][128] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,529,0,0,0,0,528, + 0,0,0,0,0,0,0,0,0,0,537,0,0,0,0,536, 0,0,0,0,0,0,0,0,0,0,0,0,0,258,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -430,6 +430,14 @@ static const short keyword_trans[][128] = { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 522,0,0,481,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,497,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,486, @@ -925,12 +933,12 @@ static const struct {CHARACTER, 0, 84, 478, CHARACTER}, {CHARACTER, 0, 69, 479, CHARACTER}, {CHARACTER, 0, 95, 480, CHARACTER}, - {CHARACTER, 0, 83, 481, CHARACTER}, + {CHARACTER, 48, 0, 0, CHARACTER}, {CHARACTER, 0, 76, 482, CHARACTER}, {CHARACTER, 0, 79, 483, CHARACTER}, {CHARACTER, 0, 84, 484, CHARACTER}, {Q_PRIVATE_SLOT_TOKEN, 0, 0, 0, CHARACTER}, - {CHARACTER, 48, 0, 0, CHARACTER}, + {CHARACTER, 49, 0, 0, CHARACTER}, {CHARACTER, 0, 77, 487, CHARACTER}, {CHARACTER, 0, 79, 488, CHARACTER}, {CHARACTER, 0, 67, 489, CHARACTER}, @@ -967,6 +975,14 @@ static const struct {CHARACTER, 0, 76, 520, CHARACTER}, {CHARACTER, 0, 69, 521, CHARACTER}, {Q_SCRIPTABLE_TOKEN, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 82, 523, CHARACTER}, + {CHARACTER, 0, 79, 524, CHARACTER}, + {CHARACTER, 0, 80, 525, CHARACTER}, + {CHARACTER, 0, 69, 526, CHARACTER}, + {CHARACTER, 0, 82, 527, CHARACTER}, + {CHARACTER, 0, 84, 528, CHARACTER}, + {CHARACTER, 0, 89, 529, CHARACTER}, + {Q_PRIVATE_PROPERTY_TOKEN, 0, 0, 0, CHARACTER}, {NEWLINE, 0, 0, 0, NOTOKEN}, {QUOTE, 0, 0, 0, NOTOKEN}, {SINGLEQUOTE, 0, 0, 0, NOTOKEN}, diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 94ad56f..680b8a5 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -658,6 +658,9 @@ void Moc::parse() case Q_PRIVATE_SLOT_TOKEN: parseSlotInPrivate(&def, access); break; + case Q_PRIVATE_PROPERTY_TOKEN: + parsePrivateProperty(&def); + break; case ENUM: { EnumDef enumDef; if (parseEnum(&enumDef)) @@ -872,11 +875,8 @@ void Moc::parseSignals(ClassDef *def) } } - -void Moc::parseProperty(ClassDef *def) +void Moc::createPropertyDef(PropertyDef &propDef) { - next(LPAREN); - PropertyDef propDef; QByteArray type = parseType().name; if (type.isEmpty()) error(); @@ -964,7 +964,6 @@ void Moc::parseProperty(ClassDef *def) error(2); } } - next(RPAREN); if (propDef.read.isNull()) { QByteArray msg; msg += "Property declaration "; @@ -988,6 +987,41 @@ void Moc::parseProperty(ClassDef *def) propDef.constant = false; warning(msg.constData()); } +} + +void Moc::parseProperty(ClassDef *def) +{ + next(LPAREN); + PropertyDef propDef; + createPropertyDef(propDef); + next(RPAREN); + + + if(!propDef.notify.isEmpty()) + def->notifyableProperties++; + def->propertyList += propDef; +} + +void Moc::parsePrivateProperty(ClassDef *def) +{ + next(LPAREN); + PropertyDef propDef; + next(IDENTIFIER); + propDef.inPrivateClass = lexem(); + while (test(SCOPE)) { + propDef.inPrivateClass += lexem(); + next(IDENTIFIER); + propDef.inPrivateClass += lexem(); + } + // also allow void functions + if (test(LPAREN)) { + next(RPAREN); + propDef.inPrivateClass += "()"; + } + + next(COMMA); + + createPropertyDef(propDef); if(!propDef.notify.isEmpty()) def->notifyableProperties++; diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h index 10abfc6..d365ed5 100644 --- a/src/tools/moc/moc.h +++ b/src/tools/moc/moc.h @@ -116,7 +116,7 @@ struct FunctionDef struct PropertyDef { PropertyDef():notifyId(-1), constant(false), final(false), gspec(ValueSpec){} - QByteArray name, type, read, write, reset, designable, scriptable, editable, stored, user, notify; + QByteArray name, type, read, write, reset, designable, scriptable, editable, stored, user, notify, inPrivateClass; int notifyId; bool constant; bool final; @@ -217,6 +217,7 @@ public: void parseSlots(ClassDef *def, FunctionDef::Access access); void parseSignals(ClassDef *def); void parseProperty(ClassDef *def); + void createPropertyDef(PropertyDef &def); void parseEnumOrFlag(ClassDef *def, bool isFlag); void parseFlag(ClassDef *def); void parseClassInfo(ClassDef *def); @@ -224,6 +225,7 @@ public: void parseDeclareInterface(); void parseDeclareMetatype(); void parseSlotInPrivate(ClassDef *def, FunctionDef::Access access); + void parsePrivateProperty(ClassDef *def); void parseFunctionArguments(FunctionDef *def); diff --git a/src/tools/moc/token.cpp b/src/tools/moc/token.cpp index 98307a1..3da9446 100644 --- a/src/tools/moc/token.cpp +++ b/src/tools/moc/token.cpp @@ -179,6 +179,7 @@ const char *tokenTypeName(Token t) case Q_SIGNAL_TOKEN: return "Q_SIGNAL_TOKEN"; case Q_SLOT_TOKEN: return "Q_SLOT_TOKEN"; case Q_PRIVATE_SLOT_TOKEN: return "Q_PRIVATE_SLOT_TOKEN"; + case Q_PRIVATE_PROPERTY_TOKEN: return "Q_PRIVATE_PROPERTY_TOKEN"; case SPECIAL_TREATMENT_MARK: return "SPECIAL_TREATMENT_MARK"; case MOC_INCLUDE_BEGIN: return "MOC_INCLUDE_BEGIN"; case MOC_INCLUDE_END: return "MOC_INCLUDE_END"; diff --git a/src/tools/moc/token.h b/src/tools/moc/token.h index 6b1ad7d..6ca3d84 100644 --- a/src/tools/moc/token.h +++ b/src/tools/moc/token.h @@ -185,6 +185,7 @@ enum Token { Q_QT3_SUPPORT_TOKEN, Q_INVOKABLE_TOKEN, Q_SCRIPTABLE_TOKEN, + Q_PRIVATE_PROPERTY_TOKEN, Q_META_TOKEN_END, SPECIAL_TREATMENT_MARK = Q_META_TOKEN_END, MOC_INCLUDE_BEGIN, diff --git a/src/tools/moc/util/generate_keywords.cpp b/src/tools/moc/util/generate_keywords.cpp index 0641b40..88f187d 100644 --- a/src/tools/moc/util/generate_keywords.cpp +++ b/src/tools/moc/util/generate_keywords.cpp @@ -248,7 +248,7 @@ static const Keyword keywords[] = { { "Q_SIGNAL", "Q_SIGNAL_TOKEN" }, { "Q_SLOT", "Q_SLOT_TOKEN" }, { "Q_SCRIPTABLE", "Q_SCRIPTABLE_TOKEN" }, - + { "Q_PRIVATE_PROPERTY", "Q_PRIVATE_PROPERTY_TOKEN" }, { "\n", "NEWLINE" }, { "\"", "QUOTE" }, { "\'", "SINGLEQUOTE" }, diff --git a/tests/auto/moc/tst_moc.cpp b/tests/auto/moc/tst_moc.cpp index fad4845..30c2721 100644 --- a/tests/auto/moc/tst_moc.cpp +++ b/tests/auto/moc/tst_moc.cpp @@ -484,6 +484,7 @@ private slots: void singleFunctionKeywordSignalAndSlot(); void templateGtGt(); void qprivateslots(); + void qprivateproperties(); void inlineSlotsWithThrowDeclaration(); void warnOnPropertyWithoutREAD(); void constructors(); @@ -1071,6 +1072,56 @@ void tst_Moc::qprivateslots() QVERIFY(mobj->indexOfMethod("method1()") != -1); //tast204730 } +class PrivatePropertyTest : public QObject +{ + Q_OBJECT + Q_PROPERTY(int foo READ foo WRITE setFoo); + Q_PRIVATE_PROPERTY(d, int bar READ bar WRITE setBar); + Q_PRIVATE_PROPERTY(PrivatePropertyTest::d, int plop READ plop WRITE setPlop); + Q_PRIVATE_PROPERTY(PrivatePropertyTest::d_func(), int baz READ baz WRITE setBaz); + class MyDPointer { + public: + MyDPointer() : mBar(0), mPlop(0) {} + int bar() { return mBar ; } + void setBar(int value) { mBar = value; } + int plop() { return mPlop ; } + void setPlop(int value) { mPlop = value; } + int baz() { return mBaz ; } + void setBaz(int value) { mBaz = value; } + private: + int mBar; + int mPlop; + int mBaz; + }; +public: + PrivatePropertyTest() : mFoo(0), d (new MyDPointer) {} + int foo() { return mFoo ; } + void setFoo(int value) { mFoo = value; } + MyDPointer *d_func() {return d;} +private: + int mFoo; + MyDPointer *d; +}; + + +void tst_Moc::qprivateproperties() +{ + PrivatePropertyTest test; + + test.setProperty("foo", 1); + QCOMPARE(test.property("foo"), qVariantFromValue(1)); + + test.setProperty("bar", 2); + QCOMPARE(test.property("bar"), qVariantFromValue(2)); + + test.setProperty("plop", 3); + QCOMPARE(test.property("plop"), qVariantFromValue(3)); + + test.setProperty("baz", 4); + QCOMPARE(test.property("baz"), qVariantFromValue(4)); + +} + #include "task189996.h" void InlineSlotsWithThrowDeclaration::c() throw() {} -- cgit v0.12