diff options
-rw-r--r-- | src/corelib/doc/src/objectmodel/properties.qdoc | 7 | ||||
-rw-r--r-- | src/tools/moc/generator.cpp | 6 | ||||
-rw-r--r-- | src/tools/moc/moc.cpp | 8 | ||||
-rw-r--r-- | tests/auto/tools/moc/tst_moc.cpp | 79 |
4 files changed, 77 insertions, 23 deletions
diff --git a/src/corelib/doc/src/objectmodel/properties.qdoc b/src/corelib/doc/src/objectmodel/properties.qdoc index 7276e8d86a..7ca3e25b00 100644 --- a/src/corelib/doc/src/objectmodel/properties.qdoc +++ b/src/corelib/doc/src/objectmodel/properties.qdoc @@ -53,7 +53,12 @@ argument, either of the property's type or a pointer or reference to that type. e.g., QWidget::enabled has the \c WRITE function 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 function is specified. This makes the given member variable diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index f030bc8918..0e8ba0bb72 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -1315,6 +1315,12 @@ void Generator::generateStaticMetacall() if (cdef->enumDeclarations.value(p.type, false)) { fprintf(out, " case %d: %s%s(QFlag(*reinterpret_cast<int*>(_v))); break;\n", 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()) { fprintf(out, " case %d: %s%s(*reinterpret_cast< %s*>(_v)); break;\n", propindex, prefix.constData(), p.write.constData(), p.type.constData()); diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index a14f0c1ccd..8a5abd3020 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -1301,7 +1301,7 @@ void Moc::parsePropertyAttributes(PropertyDef &propDef) error(1); } else if (test(DEFAULT)) { v = lexem(); - if (l != "READ") + if (l != "READ" && l != "WRITE") error(1); } else { next(IDENTIFIER); @@ -1387,6 +1387,12 @@ void Moc::parsePropertyAttributes(PropertyDef &propDef) propDef.read = ""; 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) diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp index 97575f5bb7..48249eec0c 100644 --- a/tests/auto/tools/moc/tst_moc.cpp +++ b/tests/auto/tools/moc/tst_moc.cpp @@ -744,7 +744,7 @@ private slots: void observerMetaCall(); void setQPRopertyBinding(); void privateQPropertyShim(); - void readThroughBindable(); + void readWriteThroughBindable(); signals: void sigWithUnsignedArg(unsigned foo); @@ -4339,7 +4339,7 @@ void tst_Moc::privateQPropertyShim() class BindableOnly : public QObject { Q_OBJECT - Q_PROPERTY(int score BINDABLE scoreBindable READ default) + Q_PROPERTY(int score BINDABLE scoreBindable READ default WRITE default) public: BindableOnly(QObject *parent = nullptr) : QObject(parent) @@ -4350,27 +4350,64 @@ private: QProperty<int> m_score; }; - -void tst_Moc::readThroughBindable() +class BindableAndNotifyable : public QObject { - BindableOnly 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"); + 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; +}; - QVERIFY(p.isValid()); - QCOMPARE(p.read(&o), 5); +void tst_Moc::readWriteThroughBindable() +{ + { + BindableOnly 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); + } + { + 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) |