Open ratijas opened 4 years ago
Just chipping in on this discussion! While looking at other Qt bindings is useful, it's also useful to keep in mind that proc_macro's are getting quite a bit of stability lately, and maybe the other bindings don't use that to their full extent yet.
What would be cool is the ability to annotate otherwise normal Rust methods:
use qmetaobject::QObject;
#[derive(QObject)]
#[qmetaobject::signal(contentsChanged)]
struct Foo {
inner: Vec<u32>,
#[qmetaobject::property]
#[notify(contentsChanged)]
is_active: bool,
}
impl Foo {
#[qmetaobject::method(Foo::addInteger)]
fn add(&mut self, i: u32) { self.contents_changed() } // note that it is possible to auto-map the casing!
}
EDIT: I've also added some slot and property syntax idea's.
Note that I'm only talking from an ergonomic point of view, I don't know whether this is physically possible to implement.
this particular suntax is indeed not possible because the #[derive(QObject)] do not have any knowledge of the other impls. But there is certainly room for improvement. When i first developed this crate, only the derive macro was stable. Also i was not familiar with the rust convention, and laybe qt_property! would have been better as a #[property] and there could be better ways to register methods. Especially signals could be done as associated const or something like that instead of fields.
I suppose methods could get registered as an attribute under the derive too, then? Like
#[derive(QObject)]
#[qmetaobject::method(fooBar)]
struct Foo {}
Another comment that can be taken into account in this rework: handling the renaming/capitalization of methods, we're putting [#[allow(non_snake_case)
](https://gitlab.com/rubdos/whisperfish/-/issues/53) all over the place right now.
I've been out for a while. Came back after two new minor Rust versions has already shipped.
Looking at the release notes of 1.45.0, they even took an example from the gnome-class
crate. I don't know much about GObject
and Gnome concepts, but it looks somewhat reminiscent to something familiar. Maybe worth investigating deeper.
Also, note how GNOME project took initiative to create and support Rust wrappers on their own. (I'm looking at you, The Qt Company :eyes:)
https://blog.rust-lang.org/2020/07/16/Rust-1.45.0.html#stabilizing-function-like-procedural-macros-in-expressions-patterns-and-statements https://gitlab.gnome.org/federico/gnome-class
How about this? Just add two keywords:
// Just a normal struct
struct Foo {
inner: Vec<u32>,
the_real_is_active: bool,
}
#[qmetaobject(rename_all_signal = "camelCase")]
impl QObject for Foo { // QObject is the qt_base_class!
signal contents_changed;
#[notify(contents_changed)]
#[bind(the_real_is_active)] // Or #[read(func)] #[write(func)]
property is_active: bool;
fn add(&mut self, i: u32) { self.contents_changed() }
}
This is a tracking issue for signal / slot mechanism wrappers in Rust.
From Rust side,
RustSignal
and other satellite types should be done differently, in a more type-safe and convenient way.TODO:
Origin of this discussion: https://github.com/woboq/qmetaobject-rs/pull/97#discussion_r432318559