qmltc: test alias on properties with attributes
Add tests to qmltc to see if it behaves well for aliases to different kinds of properties, and compares if the engine shares the same behavior. Same for the attributes in the QMetaProperties. Changes: * add some more MOC information to aliases ** always add NOTIFY to aliases (like the engine does) ** always set DESIGNABLE to false for aliases (like the engine does) ** always set CONSTANT to false for aliases (like the engine does) ** always set STORED to false for aliases (like the engine does) Test if: * default aliases works when compiled via qmltc * attributes of aliases are set correctly in QMetaProperty and compare it to the attributes of the QMetaProperty obtained from the engine. * aliases can read/written/reset/notified Fixes: QTBUG-105708 Change-Id: I66b9c43c8c8de3dbd2b33d5ce15cd42ffb377ce7 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
This commit is contained in:
parent
b6463590fa
commit
8120ec1d3d
|
@ -17,6 +17,8 @@ set(cpp_sources
|
|||
cpptypes/extensiontypes.h cpptypes/extensiontypes.cpp
|
||||
|
||||
cpptypes/typewithspecialproperties.h
|
||||
|
||||
cpptypes/typewithmanyproperties.h
|
||||
)
|
||||
|
||||
set(qml_sources
|
||||
|
@ -50,6 +52,7 @@ set(qml_sources
|
|||
javaScriptFunctions.qml
|
||||
changingBindings.qml
|
||||
propertyAlias.qml
|
||||
propertyAliasAttributes.qml
|
||||
propertyAlias_external.qml
|
||||
propertyChangeHandler.qml
|
||||
NestedHelloWorld.qml
|
||||
|
@ -58,7 +61,7 @@ set(qml_sources
|
|||
listPropertySameName.qml
|
||||
defaultProperty.qml
|
||||
defaultPropertyCorrectSelection.qml
|
||||
# defaultAlias.qml
|
||||
defaultAlias.qml
|
||||
propertyReturningFunction.qml
|
||||
AttachedProperty.qml
|
||||
attachedPropertyDerived.qml
|
||||
|
@ -99,6 +102,7 @@ set(qml_sources
|
|||
|
||||
# support types:
|
||||
DefaultPropertySingleChild.qml
|
||||
DefaultPropertyAliasChild.qml
|
||||
DefaultPropertyManyChildren.qml
|
||||
LocallyImported.qml
|
||||
LocalWithOnCompleted.qml
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
import QtQml 2.0
|
||||
|
||||
QtObject {
|
||||
id: self
|
||||
|
||||
property QtObject someObject
|
||||
default property alias child: self.someObject
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
// Copyright (C) 2021 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#ifndef PROPERTYALIASATTRIBUTES_H
|
||||
#define PROPERTYALIASATTRIBUTES_H
|
||||
|
||||
#include <QtCore/qobject.h>
|
||||
#include <QtCore/QBindable>
|
||||
#include <QtQml/qqmlregistration.h>
|
||||
|
||||
using namespace Qt::Literals;
|
||||
|
||||
class TypeWithManyProperties : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
|
||||
const QString m_readOnly = u"Hello World!"_s;
|
||||
QString m_readAndWrite;
|
||||
QString m_resettable;
|
||||
QString m_unresettable;
|
||||
QString m_hasAllAttributes;
|
||||
QString m_hasAllAttributes2;
|
||||
|
||||
public:
|
||||
TypeWithManyProperties()
|
||||
{
|
||||
hasAllAttributesBindable().setBinding(
|
||||
[&] { return u"From the bindable: "_s + readOnly(); });
|
||||
}
|
||||
|
||||
Q_PROPERTY(QString readOnly READ readOnly);
|
||||
Q_PROPERTY(QString readAndWrite READ readAndWrite WRITE setReadAndWrite);
|
||||
Q_PROPERTY(QString readAndWriteMember MEMBER m_readAndWrite);
|
||||
Q_PROPERTY(QString resettable READ resettable WRITE setReadAndWrite RESET resetResettable);
|
||||
Q_PROPERTY(QString unresettable READ unresettable WRITE setUnresettable);
|
||||
Q_PROPERTY(QString notifiable READ readAndWrite WRITE setReadAndWriteAndNotify NOTIFY
|
||||
notifiableChanged);
|
||||
Q_PROPERTY(QString notifiableMember MEMBER m_readAndWrite NOTIFY notifiableChanged);
|
||||
Q_PROPERTY(QString latestReadAndWrite MEMBER m_readAndWrite REVISION(1, 0));
|
||||
Q_PROPERTY(QString notExisting MEMBER m_readAndWrite REVISION(6, 0));
|
||||
|
||||
Q_PROPERTY(QString hasAllAttributes READ hasAllAttributes WRITE setHasAllAttributes RESET
|
||||
resetHasAllAttributes NOTIFY hasAllAttributesChanged REVISION(1, 0)
|
||||
BINDABLE hasAllAttributesBindable
|
||||
DESIGNABLE false SCRIPTABLE true STORED false USER true FINAL
|
||||
REQUIRED);
|
||||
|
||||
Q_OBJECT_BINDABLE_PROPERTY(TypeWithManyProperties, QString, hasAllAttributesProperty);
|
||||
|
||||
QBindable<QString> hasAllAttributesBindable()
|
||||
{
|
||||
return QBindable<QString>(&hasAllAttributesProperty);
|
||||
}
|
||||
|
||||
Q_PROPERTY(QString hasAllAttributes2 READ hasAllAttributes2
|
||||
DESIGNABLE true SCRIPTABLE true STORED true USER false CONSTANT);
|
||||
|
||||
QString readOnly() { return m_readOnly; }
|
||||
|
||||
QString readAndWrite() { return m_readAndWrite; }
|
||||
|
||||
void setReadAndWrite(const QString &s) { m_readAndWrite = s; }
|
||||
|
||||
void setReadAndWriteAndNotify(const QString &s)
|
||||
{
|
||||
if (s != readAndWrite()) {
|
||||
setReadAndWrite(s);
|
||||
emit notifiableChanged(s);
|
||||
}
|
||||
}
|
||||
|
||||
void resetResettable() { m_resettable = u"Reset!"_s; }
|
||||
|
||||
QString resettable() { return m_resettable; }
|
||||
QString unresettable() { return m_unresettable; }
|
||||
void setResettable(const QString &s) { m_resettable = s; }
|
||||
void setUnresettable(const QString &s) { m_unresettable = s; }
|
||||
|
||||
QString hasAllAttributes2() { return u"Some Constant string"_s; }
|
||||
QString hasAllAttributes() { return m_hasAllAttributes; }
|
||||
void setHasAllAttributes(const QString &s) { m_hasAllAttributes = s; }
|
||||
void resetHasAllAttributes() { m_hasAllAttributes = "This value has been reset."; }
|
||||
|
||||
signals:
|
||||
void notifiableChanged(const QString &newValue);
|
||||
void hasAllAttributesChanged(const QString &newValue);
|
||||
};
|
||||
|
||||
#endif // PROPERTYALIASATTRIBUTES_H
|
|
@ -1,9 +1,8 @@
|
|||
import QtQml 2.0
|
||||
import QtQml
|
||||
|
||||
QtObject {
|
||||
DefaultPropertyAliasChild {
|
||||
id: self
|
||||
property string hello: "Hello from parent"
|
||||
property QtObject origin
|
||||
default property alias child: origin
|
||||
|
||||
QtObject {
|
||||
property string hello: "Hello from parent.child (alias)"
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright (C) 2021 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
import QtQml
|
||||
import QmltcTests
|
||||
|
||||
TypeWithManyProperties {
|
||||
id: self
|
||||
|
||||
property alias hasAllAttributesAlias: self.hasAllAttributes
|
||||
//hasAllAttributes: "The string."
|
||||
hasAllAttributesAlias: "The string." // when this is missing then qmltc does not emit any error...
|
||||
property alias hasAllAttributes2Alias: self.hasAllAttributes2
|
||||
|
||||
property alias readOnlyAlias: self.readOnly
|
||||
property alias readAndWriteMemberAlias: self.readAndWriteMember
|
||||
property alias resettableAlias: self.resettable
|
||||
property alias unresettableAlias: self.unresettable
|
||||
property alias notifiableAlias: self.notifiable
|
||||
property alias notifiableMemberAlias: self.notifiableMember
|
||||
property alias latestReadAndWriteAlias: self.latestReadAndWrite
|
||||
|
||||
// aliases cannot be readonly, they inherit it from the property pointed to
|
||||
// readonly default property alias readOnlyAlias2: self.readAndWriteMember // not valid
|
||||
|
||||
default property alias defaultAlias: self.readAndWriteMember
|
||||
|
||||
// cannot be compiled by qmlcachegen it seems: required property cannot have initializer
|
||||
// required property alias requiredAlias: self.hasAllAttributes
|
||||
|
||||
function assignUndefinedToResettableAlias() {
|
||||
resettableAlias = undefined
|
||||
}
|
||||
function assignUndefinedToUnresettableAlias() {
|
||||
unresettableAlias = undefined
|
||||
}
|
||||
}
|
|
@ -33,6 +33,7 @@
|
|||
#include "changingbindings.h"
|
||||
#include "propertyalias.h"
|
||||
#include "propertyalias_external.h"
|
||||
#include "propertyaliasattributes.h"
|
||||
#include "complexaliases.h"
|
||||
#include "propertychangehandler.h"
|
||||
#include "nestedhelloworld.h"
|
||||
|
@ -72,6 +73,7 @@
|
|||
#include "valuetypelistproperty.h"
|
||||
#include "translations.h"
|
||||
#include "translationsbyid.h"
|
||||
#include "defaultalias.h"
|
||||
|
||||
#include "testprivateproperty.h"
|
||||
|
||||
|
@ -894,8 +896,19 @@ void tst_qmltc::specialProperties()
|
|||
// alias attributes:
|
||||
const QMetaObject *mo = created.metaObject();
|
||||
QMetaProperty xxAlias = mo->property(mo->indexOfProperty("xxAlias"));
|
||||
|
||||
QQmlComponent c(&e);
|
||||
c.loadUrl(QUrl("qrc:/qt/qml/QmltcTests/specialProperties.qml"));
|
||||
QScopedPointer<QObject> _fromEngine(c.create());
|
||||
QVERIFY2(_fromEngine, qPrintable(c.errorString()));
|
||||
QObject &fromEngine = *_fromEngine;
|
||||
const QMetaObject *fromEngineMetaObject = fromEngine.metaObject();
|
||||
|
||||
QMetaProperty xxAliasFromEngine =
|
||||
fromEngineMetaObject->property(mo->indexOfProperty("xxAlias"));
|
||||
QVERIFY(xxAlias.isValid());
|
||||
QVERIFY(xxAlias.isConstant());
|
||||
QVERIFY(xxAliasFromEngine.isValid());
|
||||
QCOMPARE(xxAlias.isConstant(), xxAliasFromEngine.isConstant());
|
||||
QCOMPARE(created.xyAlias(), u"reset");
|
||||
}
|
||||
|
||||
|
@ -1091,6 +1104,192 @@ void tst_qmltc::propertyAlias_external()
|
|||
QCOMPARE(heightAliasChangedSpy.count(), 1);
|
||||
}
|
||||
|
||||
void tst_qmltc::propertyAliasAttribute()
|
||||
{
|
||||
QQmlEngine e;
|
||||
PREPEND_NAMESPACE(propertyAliasAttributes) fromQmltc(&e);
|
||||
|
||||
QQmlComponent c(&e);
|
||||
c.loadUrl(QUrl("qrc:/qt/qml/QmltcTests/propertyAliasAttributes.qml"));
|
||||
QScopedPointer<QObject> _fromEngine(c.create());
|
||||
QVERIFY2(_fromEngine, qPrintable(c.errorString()));
|
||||
QObject &fromEngine = *_fromEngine;
|
||||
const QMetaObject *fromEngineMetaObject = fromEngine.metaObject();
|
||||
|
||||
const QString stringA = u"The quick brown fox"_s;
|
||||
const QString stringB = u"jumps over the lazy dog."_s;
|
||||
|
||||
QCOMPARE(fromQmltc.readOnlyAlias(), u"Hello World!"_s);
|
||||
QCOMPARE(fromEngine.property("readOnlyAlias"), u"Hello World!"_s);
|
||||
|
||||
QVERIFY(!fromQmltc.setProperty("readOnlyAlias", u"Some string"_s));
|
||||
QVERIFY(!fromEngine.setProperty("readOnlyAlias", u"Some string"_s));
|
||||
|
||||
// reading and writing from alias is already covered in the alias test
|
||||
// check if it works on properties with the MEMBERS attribute
|
||||
fromQmltc.setReadAndWriteMemberAlias(stringA);
|
||||
fromEngine.setProperty("readAndWriteMemberAlias", stringA);
|
||||
|
||||
QCOMPARE(fromQmltc.property("readAndWriteMember"), stringA);
|
||||
QCOMPARE(fromEngine.property("readAndWriteMember"), stringA);
|
||||
|
||||
fromQmltc.setReadAndWriteMemberAlias(stringB);
|
||||
fromEngine.setProperty("readAndWriteMemberAlias", stringB);
|
||||
|
||||
QCOMPARE(fromQmltc.readAndWriteMemberAlias(), stringB);
|
||||
QCOMPARE(fromQmltc.property("readAndWriteMember"), stringB);
|
||||
|
||||
QCOMPARE(fromEngine.property("readAndWriteMemberAlias"), stringB);
|
||||
QCOMPARE(fromEngine.property("readAndWriteMember"), stringB);
|
||||
|
||||
// check if alias can be reset through property
|
||||
fromQmltc.setResettableAlias(stringA);
|
||||
fromEngine.setProperty("resettableAlias", stringB);
|
||||
fromQmltc.resetResettable();
|
||||
const int resettableIdx = fromEngineMetaObject->indexOfProperty("resettable");
|
||||
QVERIFY(fromEngineMetaObject->property(resettableIdx).reset(&fromEngine));
|
||||
QCOMPARE(fromQmltc.resettable(), u"Reset!"_s);
|
||||
QCOMPARE(fromQmltc.resettableAlias(), u"Reset!"_s);
|
||||
QCOMPARE(fromEngine.property("resettable"), u"Reset!"_s);
|
||||
QCOMPARE(fromEngine.property("resettableAlias"), u"Reset!"_s);
|
||||
|
||||
// check if property can be reset through alias
|
||||
fromQmltc.setResettableAlias(stringA);
|
||||
fromEngine.setProperty("resettableAlias", stringA);
|
||||
fromQmltc.resetResettableAlias();
|
||||
QMetaMethod resetResettableAlias = fromEngineMetaObject->method(
|
||||
fromEngineMetaObject->indexOfMethod("resetResettableAlias"));
|
||||
resetResettableAlias.invoke(&fromEngine);
|
||||
QCOMPARE(fromQmltc.resettable(), u"Reset!"_s);
|
||||
QCOMPARE(fromQmltc.resettableAlias(), u"Reset!"_s);
|
||||
QCOMPARE(fromEngine.property("resettable"), u"Reset!"_s);
|
||||
QCOMPARE(fromEngine.property("resettableAlias"), u"Reset!"_s);
|
||||
|
||||
// check if property can be reset by assigning undefined to alias
|
||||
fromQmltc.setResettableAlias(stringA);
|
||||
fromEngine.setProperty("resettableAlias", stringA);
|
||||
fromQmltc.assignUndefinedToResettableAlias();
|
||||
QMetaMethod assignUndefinedToResettableAlias = fromEngineMetaObject->method(
|
||||
fromEngineMetaObject->indexOfMethod("assignUndefinedToResettableAlias"));
|
||||
assignUndefinedToResettableAlias.invoke(&fromEngine);
|
||||
QCOMPARE(fromQmltc.resettableAlias(), u"Reset!"_s);
|
||||
QCOMPARE(fromQmltc.resettable(), u"Reset!"_s);
|
||||
QCOMPARE(fromEngine.property("resettableAlias"), u"Reset!"_s);
|
||||
QCOMPARE(fromEngine.property("resettable"), u"Reset!"_s);
|
||||
|
||||
// check if property can be reset by assigning undefined to alias of
|
||||
// non-resettable prop which should not happen: instead, nothing should happen
|
||||
fromQmltc.setUnresettableAlias(stringA);
|
||||
fromEngine.setProperty("unresettableAlias", stringA);
|
||||
fromQmltc.assignUndefinedToUnresettableAlias();
|
||||
QMetaMethod assignUndefinedToUnresettableAlias = fromEngineMetaObject->method(
|
||||
fromEngineMetaObject->indexOfMethod("assignUndefinedToUnresettableAlias"));
|
||||
assignUndefinedToUnresettableAlias.invoke(&fromEngine);
|
||||
QCOMPARE(fromQmltc.unresettableAlias(), stringA);
|
||||
QCOMPARE(fromQmltc.property("unresettable"), stringA);
|
||||
QCOMPARE(fromEngine.property("unresettableAlias"), stringA);
|
||||
QCOMPARE(fromEngine.property("unresettable"), stringA);
|
||||
|
||||
// check if notify arrives!
|
||||
fromQmltc.setReadAndWrite(stringB);
|
||||
fromEngine.setProperty("readAndWrite", stringB);
|
||||
qsizetype calls = 0;
|
||||
QSignalSpy spyQmltc(&fromQmltc, SIGNAL(notifiableChanged(QString)));
|
||||
QSignalSpy spyEngine(&fromEngine, SIGNAL(notifiableChanged(QString)));
|
||||
// write through alias
|
||||
fromQmltc.setNotifiableAlias(stringA);
|
||||
QVERIFY(fromEngine.setProperty("notifiableAlias", stringA));
|
||||
QCOMPARE(spyQmltc.count(), ++calls);
|
||||
QCOMPARE(spyEngine.count(), calls);
|
||||
// write through property
|
||||
fromQmltc.setReadAndWriteAndNotify(stringB);
|
||||
QVERIFY(fromEngine.setProperty("notifiable", stringB));
|
||||
QCOMPARE(spyQmltc.count(), ++calls);
|
||||
QCOMPARE(spyEngine.count(), calls);
|
||||
|
||||
fromQmltc.setNotifiableMemberAlias(stringA);
|
||||
QVERIFY(fromEngine.setProperty("notifiableMemberAlias", stringA));
|
||||
QCOMPARE(spyQmltc.count(), ++calls);
|
||||
QCOMPARE(spyEngine.count(), calls);
|
||||
fromQmltc.setProperty("notifiableMember", stringB);
|
||||
QVERIFY(fromEngine.setProperty("notifiableMember", stringB));
|
||||
QCOMPARE(spyQmltc.count(), ++calls);
|
||||
QCOMPARE(spyEngine.count(), calls);
|
||||
|
||||
// check that the alias to a revisioned property works
|
||||
fromQmltc.setLatestReadAndWriteAlias(stringA);
|
||||
QVERIFY(fromEngine.setProperty("latestReadAndWriteAlias", stringA));
|
||||
QCOMPARE(fromQmltc.latestReadAndWriteAlias(), stringA);
|
||||
QCOMPARE(fromQmltc.property("latestReadAndWrite"), stringA);
|
||||
QCOMPARE(fromEngine.property("latestReadAndWriteAlias"), stringA);
|
||||
QCOMPARE(fromEngine.property("latestReadAndWrite"), stringA);
|
||||
|
||||
QVERIFY(fromQmltc.setProperty("latestReadAndWrite", stringB));
|
||||
QVERIFY(fromEngine.setProperty("latestReadAndWrite", stringB));
|
||||
QCOMPARE(fromQmltc.latestReadAndWriteAlias(), stringB);
|
||||
QCOMPARE(fromQmltc.property("latestReadAndWrite"), stringB);
|
||||
QCOMPARE(fromEngine.property("latestReadAndWriteAlias"), stringB);
|
||||
QCOMPARE(fromEngine.property("latestReadAndWrite"), stringB);
|
||||
|
||||
// check if metaobject of alias is correct
|
||||
const QVector<const QMetaObject *> metaObjects = {
|
||||
fromQmltc.metaObject(),
|
||||
fromEngine.metaObject(),
|
||||
};
|
||||
|
||||
QVERIFY(metaObjects[0]);
|
||||
QVERIFY(metaObjects[1]);
|
||||
|
||||
QVector<QHash<QString, QMetaProperty>> metaProperties(2);
|
||||
for (int j = 0; j < metaObjects.size(); j++) {
|
||||
const QMetaObject *metaObject = metaObjects[j];
|
||||
for (int i = metaObject->propertyOffset(); i < metaObject->propertyCount(); ++i) {
|
||||
metaProperties[j][QString::fromLatin1(metaObject->property(i).name())] =
|
||||
metaObject->property(i);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
QVERIFY(metaProperties[0].contains("hasAllAttributesAlias"));
|
||||
QVERIFY(metaProperties[1].contains("hasAllAttributesAlias"));
|
||||
QMetaProperty mpQmltc = metaProperties[0].value("hasAllAttributesAlias");
|
||||
QMetaProperty mpEngine = metaProperties[1].value("hasAllAttributesAlias");
|
||||
QCOMPARE(mpQmltc.isReadable(), mpEngine.isReadable());
|
||||
QCOMPARE(mpQmltc.isWritable(), mpEngine.isWritable());
|
||||
QCOMPARE(mpQmltc.isResettable(), mpEngine.isResettable());
|
||||
QCOMPARE(mpQmltc.hasNotifySignal(), mpEngine.hasNotifySignal());
|
||||
QCOMPARE(mpQmltc.revision(), mpEngine.revision());
|
||||
QCOMPARE(mpQmltc.isDesignable(), mpEngine.isDesignable());
|
||||
QCOMPARE(mpQmltc.isScriptable(), mpEngine.isScriptable());
|
||||
QCOMPARE(mpQmltc.isStored(), mpEngine.isStored());
|
||||
QCOMPARE(mpQmltc.isUser(), mpEngine.isUser());
|
||||
QCOMPARE(mpQmltc.isBindable(), mpEngine.isBindable());
|
||||
QCOMPARE(mpQmltc.isConstant(), mpEngine.isConstant());
|
||||
QCOMPARE(mpQmltc.isFinal(), mpEngine.isFinal());
|
||||
QCOMPARE(mpQmltc.isRequired(), mpEngine.isRequired());
|
||||
}
|
||||
|
||||
{
|
||||
QVERIFY(metaProperties[0].contains("hasAllAttributes2Alias"));
|
||||
QVERIFY(metaProperties[1].contains("hasAllAttributes2Alias"));
|
||||
QMetaProperty mpQmltc = metaProperties[0].value("hasAllAttributes2Alias");
|
||||
QMetaProperty mpEngine = metaProperties[1].value("hasAllAttributes2Alias");
|
||||
QCOMPARE(mpQmltc.isReadable(), mpEngine.isReadable());
|
||||
QCOMPARE(mpQmltc.isWritable(), mpEngine.isWritable());
|
||||
QCOMPARE(mpQmltc.isResettable(), mpEngine.isResettable());
|
||||
QCOMPARE(mpQmltc.hasNotifySignal(), mpEngine.hasNotifySignal());
|
||||
QCOMPARE(mpQmltc.revision(), mpEngine.revision());
|
||||
QCOMPARE(mpQmltc.isDesignable(), mpEngine.isDesignable());
|
||||
QCOMPARE(mpQmltc.isScriptable(), mpEngine.isScriptable());
|
||||
QCOMPARE(mpQmltc.isStored(), mpEngine.isStored());
|
||||
QCOMPARE(mpQmltc.isUser(), mpEngine.isUser());
|
||||
QCOMPARE(mpQmltc.isBindable(), mpEngine.isBindable());
|
||||
QCOMPARE(mpQmltc.isConstant(), mpEngine.isConstant());
|
||||
QCOMPARE(mpQmltc.isFinal(), mpEngine.isFinal());
|
||||
QCOMPARE(mpQmltc.isRequired(), mpEngine.isRequired());
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: we need to support RESET in aliases as well? (does it make sense?)
|
||||
void tst_qmltc::complexAliases()
|
||||
{
|
||||
|
@ -1455,7 +1654,19 @@ void tst_qmltc::defaultPropertyCorrectSelection()
|
|||
|
||||
void tst_qmltc::defaultAlias()
|
||||
{
|
||||
QSKIP("Not implemented - not supported");
|
||||
QQmlEngine e;
|
||||
PREPEND_NAMESPACE(defaultAlias) created(&e);
|
||||
|
||||
QQmlComponent c(&e);
|
||||
c.loadUrl(QUrl("qrc:/qt/qml/QmltcTests/defaultAlias.qml"));
|
||||
QScopedPointer<QObject> fromEngine(c.create());
|
||||
QVERIFY2(fromEngine, qPrintable(c.errorString()));
|
||||
|
||||
auto *child = static_cast<QmltcTest::defaultAlias_QtObject *>(created.child());
|
||||
QVERIFY(fromEngine->property("child").canConvert<QObject *>());
|
||||
QObject *childFromEngine = fromEngine->property("child").value<QObject *>();
|
||||
QVERIFY(childFromEngine);
|
||||
QCOMPARE(child->hello(), childFromEngine->property("hello"));
|
||||
}
|
||||
|
||||
void tst_qmltc::attachedProperty()
|
||||
|
|
|
@ -45,6 +45,7 @@ private slots:
|
|||
void changingBindings();
|
||||
void propertyAlias();
|
||||
void propertyAlias_external();
|
||||
void propertyAliasAttribute();
|
||||
void complexAliases();
|
||||
void propertyChangeHandler();
|
||||
void nestedHelloWorld();
|
||||
|
|
|
@ -733,10 +733,20 @@ void QmltcCompiler::compileAlias(QmltcType ¤t, const QQmlJSMetaProperty &a
|
|||
current.functions.emplaceBack(bindable);
|
||||
mocLines << u"BINDABLE"_s << bindable.name;
|
||||
}
|
||||
|
||||
// 3. add notify - which is pretty special
|
||||
if (QString notifyName = result.property.notify(); !notifyName.isEmpty()) {
|
||||
// step 1: generate the moc instructions
|
||||
// mimic the engines behavior: do it even if the notify will never be emitted
|
||||
if (const QString aliasNotifyName = alias.notify(); !aliasNotifyName.isEmpty()) {
|
||||
|
||||
Q_ASSERT(result.kind == QQmlJSUtils::AliasTarget_Property); // property is invalid otherwise
|
||||
|
||||
mocLines << u"NOTIFY"_s << aliasNotifyName;
|
||||
}
|
||||
|
||||
// step 2: connect the notifier to the aliased property notifier, if this latter exists
|
||||
// otherwise, mimic the engines behavior and generate a useless notify
|
||||
if (const QString notifyName = result.property.notify(); !notifyName.isEmpty()) {
|
||||
auto notifyFrames = frames;
|
||||
notifyFrames.pop(); // we don't need the last frame at all in this case
|
||||
|
||||
|
@ -762,6 +772,7 @@ void QmltcCompiler::compileAlias(QmltcType ¤t, const QQmlJSMetaProperty &a
|
|||
current.endInit.body += notifyEpilogue;
|
||||
current.endInit.body << u"}"_s;
|
||||
}
|
||||
|
||||
if (QString resetName = result.property.reset(); !resetName.isEmpty()) {
|
||||
Q_ASSERT(result.kind == QQmlJSUtils::AliasTarget_Property); // property is invalid otherwise
|
||||
QmltcMethod reset {};
|
||||
|
@ -775,8 +786,12 @@ void QmltcCompiler::compileAlias(QmltcType ¤t, const QQmlJSMetaProperty &a
|
|||
mocLines << u"RESET"_s << reset.name;
|
||||
}
|
||||
|
||||
if (result.property.isConstant())
|
||||
mocLines << u"CONSTANT"_s;
|
||||
// mimic the engines behavior: aliases are never constants
|
||||
// mocLines << u"CONSTANT"_s;
|
||||
// mimic the engines behavior: aliases are never stored
|
||||
mocLines << u"STORED"_s << u"false"_s;
|
||||
// mimic the engines behavior: aliases are never designable
|
||||
mocLines << u"DESIGNABLE"_s << u"false"_s;
|
||||
|
||||
// 4. add moc entry
|
||||
// Q_PROPERTY(QString text READ text WRITE setText BINDABLE bindableText NOTIFY textChanged)
|
||||
|
|
|
@ -562,8 +562,12 @@ static void setAliasData(QQmlJSMetaProperty *alias, const QQmlJSUtils::ResolvedA
|
|||
return;
|
||||
if (origin.property.isWritable() && alias->write().isEmpty())
|
||||
alias->setWrite(compiledData.write);
|
||||
if (!origin.property.notify().isEmpty() && alias->notify().isEmpty())
|
||||
|
||||
// the engine always compiles a notify for properties/aliases defined in qml code
|
||||
// Yes, this generated notify will never be emitted.
|
||||
if (alias->notify().isEmpty())
|
||||
alias->setNotify(compiledData.notify);
|
||||
|
||||
if (!origin.property.bindable().isEmpty() && alias->bindable().isEmpty())
|
||||
alias->setBindable(compiledData.bindable);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue