Fix QQmlContext::nameForObject()
nameForObject() should not search the linked contexts. Linked contexts are not reachable from the "head" context in QML. However, it should search context objects, just like contextProperty() does. [ChangeLog][QtQml][Important Behavior Changes] QQmlContext::nameForObject() now finds properties of context objects, but it does not search unrelated other ("linked") contexts anymore. Change-Id: Ic6e01fddf3e2d4b3a1bc7308e126f47fae7cd6d1 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
7fc9e67107
commit
9cd1e7902c
|
@ -367,19 +367,26 @@ static bool readObjectProperty(
|
|||
}
|
||||
|
||||
/*!
|
||||
Returns the value of the \a name property for this context
|
||||
as a QVariant.
|
||||
Returns the value of the \a name property for this context as a QVariant.
|
||||
If you know that the property you're looking for is a QObject assigned using
|
||||
a QML id in the current context, \l objectForName() is more convenient and
|
||||
faster. In contrast to \l objectForName() and \l nameForObject(), this method
|
||||
does traverse the context hierarchy and searches in parent contexts if the
|
||||
\a name is not found in the current one. It also considers any
|
||||
\l contextObject() you may have set.
|
||||
|
||||
\sa objectForName(), nameForObject(), contextObject()
|
||||
*/
|
||||
QVariant QQmlContext::contextProperty(const QString &name) const
|
||||
{
|
||||
Q_D(const QQmlContext);
|
||||
QVariant value;
|
||||
|
||||
QQmlRefPointer<QQmlContextData> data = d->m_data;
|
||||
const QQmlRefPointer<QQmlContextData> data = d->m_data;
|
||||
|
||||
const int idx = data->propertyIndex(name);
|
||||
if (idx == -1) {
|
||||
if (QObject *obj = data->contextObject()) {
|
||||
QVariant value;
|
||||
if (readObjectProperty(data, obj, name, &value))
|
||||
return value;
|
||||
}
|
||||
|
@ -388,20 +395,27 @@ QVariant QQmlContext::contextProperty(const QString &name) const
|
|||
return parentContext()->contextProperty(name);
|
||||
} else {
|
||||
if (idx >= d->numPropertyValues())
|
||||
value = QVariant::fromValue(data->idValue(idx - d->numPropertyValues()));
|
||||
return QVariant::fromValue(data->idValue(idx - d->numPropertyValues()));
|
||||
else
|
||||
value = d->propertyValue(idx);
|
||||
return d->propertyValue(idx);
|
||||
}
|
||||
|
||||
return value;
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the name of \a object in this context, or an empty string if \a object
|
||||
is not named in the context. Objects are named by setContextProperty(), or by ids in
|
||||
the case of QML created contexts.
|
||||
Returns the name of \a object in this context, or an empty string if \a object
|
||||
is not named in the context. Objects are named by \l setContextProperty(), or
|
||||
as properties of a context object, or by ids in the case of QML created
|
||||
contexts.
|
||||
|
||||
If the object has multiple names, the first is returned.
|
||||
If the object has multiple names, the first is returned.
|
||||
|
||||
In contrast to \l contextProperty(), this method does not traverse the
|
||||
context hierarchy. If the name is not found in the current context, an empty
|
||||
String is returned.
|
||||
|
||||
\sa contextProperty(), objectForName()
|
||||
*/
|
||||
QString QQmlContext::nameForObject(const QObject *object) const
|
||||
{
|
||||
|
|
|
@ -286,15 +286,29 @@ QString QQmlContextData::findObjectId(const QObject *obj) const
|
|||
return propertyName(ii);
|
||||
}
|
||||
|
||||
const QVariant objVariant = QVariant::fromValue(obj);
|
||||
if (m_publicContext) {
|
||||
QQmlContextPrivate *p = QQmlContextPrivate::get(m_publicContext);
|
||||
for (int ii = 0; ii < p->numPropertyValues(); ++ii)
|
||||
if (p->propertyValue(ii) == QVariant::fromValue(const_cast<QObject *>(obj)))
|
||||
if (p->propertyValue(ii) == objVariant)
|
||||
return propertyName(ii);
|
||||
}
|
||||
|
||||
if (m_linkedContext)
|
||||
return m_linkedContext->findObjectId(obj);
|
||||
if (m_contextObject) {
|
||||
// This is expensive, but nameForObject should really mirror contextProperty()
|
||||
for (const QMetaObject *metaObject = m_contextObject->metaObject();
|
||||
metaObject; metaObject = metaObject->superClass()) {
|
||||
for (int i = metaObject->propertyOffset(), end = metaObject->propertyCount();
|
||||
i != end; ++i) {
|
||||
const QMetaProperty prop = metaObject->property(i);
|
||||
if (prop.metaType().flags() & QMetaType::PointerToQObject
|
||||
&& prop.read(m_contextObject) == objVariant) {
|
||||
return QString::fromUtf8(prop.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
|
|
|
@ -595,6 +595,10 @@ void tst_qqmlcontext::objectsAndNames()
|
|||
QObject *containmentMask = qvariant_cast<QObject *>(ctxtObj->property("containmentMask"));
|
||||
QCOMPARE(containmentMask->objectName(), QStringLiteral("ddd"));
|
||||
|
||||
QCOMPARE(extraContext->nameForObject(aa), QStringLiteral("aa"));
|
||||
QCOMPARE(extraContext->nameForObject(bb), QStringLiteral("bb"));
|
||||
QCOMPARE(extraContext->nameForObject(cc), QStringLiteral("cc"));
|
||||
QCOMPARE(extraContext->nameForObject(containmentMask), QStringLiteral("containmentMask"));
|
||||
QCOMPARE(extraContext->objectForName(QStringLiteral("aa")), aa);
|
||||
QCOMPARE(extraContext->objectForName(QStringLiteral("bb")), bb);
|
||||
QCOMPARE(extraContext->objectForName(QStringLiteral("cc")), cc);
|
||||
|
@ -612,6 +616,8 @@ void tst_qqmlcontext::objectsAndNames()
|
|||
// objectForName and nameForObject deliberately don't
|
||||
QCOMPARE(extraContext->objectForName(QStringLiteral("root")), nullptr);
|
||||
QCOMPARE(extraContext->objectForName(QStringLiteral("nested")), nullptr);
|
||||
QCOMPARE(extraContext->nameForObject(o.data()), QString());
|
||||
QCOMPARE(extraContext->nameForObject(qvariant_cast<QObject*>(o->property("o"))), QString());
|
||||
}
|
||||
|
||||
class DeleteCommand : public QObject
|
||||
|
|
Loading…
Reference in New Issue