Sty
Sty

Reputation: 800

Setting QObject* as QMLEngine root context property

In my current Qt-Quick-UI-based C++ application I want to make a QObject with a Q_PROPERTY(QAbstractListModel * ...) available to my UI:

class MyClass : public QObject
{
 Q_OBJECT
 Q_PROPERTY(MyListModel* model READ model CONSTANT)
 public:
  const MyListModel* model() const {return m_model.get();}
 private:
  std::unique_ptr<MyListModel> m_model;
}

Based on the documentation the way I understood this should work is that in e.g. my main.cpp I do the following:

int main(int argc, char *argv[])
{
 std::unique_ptr<QCoreApplication> app;  // allows both console and GUI mode
 BackendController controller;  // holds a MyClass object and according (pointer-typed) getter
 std::unique_ptr<QQmlApplicationEngine> qmlengine;  // needed for GUI mode
 if(GUI_MODE)
 {
  app.reset(new QApplication(argc, argv));
  qmlengine.reset(new QQmlApplicationEngine(app));
  qmlengine->rootContext()->setContextProperty("myobject", controller.getMyObject());
  engine.load(QUrl(QStringLiteral("qrc:/uimain.qml")));
  auto rcontext = qmlengine->rootContext();
 } // else ...
 return app->exec();
}

I would expect to be able to do something like this in my QML:

ListView {
  id: listview
  model: myobject.model
  delegate: Text {
    text: "An entry"
  }
}

However, even if I ensure that there are entries in the MyListModel, my ListView stays empty. Which is the reason why I put in the auto rcontext line, set a breakpoint there and ran a debugger (after trying a myriad of other approaches to check why nothing displays).

When comparing the pointers of the MyObject stored in the BackendController class (and the pointer that is returned by the getter as well) to the context property that was set in rcontext, there is a mismatch. The debugger states that the "myobject" property I set is a QVariant<bool> (evaluating to true), and when extracting the actual stored value (i.e. what should be a QObject*), it differs from the pointer I passed to the setContextProperty function.

I noticed the same behaviour even when passing pointers from the main() scope, like app.get(), but when passing QVariant "primitives" (like QStrings) they get registered without issues.

In case that this is relevant: after initializing the QQmlApplicationEngine and before loading the actual QML file, I also registered (uncreatable) QML types for all object types that QML may get into contact with (i.e. MyObject and MyListModel) and imported the according pseudo-module in QML as well - to no avail.

So I am now wondering what is going on here. Is this some flaw with how Qt 5.10 evaluates the setContextProperty function when given QObject*-type arguments? Or am I grossly overlooking something in my setup here?

Upvotes: 0

Views: 1222

Answers (1)

Sty
Sty

Reputation: 800

As it turns out, my mistake was making the MyClass getter function (controller.getMyObject()) a const function. Apparently, the setContextProperty() function expects either some QVariant or an in no way const QObject*.

Upvotes: 2

Related Questions