Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example how to create a global application interface object available as QmlEngine root context property #306

Open
antis81 opened this issue Nov 10, 2023 · 0 comments

Comments

@antis81
Copy link

antis81 commented Nov 10, 2023

I am pretty new to Rust and simply found the idea intriguing and adapt to an existing QML frontend (this one more precisely). The first steps went pretty smooth starting from the qmetaobject example and I was quickly able to get some visuals rendered on screen. 👍

However I got a little stuck with how to register a QObject as a root context property to interface with the application backend. A little (functional C++) snippet should illustrate this.

int main(int argc, char *argv[]) {
  QGuiApplication app(argc, argv);

  MyObject_1 obj_1; // some QObject instance
  MyObject_2 obj_2; // another QObject instance

  QQmlApplicationEngine engine;
  engine.rootContext()->setContextProperty(u"Obj1"_qs, &obj_1);
  engine.rootContext()->setContextProperty(u"Obj2"_qs, &obj_2);
  // engine.load(…qml page…);
  return app.exec();
}

In the C++ application those (global) objects are then accessible in QML.

Text { text: "Obj1 name:" + Obj1.name }

I could not find an example on how to formulate something like this with qmetaobject-rs. Something like qml_register_singleton_instance(…) would also be fine. The question is more like how to correctly bind a QObject value in rust?

use qmetaobject::prelude::*

#[derive(QObject, Default)]
struct MyObject1 {
    base: qt_base_class!(trait QObject),
    my_method: qt_method!(
        fn my_method(&self) -> QString {
            "Hello QML!".into()
        }
    ),
}

fn main() {
    let mut obj_1 = /* ??? what to put here ??? */;
}

ℹ️ UPDATE: The following example works. May be useful for an example on the website.

fn main() {
    let obj_1 = MyObject1::default();
    // FIXME: Does compile; produces runtime error in QML -> Unable to determine callable overload.
    // qml_register_singleton_instance(cstr!("Obj1"), 1, 0, cstr!("Obj1"), obj_1);

    let mut engine = QmlEngine::new();
    let app_interface = engine.new_qobject(obj_1);

    engine.set_property("Obj1".into(), obj_1.to_variant()); // TODO: Couldn't get this to work with set_object_property
    engine.add_import_path("qml".into());
    engine.load_file("qml/Main.qml".into());
    engine.exec();
}

However I am not completely happy with this and think a singleton instance is preferable for this (or maybe QJSValue property?). Is the FIXME mentioned actually an issue with QmlEngine's internal initalization sequence? (no other code changes involved). 🐞 ❓

@antis81 antis81 changed the title How to instantiate a QObject and make it globally available to QmlEngine's root context? Example how to create a global application interface object available as QmlEngine root context property Nov 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant