QML: How to access context property if its name is shadowed by a component-local property?
-
My code:
main.cpp:
#include <QGuiApplication> #include <QQmlApplicationEngine> #include <QQmlContext> int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); engine.rootContext()->setContextProperty("text", "hey"); return app.exec(); }
main.qml:
import QtQuick 2.5 import QtQuick.Window 2.2 Window { id: window visible: true width: 640 height: 480 Text { text: text } }
Of course, the
text: text
line doesn't do what I want it to, because of name shadowing.I worked around that by setting a property on the root object, rather than on the root context, and using
text: window.text
.Is there any real fix though?
-
@Stefan-Monov76
short answer: no
Obviously such case is semantically ambigious.You can use an alias property, which is basically the same as your solution,
-
@raven-worx: Yes, it's ambiguous because I don't know (or there isn't) a syntax for disambiguating. For example in C++ a roughly equivalent statement, involving a local
text
and a globaltext
, would betext = ::text
which is unambiguous. Or, if you have a member var and a local, you could usetext = this->text
. So this is possible in C++, I was just asking if it's possible in QML as well :)Thanks for the answer.
-
@Stefan-Monov76
This is because C++ is object-orientated and type-safe. So namespaces are supported there.
Whereas JavaScript is not, thus it's not supported/needed there. -
@raven-worx: Yes, it's ambiguous because I don't know (or there isn't) a syntax for disambiguating. For example in C++ a roughly equivalent statement, involving a local
text
and a globaltext
, would betext = ::text
which is unambiguous.Hehe, I was discussing that with others last week, a way to differentiate context properties from regular object properties. Could be used in your case to disambiguate the root context property, or to access model properties from outside a delegate, for example :
listView.currentItem::age
without having to expose it as a property.
This syntax is not achievable for the moment, but you could do something like thislistView.currentItem.Context.property("age")
, you won't get notified of any change though. You could also do it for the root context with a singleton exposing it with the same caveat about the changes.