Open
Description
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
- Add
extern "Qt"
- allow signals on existing Qt classes #527 -extern "Qt"
block &extern "RustQt"
block - API improvements for solving duality of types and related changes #531 - you explicitly define the QObject type now!
- Generated documentation doesn't show up on qobject::T #529 - Documentation should now show up correctly
- Consider supporting multiple macro mod blocks #294 - Multiple bridges should no longer collide, as we no longer require the qobject:: prefix
- Support Result<T, E> as a return type from Rust -> C++ #404 - Results can now be represented the same way as in CXX
- Consider which attributes should be on a Q_PROPERTY #42 - Clearly define the available Q_PROPERTY attributes
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
Type
Projects
Status
Todo