Introduce Q_PROPERTY attribute REQUIRED
This is meant to correspond to required properties in QML. Change-Id: I2645981e13f7423bc86b48370c165b3cfe2aaa62 Task-number: QTBUG-81561 Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
This commit is contained in:
parent
49f143e19c
commit
cb3152086c
@ -61,6 +61,7 @@ Q_PROPERTY(type name
|
|||||||
[USER bool]
|
[USER bool]
|
||||||
[CONSTANT]
|
[CONSTANT]
|
||||||
[FINAL])
|
[FINAL])
|
||||||
|
[REQUIRED]
|
||||||
//! [0]
|
//! [0]
|
||||||
|
|
||||||
|
|
||||||
|
@ -144,6 +144,12 @@
|
|||||||
optimizations in some cases, but is not enforced by moc. Care must be taken
|
optimizations in some cases, but is not enforced by moc. Care must be taken
|
||||||
never to override a \c FINAL property.
|
never to override a \c FINAL property.
|
||||||
|
|
||||||
|
\li The presence of the \c REQUIRED attribute indicates that the property
|
||||||
|
should be set by a user of the class. This is not enforced by moc, and is
|
||||||
|
mostly useful for classes exposed to QML. In QML, classes with REQUIRED
|
||||||
|
properties cannot be instantiated unless all REQUIRED properties have
|
||||||
|
been set.
|
||||||
|
|
||||||
\endlist
|
\endlist
|
||||||
|
|
||||||
The \c READ, \c WRITE, and \c RESET functions can be inherited.
|
The \c READ, \c WRITE, and \c RESET functions can be inherited.
|
||||||
|
@ -3572,6 +3572,21 @@ bool QMetaProperty::isFinal() const
|
|||||||
return flags & Final;
|
return flags & Final;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\since 5.15
|
||||||
|
Returns \c true if the property is required; otherwise returns \c false.
|
||||||
|
|
||||||
|
A property is final if the \c{Q_PROPERTY()}'s \c REQUIRED attribute
|
||||||
|
is set.
|
||||||
|
*/
|
||||||
|
bool QMetaProperty::isRequired() const
|
||||||
|
{
|
||||||
|
if (!mobj)
|
||||||
|
return false;
|
||||||
|
int flags = mobj->d.data[handle + 2];
|
||||||
|
return flags & Required;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\obsolete
|
\obsolete
|
||||||
|
|
||||||
|
@ -266,6 +266,7 @@ public:
|
|||||||
bool isUser(const QObject *obj = nullptr) const;
|
bool isUser(const QObject *obj = nullptr) const;
|
||||||
bool isConstant() const;
|
bool isConstant() const;
|
||||||
bool isFinal() const;
|
bool isFinal() const;
|
||||||
|
bool isRequired() const;
|
||||||
|
|
||||||
bool isFlagType() const;
|
bool isFlagType() const;
|
||||||
bool isEnumType() const;
|
bool isEnumType() const;
|
||||||
|
@ -85,7 +85,8 @@ enum PropertyFlags {
|
|||||||
User = 0x00100000,
|
User = 0x00100000,
|
||||||
ResolveUser = 0x00200000,
|
ResolveUser = 0x00200000,
|
||||||
Notify = 0x00400000,
|
Notify = 0x00400000,
|
||||||
Revisioned = 0x00800000
|
Revisioned = 0x00800000,
|
||||||
|
Required = 0x01000000,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum MethodFlags {
|
enum MethodFlags {
|
||||||
|
@ -864,6 +864,8 @@ void Generator::generateProperties()
|
|||||||
flags |= Constant;
|
flags |= Constant;
|
||||||
if (p.final)
|
if (p.final)
|
||||||
flags |= Final;
|
flags |= Final;
|
||||||
|
if (p.required)
|
||||||
|
flags |= Required;
|
||||||
|
|
||||||
fprintf(out, " %4d, ", stridx(p.name));
|
fprintf(out, " %4d, ", stridx(p.name));
|
||||||
generateTypeInfo(p.type);
|
generateTypeInfo(p.type);
|
||||||
|
@ -1238,6 +1238,9 @@ void Moc::createPropertyDef(PropertyDef &propDef)
|
|||||||
} else if(l[0] == 'F' && l == "FINAL") {
|
} else if(l[0] == 'F' && l == "FINAL") {
|
||||||
propDef.final = true;
|
propDef.final = true;
|
||||||
continue;
|
continue;
|
||||||
|
} else if (l[0] == 'R' && l == "REQUIRED") {
|
||||||
|
propDef.required = true;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray v, v2;
|
QByteArray v, v2;
|
||||||
@ -1960,6 +1963,7 @@ QJsonObject PropertyDef::toJson() const
|
|||||||
|
|
||||||
prop[QLatin1String("constant")] = constant;
|
prop[QLatin1String("constant")] = constant;
|
||||||
prop[QLatin1String("final")] = final;
|
prop[QLatin1String("final")] = final;
|
||||||
|
prop[QLatin1String("required")] = required;
|
||||||
|
|
||||||
if (revision > 0)
|
if (revision > 0)
|
||||||
prop[QLatin1String("revision")] = revision;
|
prop[QLatin1String("revision")] = revision;
|
||||||
|
@ -137,6 +137,7 @@ struct PropertyDef
|
|||||||
int revision = 0;
|
int revision = 0;
|
||||||
bool constant = false;
|
bool constant = false;
|
||||||
bool final = false;
|
bool final = false;
|
||||||
|
bool required = false;
|
||||||
|
|
||||||
QJsonObject toJson() const;
|
QJsonObject toJson() const;
|
||||||
};
|
};
|
||||||
|
@ -275,6 +275,7 @@
|
|||||||
"final": false,
|
"final": false,
|
||||||
"name": "flags",
|
"name": "flags",
|
||||||
"read": "flags",
|
"read": "flags",
|
||||||
|
"required": false,
|
||||||
"scriptable": true,
|
"scriptable": true,
|
||||||
"stored": true,
|
"stored": true,
|
||||||
"type": "Flags",
|
"type": "Flags",
|
||||||
@ -299,6 +300,7 @@
|
|||||||
"final": false,
|
"final": false,
|
||||||
"name": "flags",
|
"name": "flags",
|
||||||
"read": "flags",
|
"read": "flags",
|
||||||
|
"required": false,
|
||||||
"scriptable": true,
|
"scriptable": true,
|
||||||
"stored": true,
|
"stored": true,
|
||||||
"type": "Foo::Bar::Flags",
|
"type": "Foo::Bar::Flags",
|
||||||
@ -311,6 +313,7 @@
|
|||||||
"final": false,
|
"final": false,
|
||||||
"name": "flagsList",
|
"name": "flagsList",
|
||||||
"read": "flagsList",
|
"read": "flagsList",
|
||||||
|
"required": false,
|
||||||
"scriptable": true,
|
"scriptable": true,
|
||||||
"stored": true,
|
"stored": true,
|
||||||
"type": "QList<Foo::Bar::Flags>",
|
"type": "QList<Foo::Bar::Flags>",
|
||||||
@ -1988,6 +1991,7 @@
|
|||||||
"final": false,
|
"final": false,
|
||||||
"name": "blah",
|
"name": "blah",
|
||||||
"read": "blah",
|
"read": "blah",
|
||||||
|
"required": false,
|
||||||
"scriptable": true,
|
"scriptable": true,
|
||||||
"stored": true,
|
"stored": true,
|
||||||
"type": "A::SomeEnum",
|
"type": "A::SomeEnum",
|
||||||
@ -2088,6 +2092,7 @@
|
|||||||
"final": false,
|
"final": false,
|
||||||
"name": "blah",
|
"name": "blah",
|
||||||
"read": "blah",
|
"read": "blah",
|
||||||
|
"required": false,
|
||||||
"scriptable": true,
|
"scriptable": true,
|
||||||
"stored": true,
|
"stored": true,
|
||||||
"type": "A::SomeEnum",
|
"type": "A::SomeEnum",
|
||||||
@ -2257,6 +2262,7 @@
|
|||||||
"final": false,
|
"final": false,
|
||||||
"name": "gadgetPoperty",
|
"name": "gadgetPoperty",
|
||||||
"read": "gadgetPoperty",
|
"read": "gadgetPoperty",
|
||||||
|
"required": false,
|
||||||
"scriptable": true,
|
"scriptable": true,
|
||||||
"stored": true,
|
"stored": true,
|
||||||
"type": "Gadget::SomeEnum",
|
"type": "Gadget::SomeEnum",
|
||||||
@ -2268,6 +2274,7 @@
|
|||||||
"final": false,
|
"final": false,
|
||||||
"name": "objectPoperty",
|
"name": "objectPoperty",
|
||||||
"read": "objectPoperty",
|
"read": "objectPoperty",
|
||||||
|
"required": false,
|
||||||
"scriptable": true,
|
"scriptable": true,
|
||||||
"stored": true,
|
"stored": true,
|
||||||
"type": "Object::SomeEnum",
|
"type": "Object::SomeEnum",
|
||||||
@ -2291,6 +2298,7 @@
|
|||||||
"final": false,
|
"final": false,
|
||||||
"name": "nestedGadgetPoperty",
|
"name": "nestedGadgetPoperty",
|
||||||
"read": "nestedGadgetPoperty",
|
"read": "nestedGadgetPoperty",
|
||||||
|
"required": false,
|
||||||
"scriptable": true,
|
"scriptable": true,
|
||||||
"stored": true,
|
"stored": true,
|
||||||
"type": "Nested::Gadget::SomeEnum",
|
"type": "Nested::Gadget::SomeEnum",
|
||||||
@ -2314,6 +2322,7 @@
|
|||||||
"final": false,
|
"final": false,
|
||||||
"name": "nestedObjectPoperty",
|
"name": "nestedObjectPoperty",
|
||||||
"read": "nestedObjectPoperty",
|
"read": "nestedObjectPoperty",
|
||||||
|
"required": false,
|
||||||
"scriptable": true,
|
"scriptable": true,
|
||||||
"stored": true,
|
"stored": true,
|
||||||
"type": "Nested::Object::SomeEnum",
|
"type": "Nested::Object::SomeEnum",
|
||||||
@ -2442,6 +2451,7 @@
|
|||||||
"final": false,
|
"final": false,
|
||||||
"name": "gadgetPoperty",
|
"name": "gadgetPoperty",
|
||||||
"read": "gadgetPoperty",
|
"read": "gadgetPoperty",
|
||||||
|
"required": false,
|
||||||
"scriptable": true,
|
"scriptable": true,
|
||||||
"stored": true,
|
"stored": true,
|
||||||
"type": "Gadget::SomeEnum",
|
"type": "Gadget::SomeEnum",
|
||||||
@ -2453,6 +2463,7 @@
|
|||||||
"final": false,
|
"final": false,
|
||||||
"name": "objectPoperty",
|
"name": "objectPoperty",
|
||||||
"read": "objectPoperty",
|
"read": "objectPoperty",
|
||||||
|
"required": false,
|
||||||
"scriptable": true,
|
"scriptable": true,
|
||||||
"stored": true,
|
"stored": true,
|
||||||
"type": "Object::SomeEnum",
|
"type": "Object::SomeEnum",
|
||||||
@ -2476,6 +2487,7 @@
|
|||||||
"final": false,
|
"final": false,
|
||||||
"name": "nestedGadgetPoperty",
|
"name": "nestedGadgetPoperty",
|
||||||
"read": "nestedGadgetPoperty",
|
"read": "nestedGadgetPoperty",
|
||||||
|
"required": false,
|
||||||
"scriptable": true,
|
"scriptable": true,
|
||||||
"stored": true,
|
"stored": true,
|
||||||
"type": "Nested::Gadget::SomeEnum",
|
"type": "Nested::Gadget::SomeEnum",
|
||||||
@ -2499,6 +2511,7 @@
|
|||||||
"final": false,
|
"final": false,
|
||||||
"name": "nestedObjectPoperty",
|
"name": "nestedObjectPoperty",
|
||||||
"read": "nestedObjectPoperty",
|
"read": "nestedObjectPoperty",
|
||||||
|
"required": false,
|
||||||
"scriptable": true,
|
"scriptable": true,
|
||||||
"stored": true,
|
"stored": true,
|
||||||
"type": "Nested::Object::SomeEnum",
|
"type": "Nested::Object::SomeEnum",
|
||||||
|
@ -719,6 +719,7 @@ private slots:
|
|||||||
void cxx17Namespaces();
|
void cxx17Namespaces();
|
||||||
void cxxAttributes();
|
void cxxAttributes();
|
||||||
void mocJsonOutput();
|
void mocJsonOutput();
|
||||||
|
void requiredProperties();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void sigWithUnsignedArg(unsigned foo);
|
void sigWithUnsignedArg(unsigned foo);
|
||||||
@ -4025,6 +4026,29 @@ void tst_Moc::mocJsonOutput()
|
|||||||
QVERIFY2(actualOutput == expectedOutput, showPotentialDiff(actualOutput, expectedOutput).constData());
|
QVERIFY2(actualOutput == expectedOutput, showPotentialDiff(actualOutput, expectedOutput).constData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class RequiredTest :public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY(int required MEMBER m_required REQUIRED)
|
||||||
|
Q_PROPERTY(int notRequired MEMBER m_notRequired)
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_required;
|
||||||
|
int m_notRequired;
|
||||||
|
};
|
||||||
|
|
||||||
|
void tst_Moc::requiredProperties()
|
||||||
|
{
|
||||||
|
QMetaObject mo = RequiredTest::staticMetaObject;
|
||||||
|
QMetaProperty required = mo.property(mo.indexOfProperty("required"));
|
||||||
|
QVERIFY(required.isValid());
|
||||||
|
QVERIFY(required.isRequired());
|
||||||
|
QMetaProperty notRequired = mo.property(mo.indexOfProperty("notRequired"));
|
||||||
|
QVERIFY(notRequired.isValid());
|
||||||
|
QVERIFY(!notRequired.isRequired());
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_MAIN(tst_Moc)
|
QTEST_MAIN(tst_Moc)
|
||||||
|
|
||||||
// the generated code must compile with QT_NO_KEYWORDS
|
// the generated code must compile with QT_NO_KEYWORDS
|
||||||
|
Loading…
Reference in New Issue
Block a user