moc: Allow writing properties through bindables
BINDABLE should generally behave the same as MEMBER if "WRITE default", except where it cannot. In particular we cannot know if any NOTIFY signal should be sent from the synthetic WRITE accessor. [ChangeLog][QtCore] moc will now synthesize WRITE accessors for properties with BINDABLE if you specify "WRITE default". Task-number: QTBUG-97249 Change-Id: I883c40ba0dda7989c840971860addaeaa75a8c83 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
d56f80fd9a
commit
66a30b9a33
@ -53,7 +53,12 @@
|
|||||||
argument, either of the property's type or a pointer or reference
|
argument, either of the property's type or a pointer or reference
|
||||||
to that type. e.g., QWidget::enabled has the \c WRITE function
|
to that type. e.g., QWidget::enabled has the \c WRITE function
|
||||||
QWidget::setEnabled(). Read-only properties do not need \c WRITE
|
QWidget::setEnabled(). Read-only properties do not need \c WRITE
|
||||||
functions. e.g., QWidget::focus has no \c WRITE function.
|
functions. e.g., QWidget::focus has no \c WRITE function. If you specify
|
||||||
|
both a \c BINDABLE and \c{WRITE default}, a \c WRITE accessor will be
|
||||||
|
generated from the \c BINDABLE. The generated \c WRITE accessor will \e not
|
||||||
|
explicitly emit any signal declared with \c NOTIFY. You should register
|
||||||
|
the signal as change handler to the \c BINDABLE, for example using
|
||||||
|
\l{Q_OBJECT_BINDABLE_PROPERTY}.
|
||||||
|
|
||||||
\li A \c MEMBER variable association is required if no \c READ accessor
|
\li A \c MEMBER variable association is required if no \c READ accessor
|
||||||
function is specified. This makes the given member variable
|
function is specified. This makes the given member variable
|
||||||
|
@ -1315,6 +1315,12 @@ void Generator::generateStaticMetacall()
|
|||||||
if (cdef->enumDeclarations.value(p.type, false)) {
|
if (cdef->enumDeclarations.value(p.type, false)) {
|
||||||
fprintf(out, " case %d: %s%s(QFlag(*reinterpret_cast<int*>(_v))); break;\n",
|
fprintf(out, " case %d: %s%s(QFlag(*reinterpret_cast<int*>(_v))); break;\n",
|
||||||
propindex, prefix.constData(), p.write.constData());
|
propindex, prefix.constData(), p.write.constData());
|
||||||
|
} else if (p.write == "default") {
|
||||||
|
fprintf(out, " case %d: {\n", propindex);
|
||||||
|
fprintf(out, " %s%s().setValue(*reinterpret_cast< %s*>(_v));\n",
|
||||||
|
prefix.constData(), p.bind.constData(), p.type.constData());
|
||||||
|
fprintf(out, " break;\n");
|
||||||
|
fprintf(out, " }\n");
|
||||||
} else if (!p.write.isEmpty()) {
|
} else if (!p.write.isEmpty()) {
|
||||||
fprintf(out, " case %d: %s%s(*reinterpret_cast< %s*>(_v)); break;\n",
|
fprintf(out, " case %d: %s%s(*reinterpret_cast< %s*>(_v)); break;\n",
|
||||||
propindex, prefix.constData(), p.write.constData(), p.type.constData());
|
propindex, prefix.constData(), p.write.constData(), p.type.constData());
|
||||||
|
@ -1301,7 +1301,7 @@ void Moc::parsePropertyAttributes(PropertyDef &propDef)
|
|||||||
error(1);
|
error(1);
|
||||||
} else if (test(DEFAULT)) {
|
} else if (test(DEFAULT)) {
|
||||||
v = lexem();
|
v = lexem();
|
||||||
if (l != "READ")
|
if (l != "READ" && l != "WRITE")
|
||||||
error(1);
|
error(1);
|
||||||
} else {
|
} else {
|
||||||
next(IDENTIFIER);
|
next(IDENTIFIER);
|
||||||
@ -1387,6 +1387,12 @@ void Moc::parsePropertyAttributes(PropertyDef &propDef)
|
|||||||
propDef.read = "";
|
propDef.read = "";
|
||||||
warning(msg.constData());
|
warning(msg.constData());
|
||||||
}
|
}
|
||||||
|
if (propDef.write == "default" && propDef.bind.isNull()) {
|
||||||
|
const QByteArray msg = "Property declaration " + propDef.name
|
||||||
|
+ " is not BINDable but default-WRITEable. WRITE will be ignored.";
|
||||||
|
propDef.write = "";
|
||||||
|
warning(msg.constData());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Moc::parseProperty(ClassDef *def)
|
void Moc::parseProperty(ClassDef *def)
|
||||||
|
@ -744,7 +744,7 @@ private slots:
|
|||||||
void observerMetaCall();
|
void observerMetaCall();
|
||||||
void setQPRopertyBinding();
|
void setQPRopertyBinding();
|
||||||
void privateQPropertyShim();
|
void privateQPropertyShim();
|
||||||
void readThroughBindable();
|
void readWriteThroughBindable();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void sigWithUnsignedArg(unsigned foo);
|
void sigWithUnsignedArg(unsigned foo);
|
||||||
@ -4339,7 +4339,7 @@ void tst_Moc::privateQPropertyShim()
|
|||||||
class BindableOnly : public QObject
|
class BindableOnly : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(int score BINDABLE scoreBindable READ default)
|
Q_PROPERTY(int score BINDABLE scoreBindable READ default WRITE default)
|
||||||
public:
|
public:
|
||||||
BindableOnly(QObject *parent = nullptr)
|
BindableOnly(QObject *parent = nullptr)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
@ -4350,27 +4350,64 @@ private:
|
|||||||
QProperty<int> m_score;
|
QProperty<int> m_score;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class BindableAndNotifyable : public QObject
|
||||||
void tst_Moc::readThroughBindable()
|
|
||||||
{
|
{
|
||||||
BindableOnly o;
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(int score BINDABLE scoreBindable NOTIFY scoreChanged READ default WRITE default)
|
||||||
|
public:
|
||||||
|
BindableAndNotifyable(QObject *parent = nullptr)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_score(4)
|
||||||
|
{}
|
||||||
|
QBindable<int> scoreBindable() { return QBindable<int>(&m_score); }
|
||||||
|
signals:
|
||||||
|
void scoreChanged();
|
||||||
|
private:
|
||||||
|
QProperty<int> m_score;
|
||||||
|
};
|
||||||
|
|
||||||
QCOMPARE(o.scoreBindable().value(), 4);
|
void tst_Moc::readWriteThroughBindable()
|
||||||
QCOMPARE(o.property("score").toInt(), 4);
|
{
|
||||||
o.scoreBindable().setValue(5);
|
{
|
||||||
QCOMPARE(o.scoreBindable().value(), 5);
|
BindableOnly o;
|
||||||
QCOMPARE(o.property("score").toInt(), 5);
|
QCOMPARE(o.scoreBindable().value(), 4);
|
||||||
|
QCOMPARE(o.property("score").toInt(), 4);
|
||||||
|
o.scoreBindable().setValue(5);
|
||||||
const QMetaObject *mo = o.metaObject();
|
QCOMPARE(o.scoreBindable().value(), 5);
|
||||||
const int i = mo->indexOfProperty("score");
|
QCOMPARE(o.property("score").toInt(), 5);
|
||||||
QVERIFY(i > 0);
|
const QMetaObject *mo = o.metaObject();
|
||||||
|
const int i = mo->indexOfProperty("score");
|
||||||
QMetaProperty p = mo->property(i);
|
QVERIFY(i > 0);
|
||||||
QCOMPARE(p.name(), "score");
|
QMetaProperty p = mo->property(i);
|
||||||
|
QCOMPARE(p.name(), "score");
|
||||||
QVERIFY(p.isValid());
|
QVERIFY(p.isValid());
|
||||||
QCOMPARE(p.read(&o), 5);
|
QVERIFY(p.isWritable());
|
||||||
|
QCOMPARE(p.read(&o), 5);
|
||||||
|
QVERIFY(o.setProperty("score", 6));
|
||||||
|
QCOMPARE(o.property("score").toInt(), 6);
|
||||||
|
QVERIFY(p.write(&o, 7));
|
||||||
|
QCOMPARE(p.read(&o), 7);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
BindableAndNotifyable o;
|
||||||
|
QCOMPARE(o.scoreBindable().value(), 4);
|
||||||
|
QCOMPARE(o.property("score").toInt(), 4);
|
||||||
|
o.scoreBindable().setValue(5);
|
||||||
|
QCOMPARE(o.scoreBindable().value(), 5);
|
||||||
|
QCOMPARE(o.property("score").toInt(), 5);
|
||||||
|
const QMetaObject *mo = o.metaObject();
|
||||||
|
const int i = mo->indexOfProperty("score");
|
||||||
|
QVERIFY(i > 0);
|
||||||
|
QMetaProperty p = mo->property(i);
|
||||||
|
QCOMPARE(p.name(), "score");
|
||||||
|
QVERIFY(p.isValid());
|
||||||
|
QVERIFY(p.isWritable());
|
||||||
|
QCOMPARE(p.read(&o), 5);
|
||||||
|
QVERIFY(o.setProperty("score", 6));
|
||||||
|
QCOMPARE(o.property("score").toInt(), 6);
|
||||||
|
QVERIFY(p.write(&o, 7));
|
||||||
|
QCOMPARE(p.read(&o), 7);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QTEST_MAIN(tst_Moc)
|
QTEST_MAIN(tst_Moc)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user