Skip to content

Stabilizing 1.0 API #555

Open
Open
@LeonMatthesKDAB

Description

@LeonMatthesKDAB

After discussions following #531, we believe we've found an improved API that we want to target for Cxx-Qt 1.0.

Anyone using Cxx-Qt, feel free to leave feedback on this issue.

Solved API problems

Drawbacks

  • Around 6 lines of boilerplate, compared to the current API for the example below

1.0 API Overview

The point of this API is to be even closer to CXX than before, by only putting declarations within the bridge itself.
We've found this preferable for #[inherit], as well as for #[qsignal] for a while now, but haven't found a good API for QProperty.
We believe by simply using a #[qproperty()] attribute this can be solved nicely!

// the module name now defines the module that your qobjects show up in.
#[cxxqt::bridge]
mod qobject {
    // Like an `extern "C++"` block, but every type is assumed to be a QObject/QGadget
    extern "C++Qt" {
        // Just passed through to the `extern "C++"` block without additional generation
        type QAbstractItemModel = cxx_qt_lib::QAbstractItemModel;

        type QButton;

        // Passed through straight to CXX + generates on_clicked/connect_clicked methods
        #[qsignal]
        fn clicked(self: &QButton);
    }

    #[namespace="MyNamespace"]
    enum MyEnum {
        First,
        Second
    }

    // Any type in here is a QObject that comes from a Rust struct, like with `extern "Rust"`
    extern "RustQt" {
        // This mimicks C++ pretty closely, as everything is now split into its own attribute
        #[base="QAbstractItemModel"]
        #[qml_element]
        #[qenum(MyEnum)]
        #[qproperty(i32, propOne)] // needs to access field .prop - shortcut for #[qproperty(i32, prop, READ, WRITE, NOTIFY)]
        #[qproperty(i32, propTwo, READ=get_my_prop, WRITE)]
        #[qproperty(QString, propThree, READ=get_my_prop_three, WRITE=set_my_prop_three, NOTIFY)]
        type MyObject = super::MyObject;
        // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This solves the duality of types, you define a new type
        // that's within a `mod qobject` yourself, you can choose any name you like, etc.

        // invokables are now declared in the bridge, but defined outside.
        // That solves the issues we had with `Result<..>`
        #[qinvokable]
        fn my_invokable(self: Pin<&mut MyObject>, ..., *mut OtherObject) -> Result<()>;
    
       // Signals are now just functions!
       #[qsignal]
       #[inherit]
        fn data(self: Pin<&mut MyObject>, ...) -> ...;

        // Signal and function inheritance now works the same way
        #[cxx_name = "hasChildren"]
        #[inherit]
        fn has_children_super(self: &MyObject, parent: &QModelIndex) -> bool;
        //                          ^^^^^^^^
        // We no longer have to write qobject:: inside the bridge.
        
        // setters/getters must be exposed to C++
        fn get_my_prop(self: &MyObject) -> i32;
        fn get_my_prop_three(self: Pin<&mut MyObject>) -> QString;
        fn set_my_prop_three(self: Pin<&mut MyObject>, value: &QString);
    }

    // use traits to shape code generation, similar to CXX
    impl cxx_qt::Constructor<(i32)> for MyObject {
        todo!{}
    }

    impl cxx_qt::Threading for MyObject {}
    // to disable CXXQt locking!
    unsafe impl !cxx_qt::Locking for MyObject {}
}

struct MyObject {
    pub prop: i32,

    private_stuff: MySpecialType,
}

use cxx_qt_lib::prelude::*;

// Prefix here defined by module name, no more magic type!
impl qobject::MyObject {
    fn get_my_prop(&self) -> i32 {
        todo!{}
    }
    
    fn get_my_prop_three(&self) -> QString {
        todo!{}
    }

    fn set_my_prop_three(self: Pin<&mut Self>, value: i32) {
        todo!{}
        // this should call self.notify_prop_three() in the end to signal the change.
    }

    pub fn my_invokable(self: core::pin::Pin<&mut Self>) ->  anyhow::Result<()> {
        todo! { }
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    🤔 discussionFeedback welcome🥳🎉 1.0This issue is part of stabilization for 1.0 release

    Type

    No type

    Projects

    Status

    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions