diff --git a/CHANGELOG.md b/CHANGELOG.md index ce70b7620..4e4c3ba03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `#[qinvokable]` is now defined as a signature in `extern "RustQt"` - `rust_mut` is now safe to call - `#[qproperty]` is now defined as an attribute on the qobject rather than the field +- QObject struct is now split between the bridge and implementation outside via a type alias ### Fixed diff --git a/crates/cxx-qt-gen/src/generator/cpp/mod.rs b/crates/cxx-qt-gen/src/generator/cpp/mod.rs index aff24e2be..00468b8b4 100644 --- a/crates/cxx-qt-gen/src/generator/cpp/mod.rs +++ b/crates/cxx-qt-gen/src/generator/cpp/mod.rs @@ -54,8 +54,10 @@ mod tests { let module: ItemMod = parse_quote! { #[cxx_qt::bridge] mod ffi { - #[cxx_qt::qobject] - pub struct MyObject; + extern "RustQt" { + #[cxx_qt::qobject] + type MyObject = super::MyObjectRust; + } } }; let parser = Parser::from(module).unwrap(); @@ -71,8 +73,10 @@ mod tests { let module: ItemMod = parse_quote! { #[cxx_qt::bridge(cxx_file_stem = "my_object")] mod ffi { - #[cxx_qt::qobject] - pub struct MyObject; + extern "RustQt" { + #[cxx_qt::qobject] + type MyObject = super::MyObjectRust; + } } }; let parser = Parser::from(module).unwrap(); @@ -88,8 +92,10 @@ mod tests { let module: ItemMod = parse_quote! { #[cxx_qt::bridge(namespace = "cxx_qt")] mod ffi { - #[cxx_qt::qobject] - pub struct MyObject; + extern "RustQt" { + #[cxx_qt::qobject] + type MyObject = super::MyObjectRust; + } } }; let parser = Parser::from(module).unwrap(); diff --git a/crates/cxx-qt-gen/src/generator/cpp/qobject.rs b/crates/cxx-qt-gen/src/generator/cpp/qobject.rs index 024a2905b..cc9dbf4c0 100644 --- a/crates/cxx-qt-gen/src/generator/cpp/qobject.rs +++ b/crates/cxx-qt-gen/src/generator/cpp/qobject.rs @@ -165,8 +165,10 @@ mod tests { let module: ItemMod = parse_quote! { #[cxx_qt::bridge] mod ffi { - #[cxx_qt::qobject] - pub struct MyObject; + extern "RustQt" { + #[cxx_qt::qobject] + type MyObject = super::MyObjectRust; + } } }; let parser = Parser::from(module).unwrap(); @@ -188,8 +190,10 @@ mod tests { let module: ItemMod = parse_quote! { #[cxx_qt::bridge(namespace = "cxx_qt")] mod ffi { - #[cxx_qt::qobject(base = "QStringListModel")] - pub struct MyObject; + extern "RustQt" { + #[cxx_qt::qobject(base = "QStringListModel")] + type MyObject = super::MyObjectRust; + } } }; let parser = Parser::from(module).unwrap(); @@ -209,8 +213,10 @@ mod tests { let module: ItemMod = parse_quote! { #[cxx_qt::bridge(namespace = "cxx_qt")] mod ffi { - #[cxx_qt::qobject(qml_uri = "com.kdab", qml_version = "1.0", qml_name = "MyQmlElement")] - pub struct MyNamedObject; + extern "RustQt" { + #[cxx_qt::qobject(qml_uri = "com.kdab", qml_version = "1.0", qml_name = "MyQmlElement")] + type MyNamedObject = super::MyNamedObjectRust; + } } }; let parser = Parser::from(module).unwrap(); @@ -233,8 +239,10 @@ mod tests { let module: ItemMod = parse_quote! { #[cxx_qt::bridge(namespace = "cxx_qt")] mod ffi { - #[cxx_qt::qobject(qml_uri = "com.kdab", qml_version = "1.0", qml_singleton)] - pub struct MyObject; + extern "RustQt" { + #[cxx_qt::qobject(qml_uri = "com.kdab", qml_version = "1.0", qml_singleton)] + type MyObject = super::MyObjectRust; + } } }; let parser = Parser::from(module).unwrap(); @@ -258,8 +266,10 @@ mod tests { let module: ItemMod = parse_quote! { #[cxx_qt::bridge(namespace = "cxx_qt")] mod ffi { - #[cxx_qt::qobject(qml_uri = "com.kdab", qml_version = "1.0", qml_uncreatable)] - pub struct MyObject; + extern "RustQt" { + #[cxx_qt::qobject(qml_uri = "com.kdab", qml_version = "1.0", qml_uncreatable)] + type MyObject = super::MyObjectRust; + } } }; let parser = Parser::from(module).unwrap(); diff --git a/crates/cxx-qt-gen/src/generator/naming/namespace.rs b/crates/cxx-qt-gen/src/generator/naming/namespace.rs index 53f87870f..01f216a97 100644 --- a/crates/cxx-qt-gen/src/generator/naming/namespace.rs +++ b/crates/cxx-qt-gen/src/generator/naming/namespace.rs @@ -15,7 +15,7 @@ pub struct NamespaceName { impl From<&ParsedQObject> for NamespaceName { fn from(qobject: &ParsedQObject) -> Self { - NamespaceName::from_pair_str(&qobject.namespace, &qobject.qobject_struct.ident) + NamespaceName::from_pair_str(&qobject.namespace, &qobject.qobject_ty.ident_left) } } diff --git a/crates/cxx-qt-gen/src/generator/naming/qobject.rs b/crates/cxx-qt-gen/src/generator/naming/qobject.rs index 44ab3b2eb..c6792cca4 100644 --- a/crates/cxx-qt-gen/src/generator/naming/qobject.rs +++ b/crates/cxx-qt-gen/src/generator/naming/qobject.rs @@ -24,18 +24,14 @@ pub struct QObjectName { impl From<&ParsedQObject> for QObjectName { fn from(qobject: &ParsedQObject) -> Self { - Self::from(&qobject.qobject_struct.ident) - } -} - -impl From<&Ident> for QObjectName { - fn from(ident: &Ident) -> Self { + let ident_left = &qobject.qobject_ty.ident_left; Self { - ident: ident.clone(), - cpp_class: CombinedIdent::cpp_class_from_rust_struct(ident.clone()), - rust_struct: CombinedIdent::from_rust_struct(ident.clone()), - cxx_qt_thread_class: cxx_qt_thread_class_from_ident(ident), - cxx_qt_thread_queued_fn_struct: cxx_qt_thread_queued_fn_struct_from_ident(ident), + ident: ident_left.clone(), + // TODO: later we may support cxx_name or rust_name so keep these are CombinedIdents for now + cpp_class: CombinedIdent::from_ident(ident_left.clone()), + rust_struct: CombinedIdent::from_ident(qobject.qobject_ty.ident_right.clone()), + cxx_qt_thread_class: cxx_qt_thread_class_from_ident(ident_left), + cxx_qt_thread_queued_fn_struct: cxx_qt_thread_queued_fn_struct_from_ident(ident_left), } } } @@ -61,16 +57,10 @@ fn cxx_qt_thread_queued_fn_struct_from_ident(ident: &Ident) -> Ident { } impl CombinedIdent { - /// For a given ident generate the C++ class name - fn cpp_class_from_rust_struct(ident: Ident) -> Self { - let rust = format_ident!("{ident}Qt"); - Self { cpp: ident, rust } - } - /// For a given ident generate the Rust and C++ names - fn from_rust_struct(ident: Ident) -> Self { + fn from_ident(ident: Ident) -> Self { Self { - cpp: format_ident!("{ident}Rust"), + cpp: ident.clone(), rust: ident, } } @@ -90,9 +80,9 @@ pub mod tests { fn test_parsed_property() { let names = QObjectName::from(&create_parsed_qobject()); assert_eq!(names.cpp_class.cpp, format_ident!("MyObject")); - assert_eq!(names.cpp_class.rust, format_ident!("MyObjectQt")); + assert_eq!(names.cpp_class.rust, format_ident!("MyObject")); assert_eq!(names.rust_struct.cpp, format_ident!("MyObjectRust")); - assert_eq!(names.rust_struct.rust, format_ident!("MyObject")); + assert_eq!(names.rust_struct.rust, format_ident!("MyObjectRust")); assert_eq!( names.cxx_qt_thread_class, format_ident!("MyObjectCxxQtThread") diff --git a/crates/cxx-qt-gen/src/generator/rust/inherit.rs b/crates/cxx-qt-gen/src/generator/rust/inherit.rs index d4b8f3708..d5123dd08 100644 --- a/crates/cxx-qt-gen/src/generator/rust/inherit.rs +++ b/crates/cxx-qt-gen/src/generator/rust/inherit.rs @@ -94,7 +94,7 @@ mod tests { quote! { unsafe extern "C++" { #[cxx_name = "testCxxQtInherit"] - fn test(self: Pin<&mut MyObjectQt>, a: B, b: C); + fn test(self: Pin<&mut MyObject>, a: B, b: C); } }, ); @@ -118,7 +118,7 @@ mod tests { quote! { unsafe extern "C++" { #[cxx_name = "testCxxQtInherit"] - fn test(self: &MyObjectQt, a: B, b: C); + fn test(self: &MyObject, a: B, b: C); } }, ); @@ -143,7 +143,7 @@ mod tests { quote! { extern "C++" { #[cxx_name = "testCxxQtInherit"] - unsafe fn test(self: &MyObjectQt,); + unsafe fn test(self: &MyObject,); } }, ); diff --git a/crates/cxx-qt-gen/src/generator/rust/invokable.rs b/crates/cxx-qt-gen/src/generator/rust/invokable.rs index ad53a7654..997f9143f 100644 --- a/crates/cxx-qt-gen/src/generator/rust/invokable.rs +++ b/crates/cxx-qt-gen/src/generator/rust/invokable.rs @@ -172,16 +172,16 @@ mod tests { quote! { extern "Rust" { #[cxx_name = "voidInvokableWrapper"] - fn void_invokable_wrapper(self: &MyObject, cpp: &MyObjectQt); + fn void_invokable_wrapper(self: &MyObjectRust, cpp: &MyObject); } }, ); assert_tokens_eq( &generated.cxx_qt_mod_contents[0], quote! { - impl MyObject { + impl MyObjectRust { #[doc(hidden)] - pub fn void_invokable_wrapper(self: &MyObject, cpp: &MyObjectQt) { + pub fn void_invokable_wrapper(self: &MyObjectRust, cpp: &MyObject) { cpp.void_invokable(); } } @@ -194,16 +194,16 @@ mod tests { quote! { extern "Rust" { #[cxx_name = "trivialInvokableWrapper"] - fn trivial_invokable_wrapper(self: &MyObject, cpp: &MyObjectQt, param: i32) -> i32; + fn trivial_invokable_wrapper(self: &MyObjectRust, cpp: &MyObject, param: i32) -> i32; } }, ); assert_tokens_eq( &generated.cxx_qt_mod_contents[1], quote! { - impl MyObject { + impl MyObjectRust { #[doc(hidden)] - pub fn trivial_invokable_wrapper(self: &MyObject, cpp: &MyObjectQt, param: i32) -> i32 { + pub fn trivial_invokable_wrapper(self: &MyObjectRust, cpp: &MyObject, param: i32) -> i32 { return cpp.trivial_invokable(param); } } @@ -216,16 +216,16 @@ mod tests { quote! { extern "Rust" { #[cxx_name = "opaqueInvokableWrapper"] - fn opaque_invokable_wrapper(self: &mut MyObject, cpp: Pin<&mut MyObjectQt>, param: &QColor) -> UniquePtr; + fn opaque_invokable_wrapper(self: &mut MyObjectRust, cpp: Pin<&mut MyObject>, param: &QColor) -> UniquePtr; } }, ); assert_tokens_eq( &generated.cxx_qt_mod_contents[2], quote! { - impl MyObject { + impl MyObjectRust { #[doc(hidden)] - pub fn opaque_invokable_wrapper(self: &mut MyObject, cpp: Pin<&mut MyObjectQt>, param: &QColor) -> UniquePtr { + pub fn opaque_invokable_wrapper(self: &mut MyObjectRust, cpp: Pin<&mut MyObject>, param: &QColor) -> UniquePtr { return cpp.opaque_invokable(param); } } @@ -238,16 +238,16 @@ mod tests { quote! { extern "Rust" { #[cxx_name = "unsafeInvokableWrapper"] - unsafe fn unsafe_invokable_wrapper(self: &MyObject, cpp: &MyObjectQt, param: *mut T) -> *mut T; + unsafe fn unsafe_invokable_wrapper(self: &MyObjectRust, cpp: &MyObject, param: *mut T) -> *mut T; } }, ); assert_tokens_eq( &generated.cxx_qt_mod_contents[3], quote! { - impl MyObject { + impl MyObjectRust { #[doc(hidden)] - pub unsafe fn unsafe_invokable_wrapper(self: &MyObject, cpp: &MyObjectQt, param: *mut T) -> *mut T { + pub unsafe fn unsafe_invokable_wrapper(self: &MyObjectRust, cpp: &MyObject, param: *mut T) -> *mut T { return cpp.unsafe_invokable(param); } } diff --git a/crates/cxx-qt-gen/src/generator/rust/mod.rs b/crates/cxx-qt-gen/src/generator/rust/mod.rs index ddbca6d84..a75ea9b9a 100644 --- a/crates/cxx-qt-gen/src/generator/rust/mod.rs +++ b/crates/cxx-qt-gen/src/generator/rust/mod.rs @@ -73,8 +73,10 @@ mod tests { let module: ItemMod = parse_quote! { #[cxx_qt::bridge] mod ffi { - #[cxx_qt::qobject] - pub struct MyObject; + extern "RustQt" { + #[cxx_qt::qobject] + type MyObject = super::MyObjectRust; + } } }; let parser = Parser::from(module).unwrap(); @@ -100,8 +102,10 @@ mod tests { let module: ItemMod = parse_quote! { #[cxx_qt::bridge(namespace = "cxx_qt")] mod ffi { - #[cxx_qt::qobject] - pub struct MyObject; + extern "RustQt" { + #[cxx_qt::qobject] + type MyObject = super::MyObjectRust; + } } }; let parser = Parser::from(module).unwrap(); @@ -121,8 +125,10 @@ mod tests { mod ffi { use std::collections::HashMap; - #[cxx_qt::qobject] - pub struct MyObject; + extern "RustQt" { + #[cxx_qt::qobject] + type MyObject = super::MyObjectRust; + } } }; let parser = Parser::from(module).unwrap(); @@ -140,8 +146,10 @@ mod tests { let module: ItemMod = parse_quote! { #[cxx_qt::bridge(cxx_file_stem = "my_object")] mod ffi { - #[cxx_qt::qobject] - pub struct MyObject; + extern "RustQt" { + #[cxx_qt::qobject] + type MyObject = super::MyObjectRust; + } } }; let parser = Parser::from(module).unwrap(); diff --git a/crates/cxx-qt-gen/src/generator/rust/property/mod.rs b/crates/cxx-qt-gen/src/generator/rust/property/mod.rs index 155c0f21f..f325aabad 100644 --- a/crates/cxx-qt-gen/src/generator/rust/property/mod.rs +++ b/crates/cxx-qt-gen/src/generator/rust/property/mod.rs @@ -95,16 +95,16 @@ mod tests { parse_quote! { extern "Rust" { #[cxx_name = "getTrivialProperty"] - unsafe fn trivial_property<'a>(self: &'a MyObject, cpp: &'a MyObjectQt) -> &'a i32; + unsafe fn trivial_property<'a>(self: &'a MyObjectRust, cpp: &'a MyObject) -> &'a i32; } }, ); assert_tokens_eq( &generated.cxx_qt_mod_contents[0], parse_quote! { - impl MyObject { + impl MyObjectRust { #[doc(hidden)] - pub fn trivial_property<'a>(&'a self, cpp: &'a MyObjectQt) -> &'a i32 { + pub fn trivial_property<'a>(&'a self, cpp: &'a MyObject) -> &'a i32 { cpp.trivial_property() } } @@ -113,7 +113,7 @@ mod tests { assert_tokens_eq( &generated.cxx_qt_mod_contents[1], parse_quote! { - impl MyObjectQt { + impl MyObject { #[doc = "Getter for the Q_PROPERTY "] #[doc = "trivial_property"] pub fn trivial_property(&self) -> &i32 { @@ -129,16 +129,16 @@ mod tests { parse_quote! { extern "Rust" { #[cxx_name = "setTrivialProperty"] - fn set_trivial_property(self: &mut MyObject, cpp: Pin<&mut MyObjectQt>, value: i32); + fn set_trivial_property(self: &mut MyObjectRust, cpp: Pin<&mut MyObject>, value: i32); } }, ); assert_tokens_eq( &generated.cxx_qt_mod_contents[2], parse_quote! { - impl MyObject { + impl MyObjectRust { #[doc(hidden)] - pub fn set_trivial_property(&mut self, cpp: Pin<&mut MyObjectQt>, value: i32) { + pub fn set_trivial_property(&mut self, cpp: Pin<&mut MyObject>, value: i32) { cpp.set_trivial_property(value); } } @@ -147,7 +147,7 @@ mod tests { assert_tokens_eq( &generated.cxx_qt_mod_contents[3], parse_quote! { - impl MyObjectQt { + impl MyObject { #[doc = "Setter for the Q_PROPERTY "] #[doc = "trivial_property"] pub fn set_trivial_property(mut self: Pin<&mut Self>, value: i32) { @@ -169,16 +169,16 @@ mod tests { parse_quote! { extern "Rust" { #[cxx_name = "getOpaqueProperty"] - unsafe fn opaque_property<'a>(self: &'a MyObject, cpp: &'a MyObjectQt) -> &'a UniquePtr; + unsafe fn opaque_property<'a>(self: &'a MyObjectRust, cpp: &'a MyObject) -> &'a UniquePtr; } }, ); assert_tokens_eq( &generated.cxx_qt_mod_contents[4], parse_quote! { - impl MyObject { + impl MyObjectRust { #[doc(hidden)] - pub fn opaque_property<'a>(&'a self, cpp: &'a MyObjectQt) -> &'a UniquePtr { + pub fn opaque_property<'a>(&'a self, cpp: &'a MyObject) -> &'a UniquePtr { cpp.opaque_property() } } @@ -187,7 +187,7 @@ mod tests { assert_tokens_eq( &generated.cxx_qt_mod_contents[5], parse_quote! { - impl MyObjectQt { + impl MyObject { #[doc = "Getter for the Q_PROPERTY "] #[doc = "opaque_property"] pub fn opaque_property(&self) -> &UniquePtr { @@ -203,16 +203,16 @@ mod tests { parse_quote! { extern "Rust" { #[cxx_name = "setOpaqueProperty"] - fn set_opaque_property(self: &mut MyObject, cpp: Pin<&mut MyObjectQt>, value: UniquePtr); + fn set_opaque_property(self: &mut MyObjectRust, cpp: Pin<&mut MyObject>, value: UniquePtr); } }, ); assert_tokens_eq( &generated.cxx_qt_mod_contents[6], parse_quote! { - impl MyObject { + impl MyObjectRust { #[doc(hidden)] - pub fn set_opaque_property(&mut self, cpp: Pin<&mut MyObjectQt>, value: UniquePtr) { + pub fn set_opaque_property(&mut self, cpp: Pin<&mut MyObject>, value: UniquePtr) { cpp.set_opaque_property(value); } } @@ -221,7 +221,7 @@ mod tests { assert_tokens_eq( &generated.cxx_qt_mod_contents[7], parse_quote! { - impl MyObjectQt { + impl MyObject { #[doc = "Setter for the Q_PROPERTY "] #[doc = "opaque_property"] pub fn set_opaque_property(mut self: Pin<&mut Self>, value: UniquePtr) { @@ -243,16 +243,16 @@ mod tests { parse_quote! { extern "Rust" { #[cxx_name = "getUnsafeProperty"] - unsafe fn unsafe_property<'a>(self: &'a MyObject, cpp: &'a MyObjectQt) -> &'a *mut T; + unsafe fn unsafe_property<'a>(self: &'a MyObjectRust, cpp: &'a MyObject) -> &'a *mut T; } }, ); assert_tokens_eq( &generated.cxx_qt_mod_contents[8], parse_quote! { - impl MyObject { + impl MyObjectRust { #[doc(hidden)] - pub fn unsafe_property<'a>(&'a self, cpp: &'a MyObjectQt) -> &'a *mut T { + pub fn unsafe_property<'a>(&'a self, cpp: &'a MyObject) -> &'a *mut T { cpp.unsafe_property() } } @@ -261,7 +261,7 @@ mod tests { assert_tokens_eq( &generated.cxx_qt_mod_contents[9], parse_quote! { - impl MyObjectQt { + impl MyObject { #[doc = "Getter for the Q_PROPERTY "] #[doc = "unsafe_property"] pub fn unsafe_property(&self) -> &*mut T { @@ -277,16 +277,16 @@ mod tests { parse_quote! { extern "Rust" { #[cxx_name = "setUnsafeProperty"] - unsafe fn set_unsafe_property(self: &mut MyObject, cpp: Pin<&mut MyObjectQt>, value: *mut T); + unsafe fn set_unsafe_property(self: &mut MyObjectRust, cpp: Pin<&mut MyObject>, value: *mut T); } }, ); assert_tokens_eq( &generated.cxx_qt_mod_contents[10], parse_quote! { - impl MyObject { + impl MyObjectRust { #[doc(hidden)] - pub fn set_unsafe_property(&mut self, cpp: Pin<&mut MyObjectQt>, value: *mut T) { + pub fn set_unsafe_property(&mut self, cpp: Pin<&mut MyObject>, value: *mut T) { cpp.set_unsafe_property(value); } } @@ -295,7 +295,7 @@ mod tests { assert_tokens_eq( &generated.cxx_qt_mod_contents[11], parse_quote! { - impl MyObjectQt { + impl MyObject { #[doc = "Setter for the Q_PROPERTY "] #[doc = "unsafe_property"] pub fn set_unsafe_property(mut self: Pin<&mut Self>, value: *mut T) { @@ -317,7 +317,7 @@ mod tests { unsafe extern "C++" { #[doc = "Notify for the Q_PROPERTY"] #[rust_name = "trivial_property_changed"] - fn trivialPropertyChanged(self: Pin<&mut MyObjectQt>, ); + fn trivialPropertyChanged(self: Pin<&mut MyObject>, ); } }, ); @@ -330,21 +330,21 @@ mod tests { #[doc = ", so that when the signal is emitted the function pointer is executed."] #[must_use] #[rust_name = "connect_trivial_property_changed"] - fn trivialPropertyChangedConnect(self: Pin <&mut MyObjectQt>, func: fn(Pin<&mut MyObjectQt>, ), conn_type : CxxQtConnectionType) -> CxxQtQMetaObjectConnection; + fn trivialPropertyChangedConnect(self: Pin <&mut MyObject>, func: fn(Pin<&mut MyObject>, ), conn_type : CxxQtConnectionType) -> CxxQtQMetaObjectConnection; } }, ); assert_tokens_eq( &generated.cxx_qt_mod_contents[12], parse_quote! { - impl MyObjectQt { + impl MyObject { #[doc = "Connect the given function pointer to the signal "] #[doc = "trivialPropertyChanged"] #[doc = ", so that when the signal is emitted the function pointer is executed."] #[doc = "\n"] #[doc = "Note that this method uses a AutoConnection connection type."] #[must_use] - pub fn on_trivial_property_changed(self: Pin<&mut MyObjectQt>, func: fn(Pin<&mut MyObjectQt>, )) -> CxxQtQMetaObjectConnection + pub fn on_trivial_property_changed(self: Pin<&mut MyObject>, func: fn(Pin<&mut MyObject>, )) -> CxxQtQMetaObjectConnection { self.connect_trivial_property_changed(func, CxxQtConnectionType::AutoConnection) } @@ -358,7 +358,7 @@ mod tests { unsafe extern "C++" { #[doc = "Notify for the Q_PROPERTY"] #[rust_name = "opaque_property_changed"] - fn opaquePropertyChanged(self: Pin<&mut MyObjectQt>, ); + fn opaquePropertyChanged(self: Pin<&mut MyObject>, ); } }, ); @@ -371,21 +371,21 @@ mod tests { #[doc = ", so that when the signal is emitted the function pointer is executed."] #[must_use] #[rust_name = "connect_opaque_property_changed"] - fn opaquePropertyChangedConnect(self: Pin <&mut MyObjectQt>, func: fn(Pin<&mut MyObjectQt>, ), conn_type : CxxQtConnectionType) -> CxxQtQMetaObjectConnection; + fn opaquePropertyChangedConnect(self: Pin <&mut MyObject>, func: fn(Pin<&mut MyObject>, ), conn_type : CxxQtConnectionType) -> CxxQtQMetaObjectConnection; } }, ); assert_tokens_eq( &generated.cxx_qt_mod_contents[13], parse_quote! { - impl MyObjectQt { + impl MyObject { #[doc = "Connect the given function pointer to the signal "] #[doc = "opaquePropertyChanged"] #[doc = ", so that when the signal is emitted the function pointer is executed."] #[doc = "\n"] #[doc = "Note that this method uses a AutoConnection connection type."] #[must_use] - pub fn on_opaque_property_changed(self: Pin<&mut MyObjectQt>, func: fn(Pin<&mut MyObjectQt>, )) -> CxxQtQMetaObjectConnection + pub fn on_opaque_property_changed(self: Pin<&mut MyObject>, func: fn(Pin<&mut MyObject>, )) -> CxxQtQMetaObjectConnection { self.connect_opaque_property_changed(func, CxxQtConnectionType::AutoConnection) } @@ -399,7 +399,7 @@ mod tests { unsafe extern "C++" { #[doc = "Notify for the Q_PROPERTY"] #[rust_name = "unsafe_property_changed"] - fn unsafePropertyChanged(self: Pin<&mut MyObjectQt>, ); + fn unsafePropertyChanged(self: Pin<&mut MyObject>, ); } }, ); @@ -412,21 +412,21 @@ mod tests { #[doc = ", so that when the signal is emitted the function pointer is executed."] #[must_use] #[rust_name = "connect_unsafe_property_changed"] - fn unsafePropertyChangedConnect(self: Pin <&mut MyObjectQt>, func: fn(Pin<&mut MyObjectQt>, ), conn_type : CxxQtConnectionType) -> CxxQtQMetaObjectConnection; + fn unsafePropertyChangedConnect(self: Pin <&mut MyObject>, func: fn(Pin<&mut MyObject>, ), conn_type : CxxQtConnectionType) -> CxxQtQMetaObjectConnection; } }, ); assert_tokens_eq( &generated.cxx_qt_mod_contents[14], parse_quote! { - impl MyObjectQt { + impl MyObject { #[doc = "Connect the given function pointer to the signal "] #[doc = "unsafePropertyChanged"] #[doc = ", so that when the signal is emitted the function pointer is executed."] #[doc = "\n"] #[doc = "Note that this method uses a AutoConnection connection type."] #[must_use] - pub fn on_unsafe_property_changed(self: Pin<&mut MyObjectQt>, func: fn(Pin<&mut MyObjectQt>, )) -> CxxQtQMetaObjectConnection + pub fn on_unsafe_property_changed(self: Pin<&mut MyObject>, func: fn(Pin<&mut MyObject>, )) -> CxxQtQMetaObjectConnection { self.connect_unsafe_property_changed(func, CxxQtConnectionType::AutoConnection) } diff --git a/crates/cxx-qt-gen/src/generator/rust/qobject.rs b/crates/cxx-qt-gen/src/generator/rust/qobject.rs index e274f50ac..43514c218 100644 --- a/crates/cxx-qt-gen/src/generator/rust/qobject.rs +++ b/crates/cxx-qt-gen/src/generator/rust/qobject.rs @@ -14,7 +14,7 @@ use crate::{ parser::qobject::ParsedQObject, }; use quote::quote; -use syn::{Ident, ImplItem, Item, Result}; +use syn::{parse_quote, Ident, ImplItem, Item, Result}; #[derive(Default)] pub struct GeneratedRustQObjectBlocks { @@ -62,11 +62,15 @@ impl GeneratedRustQObject { .blocks .append(&mut generate_qobject_definitions(&qobject_idents)?); - // Add our QObject struct to the implementation blocks - generated - .blocks - .cxx_qt_mod_contents - .push(syn::Item::Struct(qobject.qobject_struct.clone())); + // Add a type alias so that generated code can still find T + // + // TODO: this should be removed once generated methods aren't in the hidden module + generated.blocks.cxx_qt_mod_contents.push({ + let rust_struct_name_rust = &qobject_idents.rust_struct.rust; + parse_quote! { + type #rust_struct_name_rust = super::#rust_struct_name_rust; + } + }); // Generate methods for the properties, invokables, signals generated.blocks.append(&mut generate_rust_properties( @@ -169,9 +173,7 @@ fn generate_qobject_definitions( qobject_idents: &QObjectName, ) -> Result { let mut generated = GeneratedRustQObjectBlocks::default(); - let cpp_class_name_cpp = &qobject_idents.cpp_class.cpp.to_string(); let cpp_class_name_rust = &qobject_idents.cpp_class.rust; - let rust_struct_name_cpp = &qobject_idents.rust_struct.cpp.to_string(); let rust_struct_name_rust = &qobject_idents.rust_struct.rust; let rust_struct_name_rust_str = rust_struct_name_rust.to_string(); let fragment = RustFragmentPair { @@ -184,13 +186,11 @@ fn generate_qobject_definitions( #[doc = "Use this type when referring to the QObject as a pointer"] #[doc = "\n"] #[doc = "See the book for more information: "] - #[cxx_name = #cpp_class_name_cpp] type #cpp_class_name_rust; } }, quote! { extern "Rust" { - #[cxx_name = #rust_struct_name_cpp] type #rust_struct_name_rust; } }, @@ -218,17 +218,19 @@ mod tests { let module: ItemMod = parse_quote! { #[cxx_qt::bridge] mod ffi { - #[cxx_qt::qobject] - pub struct MyObject; + extern "RustQt" { + #[cxx_qt::qobject] + type MyObject = super::MyObjectRust; + } } }; let parser = Parser::from(module).unwrap(); let rust = GeneratedRustQObject::from(parser.cxx_qt_data.qobjects.values().next().unwrap()) .unwrap(); - assert_eq!(rust.cpp_struct_ident, "MyObjectQt"); + assert_eq!(rust.cpp_struct_ident, "MyObject"); assert_eq!(rust.namespace_internals, "cxx_qt_my_object"); - assert_eq!(rust.rust_struct_ident, "MyObject"); + assert_eq!(rust.rust_struct_ident, "MyObjectRust"); } #[test] @@ -236,17 +238,19 @@ mod tests { let module: ItemMod = parse_quote! { #[cxx_qt::bridge(namespace = "cxx_qt")] mod ffi { - #[cxx_qt::qobject] - pub struct MyObject; + extern "RustQt" { + #[cxx_qt::qobject] + type MyObject = super::MyObjectRust; + } } }; let parser = Parser::from(module).unwrap(); let rust = GeneratedRustQObject::from(parser.cxx_qt_data.qobjects.values().next().unwrap()) .unwrap(); - assert_eq!(rust.cpp_struct_ident, "MyObjectQt"); + assert_eq!(rust.cpp_struct_ident, "MyObject"); assert_eq!(rust.namespace_internals, "cxx_qt::cxx_qt_my_object"); - assert_eq!(rust.rust_struct_ident, "MyObject"); + assert_eq!(rust.rust_struct_ident, "MyObjectRust"); } #[test] @@ -254,8 +258,10 @@ mod tests { let module: ItemMod = parse_quote! { #[cxx_qt::bridge(namespace = "cxx_qt")] mod ffi { - #[cxx_qt::qobject(qml_uri = "com.kdab", qml_version = "1.0", qml_singleton)] - pub struct MyObject; + extern "RustQt" { + #[cxx_qt::qobject(qml_uri = "com.kdab", qml_version = "1.0", qml_singleton)] + type MyObject = super::MyObjectRust; + } } }; let parser = Parser::from(module).unwrap(); @@ -268,13 +274,12 @@ mod tests { quote! { unsafe extern "C++" { #[doc = "The C++ type for the QObject "] - #[doc = "MyObject"] + #[doc = "MyObjectRust"] #[doc = "\n"] #[doc = "Use this type when referring to the QObject as a pointer"] #[doc = "\n"] #[doc = "See the book for more information: "] - #[cxx_name = "MyObject"] - type MyObjectQt; + type MyObject; } }, ); @@ -282,8 +287,7 @@ mod tests { &rust.blocks.cxx_mod_contents[1], quote! { extern "Rust" { - #[cxx_name = "MyObjectRust"] - type MyObject; + type MyObjectRust; } }, ); @@ -301,7 +305,7 @@ mod tests { extern "Rust" { #[cxx_name = "createRs"] #[namespace = "cxx_qt::cxx_qt_my_object"] - fn create_rs_my_object() -> Box; + fn create_rs_my_object_rust() -> Box; } }, ); diff --git a/crates/cxx-qt-gen/src/generator/rust/signals.rs b/crates/cxx-qt-gen/src/generator/rust/signals.rs index a028974c0..b4724ef8a 100644 --- a/crates/cxx-qt-gen/src/generator/rust/signals.rs +++ b/crates/cxx-qt-gen/src/generator/rust/signals.rs @@ -142,7 +142,7 @@ mod tests { quote! { unsafe extern "C++" { #[rust_name = "ready"] - fn ready(self: Pin<&mut MyObjectQt>, ); + fn ready(self: Pin<&mut MyObject>, ); } }, ); @@ -155,21 +155,21 @@ mod tests { #[doc = ", so that when the signal is emitted the function pointer is executed."] #[must_use] #[rust_name = "connect_ready"] - fn readyConnect(self: Pin<&mut MyObjectQt>, func: fn(Pin<&mut MyObjectQt>, ), conn_type : CxxQtConnectionType) -> CxxQtQMetaObjectConnection; + fn readyConnect(self: Pin<&mut MyObject>, func: fn(Pin<&mut MyObject>, ), conn_type : CxxQtConnectionType) -> CxxQtQMetaObjectConnection; } }, ); assert_tokens_eq( &generated.cxx_qt_mod_contents[0], quote! { - impl MyObjectQt { + impl MyObject { #[doc = "Connect the given function pointer to the signal "] #[doc = "ready"] #[doc = ", so that when the signal is emitted the function pointer is executed."] #[doc = "\n"] #[doc = "Note that this method uses a AutoConnection connection type."] #[must_use] - pub fn on_ready(self: Pin<&mut MyObjectQt>, func: fn(Pin<&mut MyObjectQt>, )) -> CxxQtQMetaObjectConnection + pub fn on_ready(self: Pin<&mut MyObject>, func: fn(Pin<&mut MyObject>, )) -> CxxQtQMetaObjectConnection { self.connect_ready(func, CxxQtConnectionType::AutoConnection) } @@ -217,7 +217,7 @@ mod tests { unsafe extern "C++" { #[attribute] #[rust_name = "data_changed"] - fn dataChanged(self: Pin<&mut MyObjectQt>, trivial: i32, opaque: UniquePtr); + fn dataChanged(self: Pin<&mut MyObject>, trivial: i32, opaque: UniquePtr); } }, ); @@ -230,21 +230,21 @@ mod tests { #[doc = ", so that when the signal is emitted the function pointer is executed."] #[must_use] #[rust_name = "connect_data_changed"] - fn dataChangedConnect(self: Pin<&mut MyObjectQt>, func: fn(Pin<&mut MyObjectQt>, trivial: i32, opaque: UniquePtr), conn_type : CxxQtConnectionType) -> CxxQtQMetaObjectConnection; + fn dataChangedConnect(self: Pin<&mut MyObject>, func: fn(Pin<&mut MyObject>, trivial: i32, opaque: UniquePtr), conn_type : CxxQtConnectionType) -> CxxQtQMetaObjectConnection; } }, ); assert_tokens_eq( &generated.cxx_qt_mod_contents[0], quote! { - impl MyObjectQt { + impl MyObject { #[doc = "Connect the given function pointer to the signal "] #[doc = "dataChanged"] #[doc = ", so that when the signal is emitted the function pointer is executed."] #[doc = "\n"] #[doc = "Note that this method uses a AutoConnection connection type."] #[must_use] - pub fn on_data_changed(self: Pin<&mut MyObjectQt>, func: fn(Pin<&mut MyObjectQt>, trivial: i32, opaque: UniquePtr)) -> CxxQtQMetaObjectConnection + pub fn on_data_changed(self: Pin<&mut MyObject>, func: fn(Pin<&mut MyObject>, trivial: i32, opaque: UniquePtr)) -> CxxQtQMetaObjectConnection { self.connect_data_changed(func, CxxQtConnectionType::AutoConnection) } @@ -284,7 +284,7 @@ mod tests { quote! { extern "C++" { #[rust_name = "unsafe_signal"] - unsafe fn unsafeSignal(self: Pin<&mut MyObjectQt>, param: *mut T); + unsafe fn unsafeSignal(self: Pin<&mut MyObject>, param: *mut T); } }, ); @@ -297,21 +297,21 @@ mod tests { #[doc = ", so that when the signal is emitted the function pointer is executed."] #[must_use] #[rust_name = "connect_unsafe_signal"] - fn unsafeSignalConnect(self: Pin <&mut MyObjectQt>, func: unsafe fn(Pin<&mut MyObjectQt>, param: *mut T), conn_type : CxxQtConnectionType) -> CxxQtQMetaObjectConnection; + fn unsafeSignalConnect(self: Pin <&mut MyObject>, func: unsafe fn(Pin<&mut MyObject>, param: *mut T), conn_type : CxxQtConnectionType) -> CxxQtQMetaObjectConnection; } }, ); assert_tokens_eq( &generated.cxx_qt_mod_contents[0], quote! { - impl MyObjectQt { + impl MyObject { #[doc = "Connect the given function pointer to the signal "] #[doc = "unsafeSignal"] #[doc = ", so that when the signal is emitted the function pointer is executed."] #[doc = "\n"] #[doc = "Note that this method uses a AutoConnection connection type."] #[must_use] - pub fn on_unsafe_signal(self: Pin<&mut MyObjectQt>, func: fn(Pin<&mut MyObjectQt>, param: *mut T)) -> CxxQtQMetaObjectConnection + pub fn on_unsafe_signal(self: Pin<&mut MyObject>, func: fn(Pin<&mut MyObject>, param: *mut T)) -> CxxQtQMetaObjectConnection { self.connect_unsafe_signal(func, CxxQtConnectionType::AutoConnection) } @@ -350,7 +350,7 @@ mod tests { unsafe extern "C++" { #[inherit] #[rust_name = "existing_signal"] - fn baseName(self: Pin<&mut MyObjectQt>, ); + fn baseName(self: Pin<&mut MyObject>, ); } }, ); @@ -363,21 +363,21 @@ mod tests { #[doc = ", so that when the signal is emitted the function pointer is executed."] #[must_use] #[rust_name = "connect_existing_signal"] - fn baseNameConnect(self: Pin<& mut MyObjectQt>, func: fn(Pin<&mut MyObjectQt>, ), conn_type : CxxQtConnectionType) -> CxxQtQMetaObjectConnection; + fn baseNameConnect(self: Pin<& mut MyObject>, func: fn(Pin<&mut MyObject>, ), conn_type : CxxQtConnectionType) -> CxxQtQMetaObjectConnection; } }, ); assert_tokens_eq( &generated.cxx_qt_mod_contents[0], quote! { - impl MyObjectQt { + impl MyObject { #[doc = "Connect the given function pointer to the signal "] #[doc = "baseName"] #[doc = ", so that when the signal is emitted the function pointer is executed."] #[doc = "\n"] #[doc = "Note that this method uses a AutoConnection connection type."] #[must_use] - pub fn on_existing_signal(self: Pin<&mut MyObjectQt>, func: fn(Pin<&mut MyObjectQt>, )) -> CxxQtQMetaObjectConnection + pub fn on_existing_signal(self: Pin<&mut MyObject>, func: fn(Pin<&mut MyObject>, )) -> CxxQtQMetaObjectConnection { self.connect_existing_signal(func, CxxQtConnectionType::AutoConnection) } diff --git a/crates/cxx-qt-gen/src/generator/rust/threading.rs b/crates/cxx-qt-gen/src/generator/rust/threading.rs index 05c3303ab..947a46bef 100644 --- a/crates/cxx-qt-gen/src/generator/rust/threading.rs +++ b/crates/cxx-qt-gen/src/generator/rust/threading.rs @@ -171,12 +171,12 @@ mod tests { quote! { unsafe extern "C++" { #[doc(hidden)] - type MyObjectCxxQtThread = cxx_qt::CxxQtThread; + type MyObjectCxxQtThread = cxx_qt::CxxQtThread; include!("cxx-qt-common/cxxqt_thread.h"); #[doc(hidden)] #[cxx_name = "qtThread"] - fn cxx_qt_ffi_qt_thread(self: &MyObjectQt) -> MyObjectCxxQtThread; + fn cxx_qt_ffi_qt_thread(self: &MyObject) -> MyObjectCxxQtThread; // SAFETY: // - Send + 'static: argument closure can be transferred to QObject thread. @@ -186,7 +186,7 @@ mod tests { #[cxx_name = "cxxQtThreadQueue"] fn cxx_qt_ffi_my_object_queue_boxed_fn( cxx_qt_thread: &MyObjectCxxQtThread, - func: fn(Pin<&mut MyObjectQt>, Box), + func: fn(Pin<&mut MyObject>, Box), arg: Box, ) -> Result<()>; @@ -216,7 +216,7 @@ mod tests { assert_tokens_eq( &generated.cxx_qt_mod_contents[0], quote! { - impl cxx_qt::Threading for MyObjectQt { + impl cxx_qt::Threading for MyObject { type BoxedQueuedFn = MyObjectCxxQtThreadQueuedFn; type ThreadingTypeId = cxx::type_id!("MyObjectCxxQtThread"); @@ -228,7 +228,7 @@ mod tests { #[doc(hidden)] fn queue(cxx_qt_thread: &MyObjectCxxQtThread, f: F) -> std::result::Result<(), cxx::Exception> where - F: FnOnce(std::pin::Pin<&mut MyObjectQt>), + F: FnOnce(std::pin::Pin<&mut MyObject>), F: Send + 'static, { // Wrap the given closure and pass in to C++ function as an opaque type @@ -237,7 +237,7 @@ mod tests { #[allow(clippy::boxed_local)] #[doc(hidden)] fn func( - obj: std::pin::Pin<&mut MyObjectQt>, + obj: std::pin::Pin<&mut MyObject>, arg: std::boxed::Box, ) { (arg.inner)(obj) @@ -267,7 +267,7 @@ mod tests { pub struct MyObjectCxxQtThreadQueuedFn { // An opaque Rust type is required to be Sized. // https://github.com/dtolnay/cxx/issues/665 - inner: std::boxed::Box) + Send>, + inner: std::boxed::Box) + Send>, } }, ); diff --git a/crates/cxx-qt-gen/src/parser/cxxqtdata.rs b/crates/cxx-qt-gen/src/parser/cxxqtdata.rs index d80e7f6e0..50aafc446 100644 --- a/crates/cxx-qt-gen/src/parser/cxxqtdata.rs +++ b/crates/cxx-qt-gen/src/parser/cxxqtdata.rs @@ -3,7 +3,7 @@ // // SPDX-License-Identifier: MIT OR Apache-2.0 -use crate::syntax::foreignmod::foreign_mod_to_foreign_item_types; +use crate::syntax::foreignmod::{foreign_mod_to_foreign_item_types, ForeignTypeIdentAlias}; use crate::syntax::safety::Safety; use crate::syntax::{attribute::attribute_find_path, path::path_to_single_ident}; use crate::{ @@ -66,23 +66,36 @@ pub struct ParsedCxxQtData { impl ParsedCxxQtData { /// Find the QObjects within the module and add into the qobjects BTreeMap - pub fn find_qobject_structs(&mut self, items: &[Item]) -> Result<()> { + pub fn find_qobject_types(&mut self, items: &[Item]) -> Result<()> { for item in items { - if let Item::Struct(qobject_struct) = item { - if let Some(index) = - attribute_find_path(&qobject_struct.attrs, &["cxx_qt", "qobject"]) + if let Item::ForeignMod(foreign_mod) = item { + if foreign_mod.abi.name.as_ref().map(|lit_str| lit_str.value()) + == Some("RustQt".to_string()) { - // Load the QObject - let mut qobject = ParsedQObject::from_struct(qobject_struct, index)?; - - // Inject the bridge namespace if the qobject one is empty - if qobject.namespace.is_empty() && !self.namespace.is_empty() { - qobject.namespace = self.namespace.clone(); + for foreign_item in &foreign_mod.items { + if let ForeignItem::Verbatim(tokens) = foreign_item { + let foreign_alias: ForeignTypeIdentAlias = syn::parse2(tokens.clone())?; + + // TODO: in the future qobject macro will be removed and all types in RustQt will be QObjects + if let Some(index) = + attribute_find_path(&foreign_alias.attrs, &["cxx_qt", "qobject"]) + { + // Load the QObject + let mut qobject = + ParsedQObject::from_foreign_item_type(&foreign_alias, index)?; + + // Inject the bridge namespace if the qobject one is empty + if qobject.namespace.is_empty() && !self.namespace.is_empty() { + qobject.namespace = self.namespace.clone(); + } + + // Note that we assume a compiler error will occur later + // if you had two structs with the same name + self.qobjects + .insert(foreign_alias.ident_left.clone(), qobject); + } + } } - - // Note that we assume a compiler error will occur later - // if you had two structs with the same name - self.qobjects.insert(qobject_struct.ident.clone(), qobject); } } } @@ -170,8 +183,6 @@ impl ParsedCxxQtData { pub fn parse_cxx_qt_item(&mut self, item: Item) -> Result> { match item { Item::Impl(imp) => self.parse_impl(imp), - // Ignore structs which are qobjects - Item::Struct(s) if self.qobjects.contains_key(&s.ident) => Ok(None), Item::Use(_) => { // Any use statements go into the CXX-Qt generated block self.uses.push(item); @@ -318,12 +329,15 @@ mod tests { let module: ItemMod = parse_quote! { mod module { - struct Other; - #[cxx_qt::qobject] - pub struct MyObject; + extern "RustQt" { + type Other = super::OtherRust; + + #[cxx_qt::qobject] + type MyObject = super::MyObjectRust; + } } }; - let result = cxx_qt_data.find_qobject_structs(&module.content.unwrap().1); + let result = cxx_qt_data.find_qobject_types(&module.content.unwrap().1); assert!(result.is_ok()); assert_eq!(cxx_qt_data.qobjects.len(), 1); assert!(cxx_qt_data.qobjects.contains_key(&qobject_ident())); @@ -335,14 +349,17 @@ mod tests { let module: ItemMod = parse_quote! { mod module { - pub struct Other; - #[cxx_qt::qobject] - pub struct MyObject; - #[cxx_qt::qobject] - pub struct SecondObject; + extern "RustQt" { + type Other = super::OtherRust; + + #[cxx_qt::qobject] + type MyObject = super::MyObjectRust; + #[cxx_qt::qobject] + type SecondObject = super::SecondObjectRust; + } } }; - let result = cxx_qt_data.find_qobject_structs(&module.content.unwrap().1); + let result = cxx_qt_data.find_qobject_types(&module.content.unwrap().1); assert!(result.is_ok()); assert_eq!(cxx_qt_data.qobjects.len(), 2); assert!(cxx_qt_data.qobjects.contains_key(&qobject_ident())); @@ -360,15 +377,17 @@ mod tests { let module: ItemMod = parse_quote! { mod module { - pub struct Other; - #[cxx_qt::qobject(namespace = "qobject_namespace")] - pub struct MyObject; - #[cxx_qt::qobject] - pub struct SecondObject; + extern "RustQt" { + type Other = super::OtherRust; + #[cxx_qt::qobject(namespace = "qobject_namespace")] + type MyObject = super::MyObjectRust; + #[cxx_qt::qobject] + type SecondObject = super::SecondObjectRust; + } } }; cxx_qt_data - .find_qobject_structs(&module.content.unwrap().1) + .find_qobject_types(&module.content.unwrap().1) .unwrap(); assert_eq!(cxx_qt_data.qobjects.len(), 2); assert_eq!( @@ -395,25 +414,26 @@ mod tests { let module: ItemMod = parse_quote! { mod module { - pub struct Other; - pub struct MyObject; + extern "RustQt" { + type Other = super::OtherRust; + type MyObject = super::MyObjectRust; + } } }; - let result = cxx_qt_data.find_qobject_structs(&module.content.unwrap().1); + let result = cxx_qt_data.find_qobject_types(&module.content.unwrap().1); assert!(result.is_ok()); assert_eq!(cxx_qt_data.qobjects.len(), 0); } #[test] - fn test_find_and_merge_cxx_qt_item_struct_qobject() { + fn test_find_and_merge_cxx_qt_item_struct_qobject_passthrough() { let mut cxx_qt_data = create_parsed_cxx_qt_data(); let item: Item = parse_quote! { - #[cxx_qt::qobject] pub struct MyObject; }; let result = cxx_qt_data.parse_cxx_qt_item(item).unwrap(); - assert!(result.is_none()); + assert!(result.is_some()); } #[test] diff --git a/crates/cxx-qt-gen/src/parser/mod.rs b/crates/cxx-qt-gen/src/parser/mod.rs index 69972f8c6..1b0357be5 100644 --- a/crates/cxx-qt-gen/src/parser/mod.rs +++ b/crates/cxx-qt-gen/src/parser/mod.rs @@ -68,7 +68,7 @@ impl Parser { let bridge_namespace = cxx_qt_data.namespace.clone(); // Find any QObject structs - cxx_qt_data.find_qobject_structs(&items.1)?; + cxx_qt_data.find_qobject_types(&items.1)?; // Loop through any qobjects that were found if !cxx_qt_data.qobjects.is_empty() { @@ -160,8 +160,10 @@ mod tests { let module: ItemMod = parse_quote! { #[cxx_qt::bridge(namespace = "cxx_qt")] mod ffi { - #[cxx_qt::qobject] - pub struct MyObject; + extern "RustQt" { + #[cxx_qt::qobject] + type MyObject = super::MyObjectRust; + } unsafe extern "RustQt" { #[qsignal] @@ -185,8 +187,10 @@ mod tests { let module: ItemMod = parse_quote! { #[cxx_qt::bridge] mod ffi { - #[cxx_qt::qobject] - pub struct MyObject; + extern "RustQt" { + #[cxx_qt::qobject] + type MyObject = super::MyObjectRust; + } unsafe extern "RustQt" { #[qsignal] @@ -214,8 +218,10 @@ mod tests { let module: ItemMod = parse_quote! { #[cxx_qt::bridge] mod ffi { - #[cxx_qt::qobject] - pub struct MyObject; + extern "RustQt" { + #[cxx_qt::qobject] + type MyObject = super::MyObjectRust; + } unsafe extern "RustQt" { #[qsignal] diff --git a/crates/cxx-qt-gen/src/parser/qobject.rs b/crates/cxx-qt-gen/src/parser/qobject.rs index 138170837..2b3422897 100644 --- a/crates/cxx-qt-gen/src/parser/qobject.rs +++ b/crates/cxx-qt-gen/src/parser/qobject.rs @@ -10,13 +10,11 @@ use crate::{ }, syntax::{ attribute::{attribute_find_path, attribute_tokens_to_map, AttributeDefault}, + foreignmod::ForeignTypeIdentAlias, path::path_compare_str, }, }; -use syn::{ - spanned::Spanned, Attribute, Error, Ident, ImplItem, Item, ItemImpl, ItemStruct, LitStr, - Result, Visibility, -}; +use syn::{Attribute, Error, Ident, ImplItem, Item, ItemImpl, LitStr, Result}; /// Metadata for registering QML element #[derive(Clone, Debug, Default, Eq, PartialEq)] @@ -36,8 +34,8 @@ pub struct QmlElementMetadata { pub struct ParsedQObject { /// The base class of the struct pub base_class: Option, - /// QObject struct that stores the invokables for the QObject - pub qobject_struct: ItemStruct, + /// QObject type that stores the invokables for the QObject + pub qobject_ty: ForeignTypeIdentAlias, /// The namespace of the QObject. If one isn't specified for the QObject, /// this will be the same as the module pub namespace: String, @@ -71,12 +69,15 @@ pub struct ParsedQObject { } impl ParsedQObject { - /// Parse a [syn::ItemStruct] into a [ParsedQObject] with the index of the cxx_qt::qobject specified - pub fn from_struct(qobject_struct: &ItemStruct, attr_index: usize) -> Result { - let qml_metadata = Self::parse_qml_metadata(qobject_struct, attr_index)?; + /// Parse a ForeignTypeIdentAlias into a [ParsedQObject] with the index of the cxx_qt::qobject specified + pub fn from_foreign_item_type( + qobject_ty: &ForeignTypeIdentAlias, + attr_index: usize, + ) -> Result { + let qml_metadata = Self::parse_qml_metadata(qobject_ty, attr_index)?; let attrs_map = attribute_tokens_to_map::( - &qobject_struct.attrs[attr_index], + &qobject_ty.attrs[attr_index], AttributeDefault::Some(|span| LitStr::new("", span)), )?; @@ -90,26 +91,17 @@ impl ParsedQObject { .get("e::format_ident!("namespace")) .map_or_else(|| "".to_owned(), |base| base.value()); - // Remove the macro from the struct - let mut qobject_struct = qobject_struct.clone(); - qobject_struct.attrs.remove(attr_index); + // Remove the macro from the type + let mut qobject_ty = qobject_ty.clone(); + qobject_ty.attrs.remove(attr_index); - // Parse any properties in the struct + // Parse any properties in the type // and remove the #[qproperty] attribute - let properties = Self::parse_struct_attributes(&mut qobject_struct.attrs)?; - - // Ensure that the QObject is marked as pub otherwise the error is non obvious - // https://github.com/KDAB/cxx-qt/issues/457 - if !matches!(qobject_struct.vis, Visibility::Public(..)) { - return Err(Error::new( - qobject_struct.span(), - "qobject marked structs must be public", - )); - } + let properties = Self::parse_property_attributes(&mut qobject_ty.attrs)?; Ok(Self { base_class, - qobject_struct, + qobject_ty, namespace, signals: vec![], invokables: vec![], @@ -125,11 +117,11 @@ impl ParsedQObject { } fn parse_qml_metadata( - qobject_struct: &ItemStruct, + qobject_ty: &ForeignTypeIdentAlias, attr_index: usize, ) -> Result> { let attrs_map = attribute_tokens_to_map::( - &qobject_struct.attrs[attr_index], + &qobject_ty.attrs[attr_index], AttributeDefault::Some(|span| LitStr::new("", span)), )?; let qml_uri = attrs_map.get("e::format_ident!("qml_uri")); @@ -148,7 +140,7 @@ impl ParsedQObject { let name = match qml_name { Some(qml_name) => qml_name.value(), - None => qobject_struct.ident.to_string(), + None => qobject_ty.ident_left.to_string(), }; Ok(Some(QmlElementMetadata { @@ -260,7 +252,7 @@ impl ParsedQObject { } } - fn parse_struct_attributes(attrs: &mut Vec) -> Result> { + fn parse_property_attributes(attrs: &mut Vec) -> Result> { let mut properties = vec![]; // Note that once extract_if is stable, this would allow for comparing all the @@ -283,64 +275,57 @@ pub mod tests { use syn::{parse_quote, ItemImpl}; pub fn create_parsed_qobject() -> ParsedQObject { - let qobject_struct: ItemStruct = parse_quote! { + let qobject_struct: ForeignTypeIdentAlias = parse_quote! { #[cxx_qt::qobject] - pub struct MyObject; + type MyObject = super::MyObjectRust; }; - ParsedQObject::from_struct(&qobject_struct, 0).unwrap() + ParsedQObject::from_foreign_item_type(&qobject_struct, 0).unwrap() } #[test] fn test_from_struct_no_base_class() { - let qobject_struct: ItemStruct = parse_quote! { + let qobject_struct: ForeignTypeIdentAlias = parse_quote! { #[cxx_qt::qobject] - pub struct MyObject; + type MyObject = super::MyObjectRust; }; - let qobject = ParsedQObject::from_struct(&qobject_struct, 0).unwrap(); + let qobject = ParsedQObject::from_foreign_item_type(&qobject_struct, 0).unwrap(); assert!(qobject.base_class.is_none()); assert!(qobject.qml_metadata.is_none()); } #[test] fn test_from_struct_base_class() { - let qobject_struct: ItemStruct = parse_quote! { + let qobject_struct: ForeignTypeIdentAlias = parse_quote! { #[cxx_qt::qobject(base = "QStringListModel")] - pub struct MyObject; + type MyObject = super::MyObjectRust; }; - let qobject = ParsedQObject::from_struct(&qobject_struct, 0).unwrap(); + let qobject = ParsedQObject::from_foreign_item_type(&qobject_struct, 0).unwrap(); assert_eq!(qobject.base_class.as_ref().unwrap(), "QStringListModel"); } #[test] fn test_from_struct_properties_and_fields() { - let qobject_struct: ItemStruct = parse_quote! { + let qobject_struct: ForeignTypeIdentAlias = parse_quote! { #[cxx_qt::qobject] #[qproperty(i32, int_property)] #[qproperty(i32, public_property)] - pub struct MyObject { - int_property: i32, - pub public_property: i32, - - field: i32, - } + type MyObject = super::MyObjectRust; }; - let qobject = ParsedQObject::from_struct(&qobject_struct, 0).unwrap(); + let qobject = ParsedQObject::from_foreign_item_type(&qobject_struct, 0).unwrap(); assert_eq!(qobject.properties.len(), 2); } #[test] fn test_from_struct_fields() { - let qobject_struct: ItemStruct = parse_quote! { + let qobject_struct: ForeignTypeIdentAlias = parse_quote! { #[cxx_qt::qobject] - pub struct MyObject { - field: i32, - } + type MyObject = super::MyObjectRust; }; - let qobject = ParsedQObject::from_struct(&qobject_struct, 0).unwrap(); + let qobject = ParsedQObject::from_foreign_item_type(&qobject_struct, 0).unwrap(); assert_eq!(qobject.properties.len(), 0); } @@ -388,18 +373,15 @@ pub mod tests { #[test] fn test_parse_struct_fields_valid() { - let item: ItemStruct = parse_quote! { + let item: ForeignTypeIdentAlias = parse_quote! { #[cxx_qt::qobject] #[qproperty(f64, f64_property)] #[qproperty(f64, public_property)] - pub struct T { - f64_property: f64, - pub public_property: f64, - - field: f64, - } + type T = super::TRust; }; - let properties = ParsedQObject::from_struct(&item, 0).unwrap().properties; + let properties = ParsedQObject::from_foreign_item_type(&item, 0) + .unwrap() + .properties; assert_eq!(properties.len(), 2); assert_eq!(properties[0].ident, "f64_property"); @@ -409,22 +391,13 @@ pub mod tests { assert_eq!(properties[1].ty, f64_type()); } - #[test] - fn test_parse_struct_fields() { - let item: ItemStruct = parse_quote! { - #[cxx_qt::qobject] - pub struct T(f64); - }; - assert!(ParsedQObject::from_struct(&item, 0).is_ok()); - } - #[test] fn test_qml_metadata() { - let item: ItemStruct = parse_quote! { + let item: ForeignTypeIdentAlias = parse_quote! { #[cxx_qt::qobject(qml_uri = "foo.bar", qml_version = "1.0")] - pub struct MyObject; + type MyObject = super::MyObjectRust; }; - let qobject = ParsedQObject::from_struct(&item, 0).unwrap(); + let qobject = ParsedQObject::from_foreign_item_type(&item, 0).unwrap(); assert_eq!( qobject.qml_metadata, Some(QmlElementMetadata { @@ -440,11 +413,11 @@ pub mod tests { #[test] fn test_qml_metadata_named() { - let item: ItemStruct = parse_quote! { + let item: ForeignTypeIdentAlias = parse_quote! { #[cxx_qt::qobject(qml_uri = "foo.bar", qml_version = "1", qml_name = "MyQmlElement")] - pub struct MyNamedObject; + type MyNamedObject = super::MyObjectRust; }; - let qobject = ParsedQObject::from_struct(&item, 0).unwrap(); + let qobject = ParsedQObject::from_foreign_item_type(&item, 0).unwrap(); assert_eq!( qobject.qml_metadata, Some(QmlElementMetadata { @@ -460,11 +433,11 @@ pub mod tests { #[test] fn test_qml_metadata_singleton() { - let item: ItemStruct = parse_quote! { + let item: ForeignTypeIdentAlias = parse_quote! { #[cxx_qt::qobject(qml_uri = "foo.bar", qml_version = "1", qml_singleton)] - pub struct MyObject; + type MyObject = super::MyObjectRust; }; - let qobject = ParsedQObject::from_struct(&item, 0).unwrap(); + let qobject = ParsedQObject::from_foreign_item_type(&item, 0).unwrap(); assert_eq!( qobject.qml_metadata, Some(QmlElementMetadata { @@ -480,11 +453,11 @@ pub mod tests { #[test] fn test_qml_metadata_uncreatable() { - let item: ItemStruct = parse_quote! { + let item: ForeignTypeIdentAlias = parse_quote! { #[cxx_qt::qobject(qml_uri = "foo.bar", qml_version = "1", qml_uncreatable)] - pub struct MyObject; + type MyObject = super::MyObjectRust; }; - let qobject = ParsedQObject::from_struct(&item, 0).unwrap(); + let qobject = ParsedQObject::from_foreign_item_type(&item, 0).unwrap(); assert_eq!( qobject.qml_metadata, Some(QmlElementMetadata { @@ -500,28 +473,28 @@ pub mod tests { #[test] fn test_qml_metadata_no_version() { - let item: ItemStruct = parse_quote! { + let item: ForeignTypeIdentAlias = parse_quote! { #[cxx_qt::qobject(qml_uri = "foo.bar")] - pub struct MyObject; + type MyObject = super::MyObjectRust; }; - assert!(ParsedQObject::from_struct(&item, 0).is_err()); + assert!(ParsedQObject::from_foreign_item_type(&item, 0).is_err()); } #[test] fn test_qml_metadata_no_uri() { - let item: ItemStruct = parse_quote! { + let item: ForeignTypeIdentAlias = parse_quote! { #[cxx_qt::qobject(qml_version = "1.0")] - pub struct MyObject; + type MyObject = super::MyObjectRust; }; - assert!(ParsedQObject::from_struct(&item, 0).is_err()); + assert!(ParsedQObject::from_foreign_item_type(&item, 0).is_err()); } #[test] fn test_qml_metadata_only_name_no_version_no_uri() { - let item: ItemStruct = parse_quote! { + let item: ForeignTypeIdentAlias = parse_quote! { #[cxx_qt::qobject(qml_name = "MyQmlElement")] - pub struct MyObject; + type MyObject = super::MyObjectRust; }; - assert!(ParsedQObject::from_struct(&item, 0).is_err()); + assert!(ParsedQObject::from_foreign_item_type(&item, 0).is_err()); } } diff --git a/crates/cxx-qt-gen/src/syntax/foreignmod.rs b/crates/cxx-qt-gen/src/syntax/foreignmod.rs index c4b7f6b26..e57773fd9 100644 --- a/crates/cxx-qt-gen/src/syntax/foreignmod.rs +++ b/crates/cxx-qt-gen/src/syntax/foreignmod.rs @@ -6,10 +6,10 @@ use proc_macro2::{TokenStream, TokenTree}; use quote::{quote, ToTokens}; use syn::{ - parse::{ParseStream, Parser}, + parse::{Parse, ParseStream, Parser}, spanned::Spanned, - Attribute, Error, FnArg, ForeignItem, ForeignItemType, Ident, ItemForeignMod, Receiver, Result, - Signature, Token, Visibility, + Attribute, Error, FnArg, ForeignItem, ForeignItemType, Ident, ItemForeignMod, Path, Receiver, + Result, Signature, Token, Visibility, }; /// For a given [syn::ForeignItem] return the [syn::ForeignItemType] if there is one @@ -75,12 +75,97 @@ fn verbatim_to_foreign_type(tokens: &TokenStream) -> Result, + /// The left side of the alias + pub ident_left: Ident, + /// The right side of the alias + pub ident_right: Ident, +} + +impl Parse for ForeignTypeIdentAlias { + fn parse(input: ParseStream) -> Result { + let attrs = input.call(Attribute::parse_outer)?; + + // Note that visibility is ignored for now + let _: Visibility = input.parse()?; + + if input.peek(Token![type]) { + let _type_token: Token![type] = input.parse()?; + let ident_left: Ident = input.parse()?; + let _equals_token: Token![=] = input.parse()?; + let path: Path = input.parse()?; + let _semi_colon: Token![;] = input.parse()?; + + // Convert the path (super::T) to an ident (T) + let ident_right = { + // We only support super::T for now due to CXX only supporting type T with no alias + // as an extern "Rust" type. + // + // TODO: once CXX does have support for type aliases in extern "Rust" blocks + // we can instead pass through the full path of an ident_right. + // https://github.com/dtolnay/cxx/issues/1187 + // https://github.com/dtolnay/cxx/pull/1181 + // + // Note that we would need to still use the last segment as the Rust name internally + if path.segments.len() != 2 { + return Err(Error::new( + path.span(), + "Type alias path must have at exactly two segments, super::T", + )); + } + + if path.segments[0].ident != "super" { + return Err(Error::new( + path.span(), + "Type alias path must have super as the first segment, super::T", + )); + } + + path.segments[1].ident.clone() + }; + + if ident_left == ident_right { + return Err(Error::new( + path.span(), + "Type alias path must have differing idents, type A = super::B. A and B cannot be the same.", + )); + } + + Ok(Self { + attrs, + ident_left, + ident_right, + }) + } else { + // Error as we have parsed the attributes and visiblity but have an unknown stream + // + // To return None here we should instead peek + Err(Error::new( + input.span(), + "Unsupported verbatim input in ForeignItem", + )) + } + } +} + pub fn self_type_from_foreign_fn(signature: &Signature) -> Result { if let Some(FnArg::Receiver(receiver)) = signature.inputs.iter().next() { if !receiver.attrs.is_empty() { @@ -178,4 +263,59 @@ mod tests { // attribute on self type test! { fn foo(#[attr] self: T); } } + + #[test] + fn test_foreign_type_ident_alias() { + let alias = syn::parse2::(quote! { + #[attr] + type A = super::B; + }).unwrap(); + assert_eq!(alias.attrs.len(), 1); + assert_eq!(alias.ident_left, "A"); + assert_eq!(alias.ident_right, "B"); + } + + #[test] + fn test_foreign_type_ident_alias_segments_one() { + let parse = syn::parse2::(quote! { + type A = B; + }); + assert!(parse.is_err()); + } + + #[test] + fn test_foreign_type_ident_alias_segments_three() { + let parse = syn::parse2::(quote! { + type A = super::module::B; + }); + assert!(parse.is_err()); + } + + #[test] + fn test_foreign_type_ident_alias_no_super() { + let parse = syn::parse2::(quote! { + type A = crate::B; + }); + assert!(parse.is_err()); + } + + #[test] + fn test_foreign_type_ident_alias_left_is_right() { + let parse = syn::parse2::(quote! { + type A = super::A; + }); + assert!(parse.is_err()); + } + + #[test] + fn test_foreign_type_ident_visibility() { + // Ensure that visibility does not error, later it might be stored + let alias = syn::parse2::(quote! { + #[attr] + pub type A = super::B; + }).unwrap(); + assert_eq!(alias.attrs.len(), 1); + assert_eq!(alias.ident_left, "A"); + assert_eq!(alias.ident_right, "B"); + } } diff --git a/crates/cxx-qt-gen/src/writer/rust/mod.rs b/crates/cxx-qt-gen/src/writer/rust/mod.rs index 7d3e5a15f..3107cb1aa 100644 --- a/crates/cxx-qt-gen/src/writer/rust/mod.rs +++ b/crates/cxx-qt-gen/src/writer/rust/mod.rs @@ -109,16 +109,15 @@ pub fn write_rust(generated: &GeneratedRustBlocks) -> TokenStream { // Add the type alias to the C++ struct let cpp_struct_ident = &qobject.cpp_struct_ident; - let rust_struct_ident = &qobject.rust_struct_ident; - let rust_struct_ident_str = rust_struct_ident.to_string(); + let cpp_struct_ident_str = cpp_struct_ident.to_string(); qobject_types.push(quote! { #[doc = "The C++ type for the QObject "] - #[doc = #rust_struct_ident_str] + #[doc = #cpp_struct_ident_str] #[doc = "\n"] #[doc = "Use this type when referring to the QObject as a pointer"] #[doc = "\n"] #[doc = "See the book for more information: "] - pub type #rust_struct_ident = super::#cpp_struct_ident; + pub type #cpp_struct_ident = super::#cpp_struct_ident; }) } @@ -192,31 +191,29 @@ mod tests { }], namespace: "cxx_qt::my_object".to_owned(), qobjects: vec![GeneratedRustQObject { - cpp_struct_ident: format_ident!("MyObjectQt"), + cpp_struct_ident: format_ident!("MyObject"), namespace_internals: "cxx_qt::my_object::cxx_qt_my_object".to_owned(), - rust_struct_ident: format_ident!("MyObject"), + rust_struct_ident: format_ident!("MyObjectRust"), blocks: GeneratedRustQObjectBlocks { cxx_mod_contents: vec![ parse_quote! { unsafe extern "C++" { - #[cxx_name = "MyObject"] - type MyObjectQt; + type MyObject; } }, parse_quote! { extern "Rust" { - #[cxx_name = "MyObjectRust"] - type MyObject; + type MyObjectRust; } }, ], cxx_qt_mod_contents: vec![ parse_quote! { #[derive(Default)] - pub struct MyObject; + pub struct MyObjectRust; }, parse_quote! { - impl MyObject { + impl MyObjectRust { fn rust_method(&self) { } @@ -245,31 +242,29 @@ mod tests { namespace: "cxx_qt".to_owned(), qobjects: vec![ GeneratedRustQObject { - cpp_struct_ident: format_ident!("FirstObjectQt"), + cpp_struct_ident: format_ident!("FirstObject"), namespace_internals: "cxx_qt::cxx_qt_first_object".to_owned(), - rust_struct_ident: format_ident!("FirstObject"), + rust_struct_ident: format_ident!("FirstObjectRust"), blocks: GeneratedRustQObjectBlocks { cxx_mod_contents: vec![ parse_quote! { unsafe extern "C++" { - #[cxx_name = "FirstObject"] - type FirstObjectQt; + type FirstObject; } }, parse_quote! { extern "Rust" { - #[cxx_name = "FirstObjectRust"] - type FirstObject; + type FirstObjectRust; } }, ], cxx_qt_mod_contents: vec![ parse_quote! { #[derive(Default)] - pub struct FirstObject; + pub struct FirstObjectRust; }, parse_quote! { - impl FirstObject { + impl FirstObjectRust { fn rust_method(&self) { } @@ -279,31 +274,29 @@ mod tests { }, }, GeneratedRustQObject { - cpp_struct_ident: format_ident!("SecondObjectQt"), + cpp_struct_ident: format_ident!("SecondObject"), namespace_internals: "cxx_qt::cxx_qt_second_object".to_owned(), - rust_struct_ident: format_ident!("SecondObject"), + rust_struct_ident: format_ident!("SecondObjectRust"), blocks: GeneratedRustQObjectBlocks { cxx_mod_contents: vec![ parse_quote! { unsafe extern "C++" { - #[cxx_name = "SecondObject"] - type SecondObjectQt; + type SecondObject; } }, parse_quote! { extern "Rust" { - #[cxx_name = "SecondObjectRust"] - type SecondObject; + type SecondObjectRust; } }, ], cxx_qt_mod_contents: vec![ parse_quote! { #[derive(Default)] - pub struct SecondObject; + pub struct SecondObjectRust; }, parse_quote! { - impl SecondObject { + impl SecondObjectRust { fn rust_method(&self) { } @@ -342,25 +335,23 @@ mod tests { } unsafe extern "C++" { - #[cxx_name = "MyObject"] - type MyObjectQt; + type MyObject; } extern "Rust" { - #[cxx_name = "MyObjectRust"] - type MyObject; + type MyObjectRust; } unsafe extern "C++" { #[cxx_name = "unsafeRust"] #[doc(hidden)] - fn cxx_qt_ffi_rust(self: &MyObjectQt) -> &MyObject; + fn cxx_qt_ffi_rust(self: &MyObject) -> &MyObjectRust; } unsafe extern "C++" { #[cxx_name = "unsafeRustMut"] #[doc(hidden)] - fn cxx_qt_ffi_rust_mut(self: Pin<&mut MyObjectQt>) -> Pin<&mut MyObject>; + fn cxx_qt_ffi_rust_mut(self: Pin<&mut MyObject>) -> Pin<&mut MyObjectRust>; } } @@ -377,16 +368,16 @@ mod tests { use module::Struct; #[derive(Default)] - pub struct MyObject; + pub struct MyObjectRust; - impl MyObject { + impl MyObjectRust { fn rust_method(&self) { } } - impl cxx_qt::CxxQtType for MyObjectQt { - type Rust = MyObject; + impl cxx_qt::CxxQtType for MyObject { + type Rust = MyObjectRust; fn rust(&self) -> &Self::Rust { self.cxx_qt_ffi_rust() } @@ -403,7 +394,7 @@ mod tests { #[doc = "Use this type when referring to the QObject as a pointer"] #[doc = "\n"] #[doc = "See the book for more information: "] - pub type MyObject = super::MyObjectQt; + pub type MyObject = super::MyObject; } } } @@ -437,46 +428,42 @@ mod tests { } unsafe extern "C++" { - #[cxx_name = "FirstObject"] - type FirstObjectQt; + type FirstObject; } extern "Rust" { - #[cxx_name = "FirstObjectRust"] - type FirstObject; + type FirstObjectRust; } unsafe extern "C++" { #[cxx_name = "unsafeRust"] #[doc(hidden)] - fn cxx_qt_ffi_rust(self: &FirstObjectQt) -> &FirstObject; + fn cxx_qt_ffi_rust(self: &FirstObject) -> &FirstObjectRust; } unsafe extern "C++" { #[cxx_name = "unsafeRustMut"] #[doc(hidden)] - fn cxx_qt_ffi_rust_mut(self: Pin<&mut FirstObjectQt>) -> Pin<&mut FirstObject>; + fn cxx_qt_ffi_rust_mut(self: Pin<&mut FirstObject>) -> Pin<&mut FirstObjectRust>; } unsafe extern "C++" { - #[cxx_name = "SecondObject"] - type SecondObjectQt; + type SecondObject; } extern "Rust" { - #[cxx_name = "SecondObjectRust"] - type SecondObject; + type SecondObjectRust; } unsafe extern "C++" { #[cxx_name = "unsafeRust"] #[doc(hidden)] - fn cxx_qt_ffi_rust(self: &SecondObjectQt) -> &SecondObject; + fn cxx_qt_ffi_rust(self: &SecondObject) -> &SecondObjectRust; } unsafe extern "C++" { #[cxx_name = "unsafeRustMut"] #[doc(hidden)] - fn cxx_qt_ffi_rust_mut(self: Pin<&mut SecondObjectQt>) -> Pin<&mut SecondObject>; + fn cxx_qt_ffi_rust_mut(self: Pin<&mut SecondObject>) -> Pin<&mut SecondObjectRust>; } } @@ -493,16 +480,16 @@ mod tests { use module::Struct; #[derive(Default)] - pub struct FirstObject; + pub struct FirstObjectRust; - impl FirstObject { + impl FirstObjectRust { fn rust_method(&self) { } } - impl cxx_qt::CxxQtType for FirstObjectQt { - type Rust = FirstObject; + impl cxx_qt::CxxQtType for FirstObject { + type Rust = FirstObjectRust; fn rust(&self) -> &Self::Rust { self.cxx_qt_ffi_rust() } @@ -512,16 +499,16 @@ mod tests { } #[derive(Default)] - pub struct SecondObject; + pub struct SecondObjectRust; - impl SecondObject { + impl SecondObjectRust { fn rust_method(&self) { } } - impl cxx_qt::CxxQtType for SecondObjectQt { - type Rust = SecondObject; + impl cxx_qt::CxxQtType for SecondObject { + type Rust = SecondObjectRust; fn rust(&self) -> &Self::Rust { self.cxx_qt_ffi_rust() } @@ -538,14 +525,14 @@ mod tests { #[doc = "Use this type when referring to the QObject as a pointer"] #[doc = "\n"] #[doc = "See the book for more information: "] - pub type FirstObject = super::FirstObjectQt; + pub type FirstObject = super::FirstObject; #[doc = "The C++ type for the QObject "] #[doc = "SecondObject"] #[doc = "\n"] #[doc = "Use this type when referring to the QObject as a pointer"] #[doc = "\n"] #[doc = "See the book for more information: "] - pub type SecondObject = super::SecondObjectQt; + pub type SecondObject = super::SecondObject; } } } diff --git a/crates/cxx-qt-gen/test_inputs/inheritance.rs b/crates/cxx-qt-gen/test_inputs/inheritance.rs index 54fbb9299..7bb1c3c50 100644 --- a/crates/cxx-qt-gen/test_inputs/inheritance.rs +++ b/crates/cxx-qt-gen/test_inputs/inheritance.rs @@ -7,10 +7,9 @@ mod inheritance { type QVariant = cxx_qt_lib::QVariant; } - #[cxx_qt::qobject(base = "QAbstractItemModel")] - #[derive(Default)] - pub struct MyObject { - data: Vec, + extern "RustQt" { + #[cxx_qt::qobject(base = "QAbstractItemModel")] + type MyObject = super::MyObjectRust; } unsafe extern "RustQt" { diff --git a/crates/cxx-qt-gen/test_inputs/invokables.rs b/crates/cxx-qt-gen/test_inputs/invokables.rs index 79f2ad550..672a8a986 100644 --- a/crates/cxx-qt-gen/test_inputs/invokables.rs +++ b/crates/cxx-qt-gen/test_inputs/invokables.rs @@ -8,11 +8,10 @@ mod ffi { type QPoint = cxx_qt_lib::QPoint; } - #[cxx_qt::qobject] - #[derive(Default)] - pub struct MyObject; - unsafe extern "RustQt" { + #[cxx_qt::qobject] + type MyObject = super::MyObjectRust; + #[qinvokable] fn invokable(self: &qobject::MyObject); diff --git a/crates/cxx-qt-gen/test_inputs/passthrough_and_naming.rs b/crates/cxx-qt-gen/test_inputs/passthrough_and_naming.rs index d6d44d6cf..8bf9c1cca 100644 --- a/crates/cxx-qt-gen/test_inputs/passthrough_and_naming.rs +++ b/crates/cxx-qt-gen/test_inputs/passthrough_and_naming.rs @@ -79,10 +79,10 @@ pub mod ffi { include!(); } - #[cxx_qt::qobject(base = "QStringListModel")] - #[qproperty(i32, property_name)] - pub struct MyObject { - property_name: i32, + extern "RustQt" { + #[cxx_qt::qobject(base = "QStringListModel")] + #[qproperty(i32, property_name)] + type MyObject = super::MyObjectRust; } unsafe extern "RustQt" { @@ -99,10 +99,10 @@ pub mod ffi { } } - #[cxx_qt::qobject] - #[qproperty(i32, property_name)] - pub struct SecondObject { - property_name: i32, + extern "RustQt" { + #[cxx_qt::qobject] + #[qproperty(i32, property_name)] + type SecondObject = super::SecondObjectRust; } unsafe impl !cxx_qt::Locking for qobject::SecondObject {} diff --git a/crates/cxx-qt-gen/test_inputs/properties.rs b/crates/cxx-qt-gen/test_inputs/properties.rs index be22f0346..9943a1e81 100644 --- a/crates/cxx-qt-gen/test_inputs/properties.rs +++ b/crates/cxx-qt-gen/test_inputs/properties.rs @@ -6,16 +6,11 @@ mod ffi { type QPoint = cxx_qt_lib::QPoint; } - #[cxx_qt::qobject] - #[derive(Default)] - #[qproperty(i32, primitive)] - #[qproperty(QPoint, trivial)] - pub struct MyObject { - primitive: i32, - trivial: QPoint, - opaque: UniquePtr, - - private_rust_field: i32, - pub public_rust_field: f64, + extern "RustQt" { + #[cxx_qt::qobject] + #[derive(Default)] + #[qproperty(i32, primitive)] + #[qproperty(QPoint, trivial)] + type MyObject = super::MyObjectRust; } } diff --git a/crates/cxx-qt-gen/test_inputs/signals.rs b/crates/cxx-qt-gen/test_inputs/signals.rs index a8f5ae709..b0746b476 100644 --- a/crates/cxx-qt-gen/test_inputs/signals.rs +++ b/crates/cxx-qt-gen/test_inputs/signals.rs @@ -7,6 +7,9 @@ mod ffi { } unsafe extern "RustQt" { + #[cxx_qt::qobject] + type MyObject = super::MyObjectRust; + #[qsignal] fn ready(self: Pin<&mut qobject::MyObject>); @@ -33,8 +36,4 @@ mod ffi { #[qinvokable] fn invokable(self: Pin<&mut qobject::MyObject>); } - - #[cxx_qt::qobject] - #[derive(Default)] - pub struct MyObject; } diff --git a/crates/cxx-qt-gen/test_outputs/inheritance.rs b/crates/cxx-qt-gen/test_outputs/inheritance.rs index 8eefa6c0b..1a7da815e 100644 --- a/crates/cxx-qt-gen/test_outputs/inheritance.rs +++ b/crates/cxx-qt-gen/test_outputs/inheritance.rs @@ -24,55 +24,54 @@ mod inheritance { } unsafe extern "C++" { #[doc = "The C++ type for the QObject "] - #[doc = "MyObject"] + #[doc = "MyObjectRust"] #[doc = "\n"] #[doc = "Use this type when referring to the QObject as a pointer"] #[doc = "\n"] #[doc = "See the book for more information: "] - #[cxx_name = "MyObject"] - type MyObjectQt; + type MyObject; } extern "Rust" { - #[cxx_name = "MyObjectRust"] - type MyObject; + type MyObjectRust; } extern "Rust" { #[cxx_name = "dataWrapper"] fn data_wrapper( - self: &MyObject, - cpp: &MyObjectQt, + self: &MyObjectRust, + cpp: &MyObject, _index: &QModelIndex, _role: i32, ) -> QVariant; } extern "Rust" { #[cxx_name = "hasChildrenWrapper"] - fn has_children_wrapper(self: &MyObject, cpp: &MyObjectQt, _parent: &QModelIndex) -> bool; + fn has_children_wrapper(self: &MyObjectRust, cpp: &MyObject, _parent: &QModelIndex) + -> bool; } unsafe extern "C++" { #[doc = " Inherited hasChildren from the base class"] #[cxx_name = "hasChildrenCxxQtInherit"] - fn has_children_super(self: &MyObjectQt, parent: &QModelIndex) -> bool; + fn has_children_super(self: &MyObject, parent: &QModelIndex) -> bool; } extern "C++" { #[doc = " Inherited fetchMore from the base class"] #[cxx_name = "fetchMoreCxxQtInherit"] - unsafe fn fetch_more(self: Pin<&mut MyObjectQt>, index: &QModelIndex); + unsafe fn fetch_more(self: Pin<&mut MyObject>, index: &QModelIndex); } extern "Rust" { #[cxx_name = "createRs"] #[namespace = "cxx_qt_my_object"] - fn create_rs_my_object() -> Box; + fn create_rs_my_object_rust() -> Box; } unsafe extern "C++" { #[cxx_name = "unsafeRust"] #[doc(hidden)] - fn cxx_qt_ffi_rust(self: &MyObjectQt) -> &MyObject; + fn cxx_qt_ffi_rust(self: &MyObject) -> &MyObjectRust; } unsafe extern "C++" { #[cxx_name = "unsafeRustMut"] #[doc(hidden)] - fn cxx_qt_ffi_rust_mut(self: Pin<&mut MyObjectQt>) -> Pin<&mut MyObject>; + fn cxx_qt_ffi_rust_mut(self: Pin<&mut MyObject>) -> Pin<&mut MyObjectRust>; } } use self::cxx_qt_inheritance::*; @@ -83,38 +82,35 @@ pub mod cxx_qt_inheritance { use std::pin::Pin; #[doc(hidden)] type UniquePtr = cxx::UniquePtr; - #[derive(Default)] - pub struct MyObject { - data: Vec, - } - impl MyObject { + type MyObjectRust = super::MyObjectRust; + impl MyObjectRust { #[doc(hidden)] pub fn data_wrapper( - self: &MyObject, - cpp: &MyObjectQt, + self: &MyObjectRust, + cpp: &MyObject, _index: &QModelIndex, _role: i32, ) -> QVariant { return cpp.data(_index, _role); } } - impl MyObject { + impl MyObjectRust { #[doc(hidden)] pub fn has_children_wrapper( - self: &MyObject, - cpp: &MyObjectQt, + self: &MyObjectRust, + cpp: &MyObject, _parent: &QModelIndex, ) -> bool { return cpp.has_children(_parent); } } - impl cxx_qt::Locking for MyObjectQt {} + impl cxx_qt::Locking for MyObject {} #[doc = r" Generated CXX-Qt method which creates a boxed rust struct of a QObject"] - pub fn create_rs_my_object() -> std::boxed::Box { + pub fn create_rs_my_object_rust() -> std::boxed::Box { core::default::Default::default() } - impl cxx_qt::CxxQtType for MyObjectQt { - type Rust = MyObject; + impl cxx_qt::CxxQtType for MyObject { + type Rust = MyObjectRust; fn rust(&self) -> &Self::Rust { self.cxx_qt_ffi_rust() } @@ -130,6 +126,6 @@ pub mod cxx_qt_inheritance { #[doc = "Use this type when referring to the QObject as a pointer"] #[doc = "\n"] #[doc = "See the book for more information: "] - pub type MyObject = super::MyObjectQt; + pub type MyObject = super::MyObject; } } diff --git a/crates/cxx-qt-gen/test_outputs/invokables.rs b/crates/cxx-qt-gen/test_outputs/invokables.rs index df6d19ce9..0f227d078 100644 --- a/crates/cxx-qt-gen/test_outputs/invokables.rs +++ b/crates/cxx-qt-gen/test_outputs/invokables.rs @@ -25,31 +25,29 @@ mod ffi { } unsafe extern "C++" { #[doc = "The C++ type for the QObject "] - #[doc = "MyObject"] + #[doc = "MyObjectRust"] #[doc = "\n"] #[doc = "Use this type when referring to the QObject as a pointer"] #[doc = "\n"] #[doc = "See the book for more information: "] - #[cxx_name = "MyObject"] - type MyObjectQt; + type MyObject; } extern "Rust" { - #[cxx_name = "MyObjectRust"] - type MyObject; + type MyObjectRust; } extern "Rust" { #[cxx_name = "invokableWrapper"] - fn invokable_wrapper(self: &MyObject, cpp: &MyObjectQt); + fn invokable_wrapper(self: &MyObjectRust, cpp: &MyObject); } extern "Rust" { #[cxx_name = "invokableMutableWrapper"] - fn invokable_mutable_wrapper(self: &mut MyObject, cpp: Pin<&mut MyObjectQt>); + fn invokable_mutable_wrapper(self: &mut MyObjectRust, cpp: Pin<&mut MyObject>); } extern "Rust" { #[cxx_name = "invokableParametersWrapper"] fn invokable_parameters_wrapper( - self: &MyObject, - cpp: &MyObjectQt, + self: &MyObjectRust, + cpp: &MyObject, opaque: &QColor, trivial: &QPoint, primitive: i32, @@ -58,42 +56,42 @@ mod ffi { extern "Rust" { #[cxx_name = "invokableReturnOpaqueWrapper"] fn invokable_return_opaque_wrapper( - self: &mut MyObject, - cpp: Pin<&mut MyObjectQt>, + self: &mut MyObjectRust, + cpp: Pin<&mut MyObject>, ) -> UniquePtr; } extern "Rust" { #[cxx_name = "invokableReturnTrivialWrapper"] fn invokable_return_trivial_wrapper( - self: &mut MyObject, - cpp: Pin<&mut MyObjectQt>, + self: &mut MyObjectRust, + cpp: Pin<&mut MyObject>, ) -> QPoint; } extern "Rust" { #[cxx_name = "invokableFinalWrapper"] - fn invokable_final_wrapper(self: &MyObject, cpp: &MyObjectQt); + fn invokable_final_wrapper(self: &MyObjectRust, cpp: &MyObject); } extern "Rust" { #[cxx_name = "invokableOverrideWrapper"] - fn invokable_override_wrapper(self: &MyObject, cpp: &MyObjectQt); + fn invokable_override_wrapper(self: &MyObjectRust, cpp: &MyObject); } extern "Rust" { #[cxx_name = "invokableVirtualWrapper"] - fn invokable_virtual_wrapper(self: &MyObject, cpp: &MyObjectQt); + fn invokable_virtual_wrapper(self: &MyObjectRust, cpp: &MyObject); } unsafe extern "C++" { #[doc(hidden)] - type MyObjectCxxQtThread = cxx_qt::CxxQtThread; + type MyObjectCxxQtThread = cxx_qt::CxxQtThread; include!("cxx-qt-common/cxxqt_thread.h"); #[doc(hidden)] #[cxx_name = "qtThread"] - fn cxx_qt_ffi_qt_thread(self: &MyObjectQt) -> MyObjectCxxQtThread; + fn cxx_qt_ffi_qt_thread(self: &MyObject) -> MyObjectCxxQtThread; #[doc(hidden)] #[namespace = "rust::cxxqtlib1"] #[cxx_name = "cxxQtThreadQueue"] fn cxx_qt_ffi_my_object_queue_boxed_fn( cxx_qt_thread: &MyObjectCxxQtThread, - func: fn(Pin<&mut MyObjectQt>, Box), + func: fn(Pin<&mut MyObject>, Box), arg: Box, ) -> Result<()>; #[doc(hidden)] @@ -114,55 +112,57 @@ mod ffi { #[namespace = "cxx_qt::my_object::cxx_qt_my_object"] #[cxx_name = "CxxQtConstructorArguments0"] #[doc(hidden)] - struct CxxQtConstructorArgumentsMyObject0 { - baseArguments: CxxQtConstructorBaseArgumentsMyObject0, - newArguments: CxxQtConstructorNewArgumentsMyObject0, - initializeArguments: CxxQtConstructorInitializeArgumentsMyObject0, + struct CxxQtConstructorArgumentsMyObjectRust0 { + baseArguments: CxxQtConstructorBaseArgumentsMyObjectRust0, + newArguments: CxxQtConstructorNewArgumentsMyObjectRust0, + initializeArguments: CxxQtConstructorInitializeArgumentsMyObjectRust0, } #[namespace = "cxx_qt::my_object::cxx_qt_my_object"] #[cxx_name = "CxxQtConstructorBaseArguments0"] #[doc(hidden)] - struct CxxQtConstructorBaseArgumentsMyObject0 { + struct CxxQtConstructorBaseArgumentsMyObjectRust0 { arg0: *mut QObject, } #[namespace = "cxx_qt::my_object::cxx_qt_my_object"] #[cxx_name = "CxxQtConstructorNewArguments0"] #[doc(hidden)] - struct CxxQtConstructorNewArgumentsMyObject0 { + struct CxxQtConstructorNewArgumentsMyObjectRust0 { arg0: i32, } #[namespace = "cxx_qt::my_object::cxx_qt_my_object"] #[cxx_name = "CxxQtConstructorInitializeArguments0"] #[doc(hidden)] - struct CxxQtConstructorInitializeArgumentsMyObject0 { + struct CxxQtConstructorInitializeArgumentsMyObjectRust0 { not_empty: i8, } extern "Rust" { #[namespace = "cxx_qt::my_object::cxx_qt_my_object"] #[cxx_name = "routeArguments0"] - unsafe fn route_arguments_my_object_0( + unsafe fn route_arguments_my_object_rust_0( arg0: i32, arg1: *mut QObject, - ) -> CxxQtConstructorArgumentsMyObject0; + ) -> CxxQtConstructorArgumentsMyObjectRust0; #[namespace = "cxx_qt::my_object::cxx_qt_my_object"] #[cxx_name = "newRs0"] - fn new_rs_my_object_0(args: CxxQtConstructorNewArgumentsMyObject0) -> Box; + fn new_rs_my_object_rust_0( + args: CxxQtConstructorNewArgumentsMyObjectRust0, + ) -> Box; #[namespace = "cxx_qt::my_object::cxx_qt_my_object"] #[cxx_name = "initialize0"] - fn initialize_my_object_0( - qobject: Pin<&mut MyObjectQt>, - args: CxxQtConstructorInitializeArgumentsMyObject0, + fn initialize_my_object_rust_0( + qobject: Pin<&mut MyObject>, + args: CxxQtConstructorInitializeArgumentsMyObjectRust0, ); } unsafe extern "C++" { #[cxx_name = "unsafeRust"] #[doc(hidden)] - fn cxx_qt_ffi_rust(self: &MyObjectQt) -> &MyObject; + fn cxx_qt_ffi_rust(self: &MyObject) -> &MyObjectRust; } unsafe extern "C++" { #[cxx_name = "unsafeRustMut"] #[doc(hidden)] - fn cxx_qt_ffi_rust_mut(self: Pin<&mut MyObjectQt>) -> Pin<&mut MyObject>; + fn cxx_qt_ffi_rust_mut(self: Pin<&mut MyObject>) -> Pin<&mut MyObjectRust>; } } use self::cxx_qt_ffi::*; @@ -173,25 +173,24 @@ pub mod cxx_qt_ffi { use std::pin::Pin; #[doc(hidden)] type UniquePtr = cxx::UniquePtr; - #[derive(Default)] - pub struct MyObject; - impl MyObject { + type MyObjectRust = super::MyObjectRust; + impl MyObjectRust { #[doc(hidden)] - pub fn invokable_wrapper(self: &MyObject, cpp: &MyObjectQt) { + pub fn invokable_wrapper(self: &MyObjectRust, cpp: &MyObject) { cpp.invokable(); } } - impl MyObject { + impl MyObjectRust { #[doc(hidden)] - pub fn invokable_mutable_wrapper(self: &mut MyObject, cpp: Pin<&mut MyObjectQt>) { + pub fn invokable_mutable_wrapper(self: &mut MyObjectRust, cpp: Pin<&mut MyObject>) { cpp.invokable_mutable(); } } - impl MyObject { + impl MyObjectRust { #[doc(hidden)] pub fn invokable_parameters_wrapper( - self: &MyObject, - cpp: &MyObjectQt, + self: &MyObjectRust, + cpp: &MyObject, opaque: &QColor, trivial: &QPoint, primitive: i32, @@ -199,43 +198,43 @@ pub mod cxx_qt_ffi { cpp.invokable_parameters(opaque, trivial, primitive); } } - impl MyObject { + impl MyObjectRust { #[doc(hidden)] pub fn invokable_return_opaque_wrapper( - self: &mut MyObject, - cpp: Pin<&mut MyObjectQt>, + self: &mut MyObjectRust, + cpp: Pin<&mut MyObject>, ) -> UniquePtr { return cpp.invokable_return_opaque(); } } - impl MyObject { + impl MyObjectRust { #[doc(hidden)] pub fn invokable_return_trivial_wrapper( - self: &mut MyObject, - cpp: Pin<&mut MyObjectQt>, + self: &mut MyObjectRust, + cpp: Pin<&mut MyObject>, ) -> QPoint { return cpp.invokable_return_trivial(); } } - impl MyObject { + impl MyObjectRust { #[doc(hidden)] - pub fn invokable_final_wrapper(self: &MyObject, cpp: &MyObjectQt) { + pub fn invokable_final_wrapper(self: &MyObjectRust, cpp: &MyObject) { cpp.invokable_final(); } } - impl MyObject { + impl MyObjectRust { #[doc(hidden)] - pub fn invokable_override_wrapper(self: &MyObject, cpp: &MyObjectQt) { + pub fn invokable_override_wrapper(self: &MyObjectRust, cpp: &MyObject) { cpp.invokable_override(); } } - impl MyObject { + impl MyObjectRust { #[doc(hidden)] - pub fn invokable_virtual_wrapper(self: &MyObject, cpp: &MyObjectQt) { + pub fn invokable_virtual_wrapper(self: &MyObjectRust, cpp: &MyObject) { cpp.invokable_virtual(); } } - impl cxx_qt::Threading for MyObjectQt { + impl cxx_qt::Threading for MyObject { type BoxedQueuedFn = MyObjectCxxQtThreadQueuedFn; type ThreadingTypeId = cxx::type_id!("cxx_qt::my_object::MyObjectCxxQtThread"); fn qt_thread(&self) -> MyObjectCxxQtThread { @@ -247,13 +246,13 @@ pub mod cxx_qt_ffi { f: F, ) -> std::result::Result<(), cxx::Exception> where - F: FnOnce(std::pin::Pin<&mut MyObjectQt>), + F: FnOnce(std::pin::Pin<&mut MyObject>), F: Send + 'static, { #[allow(clippy::boxed_local)] #[doc(hidden)] fn func( - obj: std::pin::Pin<&mut MyObjectQt>, + obj: std::pin::Pin<&mut MyObject>, arg: std::boxed::Box, ) { (arg.inner)(obj) @@ -274,54 +273,54 @@ pub mod cxx_qt_ffi { } #[doc(hidden)] pub struct MyObjectCxxQtThreadQueuedFn { - inner: std::boxed::Box) + Send>, + inner: std::boxed::Box) + Send>, } - impl cxx_qt::Locking for MyObjectQt {} + impl cxx_qt::Locking for MyObject {} #[doc(hidden)] - pub fn route_arguments_my_object_0( + pub fn route_arguments_my_object_rust_0( arg0: i32, arg1: *mut QObject, - ) -> CxxQtConstructorArgumentsMyObject0 { + ) -> CxxQtConstructorArgumentsMyObjectRust0 { #[allow(unused_variables)] #[allow(clippy::let_unit_value)] let (new_arguments, base_arguments, initialize_arguments) = - >::route_arguments((arg0, arg1)); - CxxQtConstructorArgumentsMyObject0 { - baseArguments: CxxQtConstructorBaseArgumentsMyObject0 { + >::route_arguments((arg0, arg1)); + CxxQtConstructorArgumentsMyObjectRust0 { + baseArguments: CxxQtConstructorBaseArgumentsMyObjectRust0 { arg0: base_arguments.0, }, - initializeArguments: CxxQtConstructorInitializeArgumentsMyObject0 { not_empty: 0 }, - newArguments: CxxQtConstructorNewArgumentsMyObject0 { + initializeArguments: CxxQtConstructorInitializeArgumentsMyObjectRust0 { not_empty: 0 }, + newArguments: CxxQtConstructorNewArgumentsMyObjectRust0 { arg0: new_arguments.0, }, } } #[doc(hidden)] #[allow(unused_variables)] - pub fn new_rs_my_object_0( - new_arguments: CxxQtConstructorNewArgumentsMyObject0, - ) -> std::boxed::Box { + pub fn new_rs_my_object_rust_0( + new_arguments: CxxQtConstructorNewArgumentsMyObjectRust0, + ) -> std::boxed::Box { #[allow(clippy::let_unit_value)] let new_arguments = (new_arguments.arg0,); - std::boxed::Box::new( - >::new(new_arguments), - ) + std::boxed::Box::new(>::new( + new_arguments, + )) } #[doc(hidden)] #[allow(unused_variables)] - pub fn initialize_my_object_0( - qobject: core::pin::Pin<&mut MyObjectQt>, - initialize_arguments: CxxQtConstructorInitializeArgumentsMyObject0, + pub fn initialize_my_object_rust_0( + qobject: core::pin::Pin<&mut MyObject>, + initialize_arguments: CxxQtConstructorInitializeArgumentsMyObjectRust0, ) { #[allow(clippy::let_unit_value)] let initialize_arguments = (); - >::initialize( + >::initialize( qobject, initialize_arguments, ) } - impl cxx_qt::CxxQtType for MyObjectQt { - type Rust = MyObject; + impl cxx_qt::CxxQtType for MyObject { + type Rust = MyObjectRust; fn rust(&self) -> &Self::Rust { self.cxx_qt_ffi_rust() } @@ -337,6 +336,6 @@ pub mod cxx_qt_ffi { #[doc = "Use this type when referring to the QObject as a pointer"] #[doc = "\n"] #[doc = "See the book for more information: "] - pub type MyObject = super::MyObjectQt; + pub type MyObject = super::MyObject; } } diff --git a/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs b/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs index ae9225a2d..4f4bd8bad 100644 --- a/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs +++ b/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs @@ -62,30 +62,28 @@ pub mod ffi { } unsafe extern "C++" { #[doc = "The C++ type for the QObject "] - #[doc = "MyObject"] + #[doc = "MyObjectRust"] #[doc = "\n"] #[doc = "Use this type when referring to the QObject as a pointer"] #[doc = "\n"] #[doc = "See the book for more information: "] - #[cxx_name = "MyObject"] - type MyObjectQt; + type MyObject; } extern "Rust" { - #[cxx_name = "MyObjectRust"] - type MyObject; + type MyObjectRust; } extern "Rust" { #[cxx_name = "getPropertyName"] - unsafe fn property_name<'a>(self: &'a MyObject, cpp: &'a MyObjectQt) -> &'a i32; + unsafe fn property_name<'a>(self: &'a MyObjectRust, cpp: &'a MyObject) -> &'a i32; } extern "Rust" { #[cxx_name = "setPropertyName"] - fn set_property_name(self: &mut MyObject, cpp: Pin<&mut MyObjectQt>, value: i32); + fn set_property_name(self: &mut MyObjectRust, cpp: Pin<&mut MyObject>, value: i32); } unsafe extern "C++" { #[doc = "Notify for the Q_PROPERTY"] #[rust_name = "property_name_changed"] - fn propertyNameChanged(self: Pin<&mut MyObjectQt>); + fn propertyNameChanged(self: Pin<&mut MyObject>); } unsafe extern "C++" { #[doc = "Connect the given function pointer to the signal "] @@ -94,18 +92,18 @@ pub mod ffi { #[must_use] #[rust_name = "connect_property_name_changed"] fn propertyNameChangedConnect( - self: Pin<&mut MyObjectQt>, - func: fn(Pin<&mut MyObjectQt>), + self: Pin<&mut MyObject>, + func: fn(Pin<&mut MyObject>), conn_type: CxxQtConnectionType, ) -> CxxQtQMetaObjectConnection; } extern "Rust" { #[cxx_name = "invokableNameWrapper"] - fn invokable_name_wrapper(self: &mut MyObject, cpp: Pin<&mut MyObjectQt>); + fn invokable_name_wrapper(self: &mut MyObjectRust, cpp: Pin<&mut MyObject>); } unsafe extern "C++" { #[rust_name = "ready"] - fn ready(self: Pin<&mut MyObjectQt>); + fn ready(self: Pin<&mut MyObject>); } unsafe extern "C++" { #[doc = "Connect the given function pointer to the signal "] @@ -114,52 +112,50 @@ pub mod ffi { #[must_use] #[rust_name = "connect_ready"] fn readyConnect( - self: Pin<&mut MyObjectQt>, - func: fn(Pin<&mut MyObjectQt>), + self: Pin<&mut MyObject>, + func: fn(Pin<&mut MyObject>), conn_type: CxxQtConnectionType, ) -> CxxQtQMetaObjectConnection; } extern "Rust" { #[cxx_name = "createRs"] #[namespace = "cxx_qt::multi_object::cxx_qt_my_object"] - fn create_rs_my_object() -> Box; + fn create_rs_my_object_rust() -> Box; } unsafe extern "C++" { #[cxx_name = "unsafeRust"] #[doc(hidden)] - fn cxx_qt_ffi_rust(self: &MyObjectQt) -> &MyObject; + fn cxx_qt_ffi_rust(self: &MyObject) -> &MyObjectRust; } unsafe extern "C++" { #[cxx_name = "unsafeRustMut"] #[doc(hidden)] - fn cxx_qt_ffi_rust_mut(self: Pin<&mut MyObjectQt>) -> Pin<&mut MyObject>; + fn cxx_qt_ffi_rust_mut(self: Pin<&mut MyObject>) -> Pin<&mut MyObjectRust>; } unsafe extern "C++" { #[doc = "The C++ type for the QObject "] - #[doc = "SecondObject"] + #[doc = "SecondObjectRust"] #[doc = "\n"] #[doc = "Use this type when referring to the QObject as a pointer"] #[doc = "\n"] #[doc = "See the book for more information: "] - #[cxx_name = "SecondObject"] - type SecondObjectQt; + type SecondObject; } extern "Rust" { - #[cxx_name = "SecondObjectRust"] - type SecondObject; + type SecondObjectRust; } extern "Rust" { #[cxx_name = "getPropertyName"] - unsafe fn property_name<'a>(self: &'a SecondObject, cpp: &'a SecondObjectQt) -> &'a i32; + unsafe fn property_name<'a>(self: &'a SecondObjectRust, cpp: &'a SecondObject) -> &'a i32; } extern "Rust" { #[cxx_name = "setPropertyName"] - fn set_property_name(self: &mut SecondObject, cpp: Pin<&mut SecondObjectQt>, value: i32); + fn set_property_name(self: &mut SecondObjectRust, cpp: Pin<&mut SecondObject>, value: i32); } unsafe extern "C++" { #[doc = "Notify for the Q_PROPERTY"] #[rust_name = "property_name_changed"] - fn propertyNameChanged(self: Pin<&mut SecondObjectQt>); + fn propertyNameChanged(self: Pin<&mut SecondObject>); } unsafe extern "C++" { #[doc = "Connect the given function pointer to the signal "] @@ -168,19 +164,19 @@ pub mod ffi { #[must_use] #[rust_name = "connect_property_name_changed"] fn propertyNameChangedConnect( - self: Pin<&mut SecondObjectQt>, - func: fn(Pin<&mut SecondObjectQt>), + self: Pin<&mut SecondObject>, + func: fn(Pin<&mut SecondObject>), conn_type: CxxQtConnectionType, ) -> CxxQtQMetaObjectConnection; } extern "Rust" { #[cxx_name = "invokableNameWrapper"] - fn invokable_name_wrapper(self: &mut SecondObject, cpp: Pin<&mut SecondObjectQt>); + fn invokable_name_wrapper(self: &mut SecondObjectRust, cpp: Pin<&mut SecondObject>); } unsafe extern "C++" { #[my_attribute] #[rust_name = "ready"] - fn ready(self: Pin<&mut SecondObjectQt>); + fn ready(self: Pin<&mut SecondObject>); } unsafe extern "C++" { #[doc = "Connect the given function pointer to the signal "] @@ -189,25 +185,25 @@ pub mod ffi { #[must_use] #[rust_name = "connect_ready"] fn readyConnect( - self: Pin<&mut SecondObjectQt>, - func: fn(Pin<&mut SecondObjectQt>), + self: Pin<&mut SecondObject>, + func: fn(Pin<&mut SecondObject>), conn_type: CxxQtConnectionType, ) -> CxxQtQMetaObjectConnection; } extern "Rust" { #[cxx_name = "createRs"] #[namespace = "cxx_qt::multi_object::cxx_qt_second_object"] - fn create_rs_second_object() -> Box; + fn create_rs_second_object_rust() -> Box; } unsafe extern "C++" { #[cxx_name = "unsafeRust"] #[doc(hidden)] - fn cxx_qt_ffi_rust(self: &SecondObjectQt) -> &SecondObject; + fn cxx_qt_ffi_rust(self: &SecondObject) -> &SecondObjectRust; } unsafe extern "C++" { #[cxx_name = "unsafeRustMut"] #[doc(hidden)] - fn cxx_qt_ffi_rust_mut(self: Pin<&mut SecondObjectQt>) -> Pin<&mut SecondObject>; + fn cxx_qt_ffi_rust_mut(self: Pin<&mut SecondObject>) -> Pin<&mut SecondObjectRust>; } } pub use self::cxx_qt_ffi::*; @@ -224,29 +220,27 @@ pub mod cxx_qt_ffi { "Hello".to_owned() } } - pub struct MyObject { - property_name: i32, - } - impl MyObject { + type MyObjectRust = super::MyObjectRust; + impl MyObjectRust { #[doc(hidden)] - pub fn property_name<'a>(&'a self, cpp: &'a MyObjectQt) -> &'a i32 { + pub fn property_name<'a>(&'a self, cpp: &'a MyObject) -> &'a i32 { cpp.property_name() } } - impl MyObjectQt { + impl MyObject { #[doc = "Getter for the Q_PROPERTY "] #[doc = "property_name"] pub fn property_name(&self) -> &i32 { &self.rust().property_name } } - impl MyObject { + impl MyObjectRust { #[doc(hidden)] - pub fn set_property_name(&mut self, cpp: Pin<&mut MyObjectQt>, value: i32) { + pub fn set_property_name(&mut self, cpp: Pin<&mut MyObject>, value: i32) { cpp.set_property_name(value); } } - impl MyObjectQt { + impl MyObject { #[doc = "Setter for the Q_PROPERTY "] #[doc = "property_name"] pub fn set_property_name(mut self: Pin<&mut Self>, value: i32) { @@ -257,7 +251,7 @@ pub mod cxx_qt_ffi { self.as_mut().property_name_changed(); } } - impl MyObjectQt { + impl MyObject { #[doc = "Connect the given function pointer to the signal "] #[doc = "propertyNameChanged"] #[doc = ", so that when the signal is emitted the function pointer is executed."] @@ -265,19 +259,19 @@ pub mod cxx_qt_ffi { #[doc = "Note that this method uses a AutoConnection connection type."] #[must_use] pub fn on_property_name_changed( - self: Pin<&mut MyObjectQt>, - func: fn(Pin<&mut MyObjectQt>), + self: Pin<&mut MyObject>, + func: fn(Pin<&mut MyObject>), ) -> CxxQtQMetaObjectConnection { self.connect_property_name_changed(func, CxxQtConnectionType::AutoConnection) } } - impl MyObject { + impl MyObjectRust { #[doc(hidden)] - pub fn invokable_name_wrapper(self: &mut MyObject, cpp: Pin<&mut MyObjectQt>) { + pub fn invokable_name_wrapper(self: &mut MyObjectRust, cpp: Pin<&mut MyObject>) { cpp.invokable_name(); } } - impl MyObjectQt { + impl MyObject { #[doc = "Connect the given function pointer to the signal "] #[doc = "ready"] #[doc = ", so that when the signal is emitted the function pointer is executed."] @@ -285,19 +279,19 @@ pub mod cxx_qt_ffi { #[doc = "Note that this method uses a AutoConnection connection type."] #[must_use] pub fn on_ready( - self: Pin<&mut MyObjectQt>, - func: fn(Pin<&mut MyObjectQt>), + self: Pin<&mut MyObject>, + func: fn(Pin<&mut MyObject>), ) -> CxxQtQMetaObjectConnection { self.connect_ready(func, CxxQtConnectionType::AutoConnection) } } - impl cxx_qt::Locking for MyObjectQt {} + impl cxx_qt::Locking for MyObject {} #[doc = r" Generated CXX-Qt method which creates a boxed rust struct of a QObject"] - pub fn create_rs_my_object() -> std::boxed::Box { + pub fn create_rs_my_object_rust() -> std::boxed::Box { core::default::Default::default() } - impl cxx_qt::CxxQtType for MyObjectQt { - type Rust = MyObject; + impl cxx_qt::CxxQtType for MyObject { + type Rust = MyObjectRust; fn rust(&self) -> &Self::Rust { self.cxx_qt_ffi_rust() } @@ -305,29 +299,27 @@ pub mod cxx_qt_ffi { self.cxx_qt_ffi_rust_mut() } } - pub struct SecondObject { - property_name: i32, - } - impl SecondObject { + type SecondObjectRust = super::SecondObjectRust; + impl SecondObjectRust { #[doc(hidden)] - pub fn property_name<'a>(&'a self, cpp: &'a SecondObjectQt) -> &'a i32 { + pub fn property_name<'a>(&'a self, cpp: &'a SecondObject) -> &'a i32 { cpp.property_name() } } - impl SecondObjectQt { + impl SecondObject { #[doc = "Getter for the Q_PROPERTY "] #[doc = "property_name"] pub fn property_name(&self) -> &i32 { &self.rust().property_name } } - impl SecondObject { + impl SecondObjectRust { #[doc(hidden)] - pub fn set_property_name(&mut self, cpp: Pin<&mut SecondObjectQt>, value: i32) { + pub fn set_property_name(&mut self, cpp: Pin<&mut SecondObject>, value: i32) { cpp.set_property_name(value); } } - impl SecondObjectQt { + impl SecondObject { #[doc = "Setter for the Q_PROPERTY "] #[doc = "property_name"] pub fn set_property_name(mut self: Pin<&mut Self>, value: i32) { @@ -338,7 +330,7 @@ pub mod cxx_qt_ffi { self.as_mut().property_name_changed(); } } - impl SecondObjectQt { + impl SecondObject { #[doc = "Connect the given function pointer to the signal "] #[doc = "propertyNameChanged"] #[doc = ", so that when the signal is emitted the function pointer is executed."] @@ -346,19 +338,19 @@ pub mod cxx_qt_ffi { #[doc = "Note that this method uses a AutoConnection connection type."] #[must_use] pub fn on_property_name_changed( - self: Pin<&mut SecondObjectQt>, - func: fn(Pin<&mut SecondObjectQt>), + self: Pin<&mut SecondObject>, + func: fn(Pin<&mut SecondObject>), ) -> CxxQtQMetaObjectConnection { self.connect_property_name_changed(func, CxxQtConnectionType::AutoConnection) } } - impl SecondObject { + impl SecondObjectRust { #[doc(hidden)] - pub fn invokable_name_wrapper(self: &mut SecondObject, cpp: Pin<&mut SecondObjectQt>) { + pub fn invokable_name_wrapper(self: &mut SecondObjectRust, cpp: Pin<&mut SecondObject>) { cpp.invokable_name(); } } - impl SecondObjectQt { + impl SecondObject { #[doc = "Connect the given function pointer to the signal "] #[doc = "ready"] #[doc = ", so that when the signal is emitted the function pointer is executed."] @@ -366,18 +358,18 @@ pub mod cxx_qt_ffi { #[doc = "Note that this method uses a AutoConnection connection type."] #[must_use] pub fn on_ready( - self: Pin<&mut SecondObjectQt>, - func: fn(Pin<&mut SecondObjectQt>), + self: Pin<&mut SecondObject>, + func: fn(Pin<&mut SecondObject>), ) -> CxxQtQMetaObjectConnection { self.connect_ready(func, CxxQtConnectionType::AutoConnection) } } #[doc = r" Generated CXX-Qt method which creates a boxed rust struct of a QObject"] - pub fn create_rs_second_object() -> std::boxed::Box { + pub fn create_rs_second_object_rust() -> std::boxed::Box { core::default::Default::default() } - impl cxx_qt::CxxQtType for SecondObjectQt { - type Rust = SecondObject; + impl cxx_qt::CxxQtType for SecondObject { + type Rust = SecondObjectRust; fn rust(&self) -> &Self::Rust { self.cxx_qt_ffi_rust() } @@ -393,13 +385,13 @@ pub mod cxx_qt_ffi { #[doc = "Use this type when referring to the QObject as a pointer"] #[doc = "\n"] #[doc = "See the book for more information: "] - pub type MyObject = super::MyObjectQt; + pub type MyObject = super::MyObject; #[doc = "The C++ type for the QObject "] #[doc = "SecondObject"] #[doc = "\n"] #[doc = "Use this type when referring to the QObject as a pointer"] #[doc = "\n"] #[doc = "See the book for more information: "] - pub type SecondObject = super::SecondObjectQt; + pub type SecondObject = super::SecondObject; } } diff --git a/crates/cxx-qt-gen/test_outputs/properties.rs b/crates/cxx-qt-gen/test_outputs/properties.rs index fa84bf3a1..0671ab2f6 100644 --- a/crates/cxx-qt-gen/test_outputs/properties.rs +++ b/crates/cxx-qt-gen/test_outputs/properties.rs @@ -23,38 +23,36 @@ mod ffi { } unsafe extern "C++" { #[doc = "The C++ type for the QObject "] - #[doc = "MyObject"] + #[doc = "MyObjectRust"] #[doc = "\n"] #[doc = "Use this type when referring to the QObject as a pointer"] #[doc = "\n"] #[doc = "See the book for more information: "] - #[cxx_name = "MyObject"] - type MyObjectQt; + type MyObject; } extern "Rust" { - #[cxx_name = "MyObjectRust"] - type MyObject; + type MyObjectRust; } extern "Rust" { #[cxx_name = "getPrimitive"] - unsafe fn primitive<'a>(self: &'a MyObject, cpp: &'a MyObjectQt) -> &'a i32; + unsafe fn primitive<'a>(self: &'a MyObjectRust, cpp: &'a MyObject) -> &'a i32; } extern "Rust" { #[cxx_name = "setPrimitive"] - fn set_primitive(self: &mut MyObject, cpp: Pin<&mut MyObjectQt>, value: i32); + fn set_primitive(self: &mut MyObjectRust, cpp: Pin<&mut MyObject>, value: i32); } extern "Rust" { #[cxx_name = "getTrivial"] - unsafe fn trivial<'a>(self: &'a MyObject, cpp: &'a MyObjectQt) -> &'a QPoint; + unsafe fn trivial<'a>(self: &'a MyObjectRust, cpp: &'a MyObject) -> &'a QPoint; } extern "Rust" { #[cxx_name = "setTrivial"] - fn set_trivial(self: &mut MyObject, cpp: Pin<&mut MyObjectQt>, value: QPoint); + fn set_trivial(self: &mut MyObjectRust, cpp: Pin<&mut MyObject>, value: QPoint); } unsafe extern "C++" { #[doc = "Notify for the Q_PROPERTY"] #[rust_name = "primitive_changed"] - fn primitiveChanged(self: Pin<&mut MyObjectQt>); + fn primitiveChanged(self: Pin<&mut MyObject>); } unsafe extern "C++" { #[doc = "Connect the given function pointer to the signal "] @@ -63,15 +61,15 @@ mod ffi { #[must_use] #[rust_name = "connect_primitive_changed"] fn primitiveChangedConnect( - self: Pin<&mut MyObjectQt>, - func: fn(Pin<&mut MyObjectQt>), + self: Pin<&mut MyObject>, + func: fn(Pin<&mut MyObject>), conn_type: CxxQtConnectionType, ) -> CxxQtQMetaObjectConnection; } unsafe extern "C++" { #[doc = "Notify for the Q_PROPERTY"] #[rust_name = "trivial_changed"] - fn trivialChanged(self: Pin<&mut MyObjectQt>); + fn trivialChanged(self: Pin<&mut MyObject>); } unsafe extern "C++" { #[doc = "Connect the given function pointer to the signal "] @@ -80,25 +78,25 @@ mod ffi { #[must_use] #[rust_name = "connect_trivial_changed"] fn trivialChangedConnect( - self: Pin<&mut MyObjectQt>, - func: fn(Pin<&mut MyObjectQt>), + self: Pin<&mut MyObject>, + func: fn(Pin<&mut MyObject>), conn_type: CxxQtConnectionType, ) -> CxxQtQMetaObjectConnection; } extern "Rust" { #[cxx_name = "createRs"] #[namespace = "cxx_qt::my_object::cxx_qt_my_object"] - fn create_rs_my_object() -> Box; + fn create_rs_my_object_rust() -> Box; } unsafe extern "C++" { #[cxx_name = "unsafeRust"] #[doc(hidden)] - fn cxx_qt_ffi_rust(self: &MyObjectQt) -> &MyObject; + fn cxx_qt_ffi_rust(self: &MyObject) -> &MyObjectRust; } unsafe extern "C++" { #[cxx_name = "unsafeRustMut"] #[doc(hidden)] - fn cxx_qt_ffi_rust_mut(self: Pin<&mut MyObjectQt>) -> Pin<&mut MyObject>; + fn cxx_qt_ffi_rust_mut(self: Pin<&mut MyObject>) -> Pin<&mut MyObjectRust>; } } use self::cxx_qt_ffi::*; @@ -109,34 +107,27 @@ pub mod cxx_qt_ffi { use std::pin::Pin; #[doc(hidden)] type UniquePtr = cxx::UniquePtr; - #[derive(Default)] - pub struct MyObject { - primitive: i32, - trivial: QPoint, - opaque: UniquePtr, - private_rust_field: i32, - pub public_rust_field: f64, - } - impl MyObject { + type MyObjectRust = super::MyObjectRust; + impl MyObjectRust { #[doc(hidden)] - pub fn primitive<'a>(&'a self, cpp: &'a MyObjectQt) -> &'a i32 { + pub fn primitive<'a>(&'a self, cpp: &'a MyObject) -> &'a i32 { cpp.primitive() } } - impl MyObjectQt { + impl MyObject { #[doc = "Getter for the Q_PROPERTY "] #[doc = "primitive"] pub fn primitive(&self) -> &i32 { &self.rust().primitive } } - impl MyObject { + impl MyObjectRust { #[doc(hidden)] - pub fn set_primitive(&mut self, cpp: Pin<&mut MyObjectQt>, value: i32) { + pub fn set_primitive(&mut self, cpp: Pin<&mut MyObject>, value: i32) { cpp.set_primitive(value); } } - impl MyObjectQt { + impl MyObject { #[doc = "Setter for the Q_PROPERTY "] #[doc = "primitive"] pub fn set_primitive(mut self: Pin<&mut Self>, value: i32) { @@ -147,26 +138,26 @@ pub mod cxx_qt_ffi { self.as_mut().primitive_changed(); } } - impl MyObject { + impl MyObjectRust { #[doc(hidden)] - pub fn trivial<'a>(&'a self, cpp: &'a MyObjectQt) -> &'a QPoint { + pub fn trivial<'a>(&'a self, cpp: &'a MyObject) -> &'a QPoint { cpp.trivial() } } - impl MyObjectQt { + impl MyObject { #[doc = "Getter for the Q_PROPERTY "] #[doc = "trivial"] pub fn trivial(&self) -> &QPoint { &self.rust().trivial } } - impl MyObject { + impl MyObjectRust { #[doc(hidden)] - pub fn set_trivial(&mut self, cpp: Pin<&mut MyObjectQt>, value: QPoint) { + pub fn set_trivial(&mut self, cpp: Pin<&mut MyObject>, value: QPoint) { cpp.set_trivial(value); } } - impl MyObjectQt { + impl MyObject { #[doc = "Setter for the Q_PROPERTY "] #[doc = "trivial"] pub fn set_trivial(mut self: Pin<&mut Self>, value: QPoint) { @@ -177,7 +168,7 @@ pub mod cxx_qt_ffi { self.as_mut().trivial_changed(); } } - impl MyObjectQt { + impl MyObject { #[doc = "Connect the given function pointer to the signal "] #[doc = "primitiveChanged"] #[doc = ", so that when the signal is emitted the function pointer is executed."] @@ -185,13 +176,13 @@ pub mod cxx_qt_ffi { #[doc = "Note that this method uses a AutoConnection connection type."] #[must_use] pub fn on_primitive_changed( - self: Pin<&mut MyObjectQt>, - func: fn(Pin<&mut MyObjectQt>), + self: Pin<&mut MyObject>, + func: fn(Pin<&mut MyObject>), ) -> CxxQtQMetaObjectConnection { self.connect_primitive_changed(func, CxxQtConnectionType::AutoConnection) } } - impl MyObjectQt { + impl MyObject { #[doc = "Connect the given function pointer to the signal "] #[doc = "trivialChanged"] #[doc = ", so that when the signal is emitted the function pointer is executed."] @@ -199,19 +190,19 @@ pub mod cxx_qt_ffi { #[doc = "Note that this method uses a AutoConnection connection type."] #[must_use] pub fn on_trivial_changed( - self: Pin<&mut MyObjectQt>, - func: fn(Pin<&mut MyObjectQt>), + self: Pin<&mut MyObject>, + func: fn(Pin<&mut MyObject>), ) -> CxxQtQMetaObjectConnection { self.connect_trivial_changed(func, CxxQtConnectionType::AutoConnection) } } - impl cxx_qt::Locking for MyObjectQt {} + impl cxx_qt::Locking for MyObject {} #[doc = r" Generated CXX-Qt method which creates a boxed rust struct of a QObject"] - pub fn create_rs_my_object() -> std::boxed::Box { + pub fn create_rs_my_object_rust() -> std::boxed::Box { core::default::Default::default() } - impl cxx_qt::CxxQtType for MyObjectQt { - type Rust = MyObject; + impl cxx_qt::CxxQtType for MyObject { + type Rust = MyObjectRust; fn rust(&self) -> &Self::Rust { self.cxx_qt_ffi_rust() } @@ -227,6 +218,6 @@ pub mod cxx_qt_ffi { #[doc = "Use this type when referring to the QObject as a pointer"] #[doc = "\n"] #[doc = "See the book for more information: "] - pub type MyObject = super::MyObjectQt; + pub type MyObject = super::MyObject; } } diff --git a/crates/cxx-qt-gen/test_outputs/signals.rs b/crates/cxx-qt-gen/test_outputs/signals.rs index 318757974..d64c620cf 100644 --- a/crates/cxx-qt-gen/test_outputs/signals.rs +++ b/crates/cxx-qt-gen/test_outputs/signals.rs @@ -23,25 +23,23 @@ mod ffi { } unsafe extern "C++" { #[doc = "The C++ type for the QObject "] - #[doc = "MyObject"] + #[doc = "MyObjectRust"] #[doc = "\n"] #[doc = "Use this type when referring to the QObject as a pointer"] #[doc = "\n"] #[doc = "See the book for more information: "] - #[cxx_name = "MyObject"] - type MyObjectQt; + type MyObject; } extern "Rust" { - #[cxx_name = "MyObjectRust"] - type MyObject; + type MyObjectRust; } extern "Rust" { #[cxx_name = "invokableWrapper"] - fn invokable_wrapper(self: &mut MyObject, cpp: Pin<&mut MyObjectQt>); + fn invokable_wrapper(self: &mut MyObjectRust, cpp: Pin<&mut MyObject>); } unsafe extern "C++" { #[rust_name = "ready"] - fn ready(self: Pin<&mut MyObjectQt>); + fn ready(self: Pin<&mut MyObject>); } unsafe extern "C++" { #[doc = "Connect the given function pointer to the signal "] @@ -50,15 +48,15 @@ mod ffi { #[must_use] #[rust_name = "connect_ready"] fn readyConnect( - self: Pin<&mut MyObjectQt>, - func: fn(Pin<&mut MyObjectQt>), + self: Pin<&mut MyObject>, + func: fn(Pin<&mut MyObject>), conn_type: CxxQtConnectionType, ) -> CxxQtQMetaObjectConnection; } unsafe extern "C++" { #[rust_name = "data_changed"] fn dataChanged( - self: Pin<&mut MyObjectQt>, + self: Pin<&mut MyObject>, first: i32, second: UniquePtr, third: QPoint, @@ -72,9 +70,9 @@ mod ffi { #[must_use] #[rust_name = "connect_data_changed"] fn dataChangedConnect( - self: Pin<&mut MyObjectQt>, + self: Pin<&mut MyObject>, func: fn( - Pin<&mut MyObjectQt>, + Pin<&mut MyObject>, first: i32, second: UniquePtr, third: QPoint, @@ -86,7 +84,7 @@ mod ffi { unsafe extern "C++" { #[rust_name = "base_class_new_data"] fn newData( - self: Pin<&mut MyObjectQt>, + self: Pin<&mut MyObject>, first: i32, second: UniquePtr, third: QPoint, @@ -100,9 +98,9 @@ mod ffi { #[must_use] #[rust_name = "connect_base_class_new_data"] fn newDataConnect( - self: Pin<&mut MyObjectQt>, + self: Pin<&mut MyObject>, func: fn( - Pin<&mut MyObjectQt>, + Pin<&mut MyObject>, first: i32, second: UniquePtr, third: QPoint, @@ -114,17 +112,17 @@ mod ffi { extern "Rust" { #[cxx_name = "createRs"] #[namespace = "cxx_qt::my_object::cxx_qt_my_object"] - fn create_rs_my_object() -> Box; + fn create_rs_my_object_rust() -> Box; } unsafe extern "C++" { #[cxx_name = "unsafeRust"] #[doc(hidden)] - fn cxx_qt_ffi_rust(self: &MyObjectQt) -> &MyObject; + fn cxx_qt_ffi_rust(self: &MyObject) -> &MyObjectRust; } unsafe extern "C++" { #[cxx_name = "unsafeRustMut"] #[doc(hidden)] - fn cxx_qt_ffi_rust_mut(self: Pin<&mut MyObjectQt>) -> Pin<&mut MyObject>; + fn cxx_qt_ffi_rust_mut(self: Pin<&mut MyObject>) -> Pin<&mut MyObjectRust>; } } use self::cxx_qt_ffi::*; @@ -135,15 +133,14 @@ pub mod cxx_qt_ffi { use std::pin::Pin; #[doc(hidden)] type UniquePtr = cxx::UniquePtr; - #[derive(Default)] - pub struct MyObject; - impl MyObject { + type MyObjectRust = super::MyObjectRust; + impl MyObjectRust { #[doc(hidden)] - pub fn invokable_wrapper(self: &mut MyObject, cpp: Pin<&mut MyObjectQt>) { + pub fn invokable_wrapper(self: &mut MyObjectRust, cpp: Pin<&mut MyObject>) { cpp.invokable(); } } - impl MyObjectQt { + impl MyObject { #[doc = "Connect the given function pointer to the signal "] #[doc = "ready"] #[doc = ", so that when the signal is emitted the function pointer is executed."] @@ -151,13 +148,13 @@ pub mod cxx_qt_ffi { #[doc = "Note that this method uses a AutoConnection connection type."] #[must_use] pub fn on_ready( - self: Pin<&mut MyObjectQt>, - func: fn(Pin<&mut MyObjectQt>), + self: Pin<&mut MyObject>, + func: fn(Pin<&mut MyObject>), ) -> CxxQtQMetaObjectConnection { self.connect_ready(func, CxxQtConnectionType::AutoConnection) } } - impl MyObjectQt { + impl MyObject { #[doc = "Connect the given function pointer to the signal "] #[doc = "dataChanged"] #[doc = ", so that when the signal is emitted the function pointer is executed."] @@ -165,9 +162,9 @@ pub mod cxx_qt_ffi { #[doc = "Note that this method uses a AutoConnection connection type."] #[must_use] pub fn on_data_changed( - self: Pin<&mut MyObjectQt>, + self: Pin<&mut MyObject>, func: fn( - Pin<&mut MyObjectQt>, + Pin<&mut MyObject>, first: i32, second: UniquePtr, third: QPoint, @@ -177,7 +174,7 @@ pub mod cxx_qt_ffi { self.connect_data_changed(func, CxxQtConnectionType::AutoConnection) } } - impl MyObjectQt { + impl MyObject { #[doc = "Connect the given function pointer to the signal "] #[doc = "newData"] #[doc = ", so that when the signal is emitted the function pointer is executed."] @@ -185,9 +182,9 @@ pub mod cxx_qt_ffi { #[doc = "Note that this method uses a AutoConnection connection type."] #[must_use] pub fn on_base_class_new_data( - self: Pin<&mut MyObjectQt>, + self: Pin<&mut MyObject>, func: fn( - Pin<&mut MyObjectQt>, + Pin<&mut MyObject>, first: i32, second: UniquePtr, third: QPoint, @@ -197,13 +194,13 @@ pub mod cxx_qt_ffi { self.connect_base_class_new_data(func, CxxQtConnectionType::AutoConnection) } } - impl cxx_qt::Locking for MyObjectQt {} + impl cxx_qt::Locking for MyObject {} #[doc = r" Generated CXX-Qt method which creates a boxed rust struct of a QObject"] - pub fn create_rs_my_object() -> std::boxed::Box { + pub fn create_rs_my_object_rust() -> std::boxed::Box { core::default::Default::default() } - impl cxx_qt::CxxQtType for MyObjectQt { - type Rust = MyObject; + impl cxx_qt::CxxQtType for MyObject { + type Rust = MyObjectRust; fn rust(&self) -> &Self::Rust { self.cxx_qt_ffi_rust() } @@ -219,6 +216,6 @@ pub mod cxx_qt_ffi { #[doc = "Use this type when referring to the QObject as a pointer"] #[doc = "\n"] #[doc = "See the book for more information: "] - pub type MyObject = super::MyObjectQt; + pub type MyObject = super::MyObject; } } diff --git a/crates/cxx-qt-macro/src/lib.rs b/crates/cxx-qt-macro/src/lib.rs index ec510781a..1d28ee868 100644 --- a/crates/cxx-qt-macro/src/lib.rs +++ b/crates/cxx-qt-macro/src/lib.rs @@ -19,22 +19,22 @@ use cxx_qt_gen::{write_rust, GeneratedRustBlocks, Parser}; /// ```rust /// #[cxx_qt::bridge(namespace = "cxx_qt::my_object")] /// mod ffi { -/// #[cxx_qt::qobject] -/// #[derive(Default)] -/// # // Note that we can't use properties as this confuses the linker on Windows -/// pub struct MyObject; -/// /// unsafe extern "RustQt" { +/// #[cxx_qt::qobject] +/// # // Note that we can't use properties as this confuses the linker on Windows +/// type MyObject = super::MyObjectRust; +/// /// #[qinvokable] -/// fn invokable(self: &qobject::MyObject, a: i32, b: i32) -> i32 { -/// a + b -/// } +/// fn invokable(self: &qobject::MyObject, a: i32, b: i32) -> i32; /// } /// } /// +/// #[derive(Default)] +/// pub struct MyObjectRust; +/// /// # // TODO: this will change to qobject::MyObject once /// # // https://github.com/KDAB/cxx-qt/issues/559 is done -/// impl ffi::MyObjectQt { +/// impl ffi::MyObject { /// fn invokable(&self, a: i32, b: i32) -> i32 { /// a + b /// } @@ -74,12 +74,16 @@ pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream { /// ```rust /// #[cxx_qt::bridge] /// mod my_object { -/// #[cxx_qt::qobject] -/// #[derive(Default)] -/// # // Note that we can't use properties as this confuses the linker on Windows -/// pub struct MyObject; +/// extern "RustQt" { +/// #[cxx_qt::qobject] +/// # // Note that we can't use properties as this confuses the linker on Windows +/// type MyObject = super::MyObjectRust; +/// } /// } /// +/// #[derive(Default)] +/// pub struct MyObjectRust; +/// /// # // Note that we need a fake main for doc tests to build /// # fn main() {} /// ``` @@ -91,16 +95,20 @@ pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream { /// ```rust /// #[cxx_qt::bridge] /// mod my_object { -/// #[cxx_qt::qobject(base = "QStringListModel")] -/// #[derive(Default)] -/// # // Note that we can't use properties as this confuses the linker on Windows -/// pub struct MyModel; +/// extern "RustQt" { +/// #[cxx_qt::qobject(base = "QStringListModel")] +/// # // Note that we can't use properties as this confuses the linker on Windows +/// type MyModel = super::MyModelRust; +/// } /// /// unsafe extern "C++" { /// include!(); /// } /// } /// +/// #[derive(Default)] +/// pub struct MyModelRust; +/// /// # // Note that we need a fake main for doc tests to build /// # fn main() {} /// ``` diff --git a/crates/cxx-qt/src/lib.rs b/crates/cxx-qt/src/lib.rs index f1316e666..0402dcce1 100644 --- a/crates/cxx-qt/src/lib.rs +++ b/crates/cxx-qt/src/lib.rs @@ -93,11 +93,9 @@ pub trait Threading: Locking + Sized { /// ``` /// #[cxx_qt::bridge] /// mod ffi { -/// // Struct without `Default` implementation -/// #[cxx_qt::qobject] -/// pub struct MyStruct { -/// pub integer: i32, -/// pub string: String +/// extern "RustQt" { +/// #[cxx_qt::qobject] +/// type MyStruct = super::MyStructRust; /// } /// /// // Declare that we want to use a custom constructor @@ -106,6 +104,12 @@ pub trait Threading: Locking + Sized { /// impl cxx_qt::Constructor<(i32, String), NewArguments=(i32, String)> for qobject::MyStruct {} /// } /// +/// // Struct without `Default` implementation +/// pub struct MyStructRust { +/// pub integer: i32, +/// pub string: String +/// } +/// /// impl cxx_qt::Constructor<(i32, String)> for qobject::MyStruct { /// type BaseArguments = (); // Will be passed to the base class constructor /// type InitializeArguments = (); // Will be passed to the "initialize" function @@ -119,8 +123,8 @@ pub trait Threading: Locking + Sized { /// (args, (), ()) /// } /// -/// fn new((integer, string): (i32, String)) -> MyStruct { -/// MyStruct { +/// fn new((integer, string): (i32, String)) -> MyStructRust { +/// MyStructRust { /// integer, /// string /// } diff --git a/examples/demo_threading/rust/src/lib.rs b/examples/demo_threading/rust/src/lib.rs index 53e945953..15b9a8292 100644 --- a/examples/demo_threading/rust/src/lib.rs +++ b/examples/demo_threading/rust/src/lib.rs @@ -11,54 +11,18 @@ mod workers; // This mod defines our QObject called EnergyUsage #[cxx_qt::bridge(cxx_file_stem = "energy_usage", namespace = "cxx_qt::energy_usage")] mod ffi { - use crate::{constants::SENSOR_MAXIMUM_COUNT, workers::SensorHashMap}; - use std::{ - sync::{Arc, Mutex}, - thread::JoinHandle, - }; - #[namespace = ""] unsafe extern "C++" { include!("cxx-qt-lib/qstring.h"); type QString = cxx_qt_lib::QString; } - #[cxx_qt::qobject(qml_uri = "com.kdab.energy", qml_version = "1.0")] - #[qproperty(f64, average_use)] - #[qproperty(u32, sensors)] - #[qproperty(f64, total_use)] - pub struct EnergyUsage { - /// The average power usage of the connected sensors - average_use: f64, - /// The count of connected sensors - sensors: u32, - /// The total power usage of the connected sensors - total_use: f64, - - /// The join handles of the running threads - pub(crate) join_handles: Option<[JoinHandle<()>; 4]>, - /// A HashMap of the currently connected sensors - /// - /// This uses an Arc inside the Mutex as well as outside so that the HashMap is only - /// cloned when required. By using Arc::make_mut on the inner HashMap data is only cloned - /// when mutating if another thread is still holding onto reference to the data. - /// - pub(crate) sensors_map: Arc>>, - } - - impl Default for EnergyUsage { - fn default() -> Self { - Self { - average_use: 0.0, - sensors: 0, - total_use: 0.0, - - join_handles: None, - sensors_map: Arc::new(Mutex::new(Arc::new(SensorHashMap::with_capacity( - SENSOR_MAXIMUM_COUNT, - )))), - } - } + extern "RustQt" { + #[cxx_qt::qobject(qml_uri = "com.kdab.energy", qml_version = "1.0")] + #[qproperty(f64, average_use)] + #[qproperty(u32, sensors)] + #[qproperty(f64, total_use)] + type EnergyUsage = super::EnergyUsageRust; } // Enabling threading on the qobject @@ -86,21 +50,58 @@ mod ffi { } use crate::{ - constants::CHANNEL_NETWORK_COUNT, + constants::{CHANNEL_NETWORK_COUNT, SENSOR_MAXIMUM_COUNT}, network::NetworkServer, - workers::{AccumulatorWorker, SensorsWorker, TimeoutWorker}, + workers::{AccumulatorWorker, SensorHashMap, SensorsWorker, TimeoutWorker}, }; use core::pin::Pin; use cxx_qt::{CxxQtType, Threading}; use cxx_qt_lib::QString; use futures::executor::block_on; -use std::sync::{atomic::AtomicBool, mpsc::sync_channel, Arc}; +use std::{ + sync::{atomic::AtomicBool, mpsc::sync_channel, Arc, Mutex}, + thread::JoinHandle, +}; use uuid::Uuid; +pub struct EnergyUsageRust { + /// The average power usage of the connected sensors + average_use: f64, + /// The count of connected sensors + sensors: u32, + /// The total power usage of the connected sensors + total_use: f64, + + /// The join handles of the running threads + pub(crate) join_handles: Option<[JoinHandle<()>; 4]>, + /// A HashMap of the currently connected sensors + /// + /// This uses an Arc inside the Mutex as well as outside so that the HashMap is only + /// cloned when required. By using Arc::make_mut on the inner HashMap data is only cloned + /// when mutating if another thread is still holding onto reference to the data. + /// + pub(crate) sensors_map: Arc>>, +} + +impl Default for EnergyUsageRust { + fn default() -> Self { + Self { + average_use: 0.0, + sensors: 0, + total_use: 0.0, + + join_handles: None, + sensors_map: Arc::new(Mutex::new(Arc::new(SensorHashMap::with_capacity( + SENSOR_MAXIMUM_COUNT, + )))), + } + } +} + // TODO: this will change to qobject::EnergyUsage once // https://github.com/KDAB/cxx-qt/issues/559 is done -impl ffi::EnergyUsageQt { +impl ffi::EnergyUsage { /// A Q_INVOKABLE that returns the current power usage for a given uuid fn sensor_power(self: Pin<&mut Self>, uuid: &QString) -> f64 { let sensors = SensorsWorker::read_sensors(&self.rust_mut().sensors_map); @@ -128,8 +129,8 @@ impl cxx_qt::Constructor<()> for qobject::EnergyUsage { ((), (), ()) } - fn new((): ()) -> EnergyUsage { - EnergyUsage::default() + fn new((): ()) -> EnergyUsageRust { + EnergyUsageRust::default() } /// A Q_INVOKABLE which starts the TCP server diff --git a/examples/qml_extension_plugin/plugin/rust/src/lib.rs b/examples/qml_extension_plugin/plugin/rust/src/lib.rs index d2a381e3c..6b2279eb4 100644 --- a/examples/qml_extension_plugin/plugin/rust/src/lib.rs +++ b/examples/qml_extension_plugin/plugin/rust/src/lib.rs @@ -15,8 +15,8 @@ pub struct DataSerde { string: String, } -impl From<&MyObject> for DataSerde { - fn from(value: &MyObject) -> DataSerde { +impl From<&MyObjectRust> for DataSerde { + fn from(value: &MyObjectRust) -> DataSerde { DataSerde { number: value.number, string: value.string.to_string(), @@ -28,39 +28,18 @@ const DEFAULT_STR: &str = r#"{"number": 1, "string": "Hello World!"}"#; #[cxx_qt::bridge(cxx_file_stem = "my_object", namespace = "core")] mod ffi { - use super::{DataSerde, DEFAULT_STR}; - #[namespace = ""] unsafe extern "C++" { include!("cxx-qt-lib/qstring.h"); type QString = cxx_qt_lib::QString; } - #[cxx_qt::qobject] - #[qproperty(i32, number)] - #[qproperty(QString, string)] - pub struct MyObject { - pub number: i32, - pub string: QString, - } - - impl Default for MyObject { - fn default() -> Self { - let data_serde: DataSerde = serde_json::from_str(DEFAULT_STR).unwrap(); - data_serde.into() - } - } - - impl From for MyObject { - fn from(value: DataSerde) -> MyObject { - MyObject { - number: value.number, - string: QString::from(&value.string), - } - } - } - unsafe extern "RustQt" { + #[cxx_qt::qobject] + #[qproperty(i32, number)] + #[qproperty(QString, string)] + type MyObject = super::MyObjectRust; + #[qinvokable] pub fn increment(self: Pin<&mut qobject::MyObject>); @@ -79,9 +58,30 @@ use core::pin::Pin; use cxx_qt::CxxQtType; use cxx_qt_lib::QString; +pub struct MyObjectRust { + pub number: i32, + pub string: QString, +} + +impl Default for MyObjectRust { + fn default() -> Self { + let data_serde: DataSerde = serde_json::from_str(DEFAULT_STR).unwrap(); + data_serde.into() + } +} + +impl From for MyObjectRust { + fn from(value: DataSerde) -> Self { + Self { + number: value.number, + string: QString::from(&value.string), + } + } +} + // TODO: this will change to qobject::MyObject once // https://github.com/KDAB/cxx-qt/issues/559 is done -impl ffi::MyObjectQt { +impl ffi::MyObject { pub fn increment(self: Pin<&mut Self>) { let new_number = self.number() + 1; self.set_number(new_number); diff --git a/examples/qml_features/rust/src/containers.rs b/examples/qml_features/rust/src/containers.rs index 3ae96ed23..c0946d92c 100644 --- a/examples/qml_features/rust/src/containers.rs +++ b/examples/qml_features/rust/src/containers.rs @@ -32,33 +32,17 @@ pub mod ffi { type QVector_i32 = cxx_qt_lib::QVector; } - /// A QObject which stores container types internally - /// - /// It has Q_PROPERTYs which expose a string with the container's contents to show in QML - #[cxx_qt::qobject(qml_uri = "com.kdab.cxx_qt.demo", qml_version = "1.0")] - #[derive(Default)] - #[qproperty(QString, string_hash)] - #[qproperty(QString, string_list)] - #[qproperty(QString, string_map)] - #[qproperty(QString, string_set)] - #[qproperty(QString, string_vector)] - // Expose as a Q_PROPERTY so that QML tests can ensure that QVariantMap works - #[qproperty(QMap_QString_QVariant, map)] - pub struct RustContainers { - string_hash: QString, - string_list: QString, - string_map: QString, - string_set: QString, - string_vector: QString, - - pub(crate) hash: QHash_QString_QVariant, - pub(crate) list: QList_i32, - pub(crate) map: QMap_QString_QVariant, - pub(crate) set: QSet_i32, - pub(crate) vector: QVector_i32, - } - unsafe extern "RustQt" { + #[cxx_qt::qobject(qml_uri = "com.kdab.cxx_qt.demo", qml_version = "1.0")] + #[qproperty(QString, string_hash)] + #[qproperty(QString, string_list)] + #[qproperty(QString, string_map)] + #[qproperty(QString, string_set)] + #[qproperty(QString, string_vector)] + // Expose as a Q_PROPERTY so that QML tests can ensure that QVariantMap works + #[qproperty(QMap_QString_QVariant, map)] + type RustContainers = super::RustContainersRust; + /// Reset all the containers #[qinvokable] fn reset(self: Pin<&mut qobject::RustContainers>); @@ -92,9 +76,27 @@ use cxx_qt_lib::{ QVariant, QVector, }; +/// A QObject which stores container types internally +/// +/// It has Q_PROPERTYs which expose a string with the container's contents to show in QML +#[derive(Default)] +pub struct RustContainersRust { + string_hash: QString, + string_list: QString, + string_map: QString, + string_set: QString, + string_vector: QString, + + pub(crate) hash: QHash, + pub(crate) list: QList, + pub(crate) map: QMap, + pub(crate) set: QSet, + pub(crate) vector: QVector, +} + // TODO: this will change to qobject::RustContainers once // https://github.com/KDAB/cxx-qt/issues/559 is done -impl ffi::RustContainersQt { +impl ffi::RustContainers { /// Reset all the containers fn reset(mut self: Pin<&mut Self>) { // Update the private rust fields via the rust_mut diff --git a/examples/qml_features/rust/src/custom_base_class.rs b/examples/qml_features/rust/src/custom_base_class.rs index a861e32ee..f8943ff5b 100644 --- a/examples/qml_features/rust/src/custom_base_class.rs +++ b/examples/qml_features/rust/src/custom_base_class.rs @@ -31,20 +31,17 @@ pub mod ffi { type QVector_i32 = cxx_qt_lib::QVector; } - /// A struct which inherits from QAbstractListModel // ANCHOR: book_inherit_qalm // ANCHOR: book_qobject_base - #[cxx_qt::qobject( - base = "QAbstractListModel", - qml_uri = "com.kdab.cxx_qt.demo", - qml_version = "1.0" - )] - #[derive(Default)] - pub struct CustomBaseClass { - // ANCHOR_END: book_qobject_base - pub(crate) id: u32, - pub(crate) vector: Vec<(u32, f64)>, + extern "RustQt" { + #[cxx_qt::qobject( + base = "QAbstractListModel", + qml_uri = "com.kdab.cxx_qt.demo", + qml_version = "1.0" + )] + type CustomBaseClass = super::CustomBaseClassRust; } + // ANCHOR_END: book_qobject_base // ANCHOR_END: book_inherit_qalm // Enabling threading on the qobject @@ -178,9 +175,16 @@ use core::pin::Pin; use cxx_qt::{CxxQtType, Threading}; use cxx_qt_lib::{QByteArray, QHash, QHashPair_i32_QByteArray, QModelIndex, QVariant, QVector}; +/// A struct which inherits from QAbstractListModel +#[derive(Default)] +pub struct CustomBaseClassRust { + pub(crate) id: u32, + pub(crate) vector: Vec<(u32, f64)>, +} + // TODO: this will change to qobject::RustContainers once // https://github.com/KDAB/cxx-qt/issues/559 is done -impl ffi::CustomBaseClassQt { +impl ffi::CustomBaseClass { /// Add a new row to the QAbstractListModel on the current thread pub fn add(self: Pin<&mut Self>) { self.add_cpp_context(); @@ -223,7 +227,7 @@ impl ffi::CustomBaseClassQt { } // ANCHOR: book_inherit_clear -impl ffi::CustomBaseClassQt { +impl ffi::CustomBaseClass { /// Clear the rows in the QAbstractListModel pub fn clear(mut self: Pin<&mut Self>) { unsafe { @@ -236,7 +240,7 @@ impl ffi::CustomBaseClassQt { } // ANCHOR_END: book_inherit_clear -impl ffi::CustomBaseClassQt { +impl ffi::CustomBaseClass { /// Multiply the number in the row with the given index by the given factor pub fn multiply(mut self: Pin<&mut Self>, index: i32, factor: f64) { if let Some((_, value)) = self.as_mut().rust_mut().vector.get_mut(index as usize) { @@ -272,7 +276,7 @@ impl ffi::CustomBaseClassQt { // QAbstractListModel implementation // // ANCHOR: book_inherit_data -impl ffi::CustomBaseClassQt { +impl ffi::CustomBaseClass { /// i32 representing the id role pub const ID_ROLE: i32 = 0; /// i32 representing the value role @@ -293,7 +297,7 @@ impl ffi::CustomBaseClassQt { // ANCHOR_END: book_inherit_data // ANCHOR: book_inherit_can_fetch_more -impl ffi::CustomBaseClassQt { +impl ffi::CustomBaseClass { /// Return whether the base class can fetch more // Example of overriding a C++ virtual method and calling the base class implementation. pub fn can_fetch_more(&self, parent: &QModelIndex) -> bool { @@ -302,7 +306,7 @@ impl ffi::CustomBaseClassQt { } // ANCHOR_END: book_inherit_can_fetch_more -impl ffi::CustomBaseClassQt { +impl ffi::CustomBaseClass { /// Return the role names for the QAbstractListModel pub fn role_names(&self) -> QHash { let mut roles = QHash::::default(); diff --git a/examples/qml_features/rust/src/custom_parent_class.rs b/examples/qml_features/rust/src/custom_parent_class.rs index dd9e419ee..d14bfda81 100644 --- a/examples/qml_features/rust/src/custom_parent_class.rs +++ b/examples/qml_features/rust/src/custom_parent_class.rs @@ -42,23 +42,15 @@ mod ffi { include!(); } - /// A struct which inherits from QQuickPaintedItem - /// - /// Which has a parent of the type QQuickItem rather than QObject. - #[cxx_qt::qobject( - base = "QQuickPaintedItem", - qml_uri = "com.kdab.cxx_qt.demo", - qml_version = "1.0" - )] - #[qproperty(QColor, color)] - #[derive(Default)] - pub struct CustomParentClass { - color: QColor, - } - - impl cxx_qt::Constructor<()> for qobject::CustomParentClass {} - unsafe extern "RustQt" { + #[cxx_qt::qobject( + base = "QQuickPaintedItem", + qml_uri = "com.kdab.cxx_qt.demo", + qml_version = "1.0" + )] + #[qproperty(QColor, color)] + type CustomParentClass = super::CustomParentClassRust; + /// Override QQuickPaintedItem::paint to draw two rectangles in Rust using QPainter #[qinvokable(cxx_override)] unsafe fn paint(self: Pin<&mut qobject::CustomParentClass>, painter: *mut QPainter); @@ -71,14 +63,24 @@ mod ffi { #[inherit] fn update(self: Pin<&mut qobject::CustomParentClass>); } + + impl cxx_qt::Constructor<()> for qobject::CustomParentClass {} } use core::pin::Pin; -use cxx_qt_lib::QRectF; +use cxx_qt_lib::{QColor, QRectF}; + +/// A struct which inherits from QQuickPaintedItem +/// +/// Which has a parent of the type QQuickItem rather than QObject. +#[derive(Default)] +pub struct CustomParentClassRust { + color: QColor, +} // TODO: this will change to qobject::RustInvokables once // https://github.com/KDAB/cxx-qt/issues/559 is done -impl ffi::CustomParentClassQt { +impl ffi::CustomParentClass { /// Override QQuickPaintedItem::paint to draw two rectangles in Rust using QPainter fn paint(self: Pin<&mut Self>, painter: *mut ffi::QPainter) { // We need to convert the *mut QPainter to a Pin<&mut QPainter> so that we can reach the methods @@ -101,7 +103,7 @@ impl ffi::CustomParentClassQt { } } -impl cxx_qt::Constructor<()> for qobject::CustomParentClass { +impl cxx_qt::Constructor<()> for ffi::CustomParentClass { type NewArguments = (); type BaseArguments = (*mut ffi::QQuickItem,); type InitializeArguments = (); @@ -116,8 +118,8 @@ impl cxx_qt::Constructor<()> for qobject::CustomParentClass { ((), (core::ptr::null_mut(),), ()) } - fn new((): ()) -> CustomParentClass { - CustomParentClass::default() + fn new((): ()) -> CustomParentClassRust { + CustomParentClassRust::default() } fn initialize(self: core::pin::Pin<&mut Self>, _arguments: Self::InitializeArguments) { diff --git a/examples/qml_features/rust/src/invokables.rs b/examples/qml_features/rust/src/invokables.rs index 22aa770c6..0f82c9758 100644 --- a/examples/qml_features/rust/src/invokables.rs +++ b/examples/qml_features/rust/src/invokables.rs @@ -15,22 +15,9 @@ pub mod ffi { type QColor = cxx_qt_lib::QColor; } - /// A QObject which has Q_INVOKABLEs - #[cxx_qt::qobject(qml_uri = "com.kdab.cxx_qt.demo", qml_version = "1.0")] - pub struct RustInvokables { - pub(crate) red: f32, - pub(crate) green: f32, - pub(crate) blue: f32, - } - - impl Default for RustInvokables { - fn default() -> Self { - Self { - red: 0.0, - green: 0.4667, - blue: 0.7843, - } - } + unsafe extern "RustQt" { + #[cxx_qt::qobject(qml_uri = "com.kdab.cxx_qt.demo", qml_version = "1.0")] + type RustInvokables = super::RustInvokablesRust; } // ANCHOR: book_invokable_signature @@ -54,11 +41,28 @@ use core::pin::Pin; use cxx_qt::CxxQtType; use cxx_qt_lib::QColor; +/// A QObject which has Q_INVOKABLEs +pub struct RustInvokablesRust { + pub(crate) red: f32, + pub(crate) green: f32, + pub(crate) blue: f32, +} + +impl Default for RustInvokablesRust { + fn default() -> Self { + Self { + red: 0.0, + green: 0.4667, + blue: 0.7843, + } + } +} + // TODO: this will change to qobject::RustInvokables once // https://github.com/KDAB/cxx-qt/issues/559 is done // // ANCHOR: book_invokable_impl -impl ffi::RustInvokablesQt { +impl ffi::RustInvokables { /// Immutable invokable method that returns the QColor fn load_color(&self) -> QColor { self.rust().as_qcolor() @@ -84,7 +88,7 @@ impl ffi::RustInvokablesQt { } // ANCHOR_END: book_invokable_impl -impl RustInvokables { +impl RustInvokablesRust { /// Immutable Rust context method that returns the QColor fn as_qcolor(&self) -> QColor { QColor::from_rgb( diff --git a/examples/qml_features/rust/src/multiple_qobjects.rs b/examples/qml_features/rust/src/multiple_qobjects.rs index b0e3b7a67..b7935eb11 100644 --- a/examples/qml_features/rust/src/multiple_qobjects.rs +++ b/examples/qml_features/rust/src/multiple_qobjects.rs @@ -17,22 +17,11 @@ pub mod ffi { type QUrl = cxx_qt_lib::QUrl; } - /// The first QObject - #[cxx_qt::qobject(qml_uri = "com.kdab.cxx_qt.demo", qml_version = "1.0")] - #[qproperty(i32, counter)] - #[qproperty(QColor, color)] - pub struct FirstObject { - counter: i32, - color: QColor, - } - - impl Default for FirstObject { - fn default() -> Self { - Self { - counter: 10, - color: QColor::from_rgb(0, 0, 255), - } - } + extern "RustQt" { + #[cxx_qt::qobject(qml_uri = "com.kdab.cxx_qt.demo", qml_version = "1.0")] + #[qproperty(i32, counter)] + #[qproperty(QColor, color)] + type FirstObject = super::FirstObjectRust; } // Enabling threading on the qobject @@ -54,22 +43,11 @@ pub mod ffi { fn increment(self: Pin<&mut qobject::FirstObject>); } - /// The second QObject - #[cxx_qt::qobject(qml_uri = "com.kdab.cxx_qt.demo", qml_version = "1.0")] - #[qproperty(i32, counter)] - #[qproperty(QUrl, url)] - pub struct SecondObject { - counter: i32, - url: QUrl, - } - - impl Default for SecondObject { - fn default() -> Self { - Self { - counter: 100, - url: QUrl::from("https://github.com/kdab/cxx-qt"), - } - } + extern "RustQt" { + #[cxx_qt::qobject(qml_uri = "com.kdab.cxx_qt.demo", qml_version = "1.0")] + #[qproperty(i32, counter)] + #[qproperty(QUrl, url)] + type SecondObject = super::SecondObjectRust; } // Enabling threading on the qobject @@ -95,9 +73,24 @@ pub mod ffi { use core::pin::Pin; use cxx_qt_lib::{QColor, QUrl}; +/// The first QObject +pub struct FirstObjectRust { + counter: i32, + color: QColor, +} + +impl Default for FirstObjectRust { + fn default() -> Self { + Self { + counter: 10, + color: QColor::from_rgb(0, 0, 255), + } + } +} + // TODO: this will change to qobject::FirstObject once // https://github.com/KDAB/cxx-qt/issues/559 is done -impl ffi::FirstObjectQt { +impl ffi::FirstObject { /// A Q_INVOKABLE on the first QObject which increments a counter fn increment(mut self: Pin<&mut Self>) { let new_value = self.as_ref().counter() + 1; @@ -113,9 +106,24 @@ impl ffi::FirstObjectQt { } } +/// The second QObject +pub struct SecondObjectRust { + counter: i32, + url: QUrl, +} + +impl Default for SecondObjectRust { + fn default() -> Self { + Self { + counter: 100, + url: QUrl::from("https://github.com/kdab/cxx-qt"), + } + } +} + // TODO: this will change to qobject::SecondObject once // https://github.com/KDAB/cxx-qt/issues/559 is done -impl ffi::SecondObjectQt { +impl ffi::SecondObject { /// A Q_INVOKABLE on the second QObject which increments a counter fn increment(mut self: Pin<&mut Self>) { let new_value = self.as_ref().counter() + 1; diff --git a/examples/qml_features/rust/src/nested_qobjects.rs b/examples/qml_features/rust/src/nested_qobjects.rs index 2d39f8f58..dd56da45a 100644 --- a/examples/qml_features/rust/src/nested_qobjects.rs +++ b/examples/qml_features/rust/src/nested_qobjects.rs @@ -17,36 +17,21 @@ pub mod ffi { } // ANCHOR_END: book_extern_block - /// The inner QObject - #[cxx_qt::qobject(qml_uri = "com.kdab.cxx_qt.demo", qml_version = "1.0")] - #[derive(Default)] - #[qproperty(i32, counter)] - pub struct InnerObject { - counter: i32, - } - extern "RustQt" { + #[cxx_qt::qobject(qml_uri = "com.kdab.cxx_qt.demo", qml_version = "1.0")] + #[qproperty(i32, counter)] + type InnerObject = super::InnerObjectRust; + /// A signal showing how to refer to another QObject as an argument #[qsignal] unsafe fn called(self: Pin<&mut qobject::InnerObject>, inner: *mut CxxInnerObject); } - /// The outer QObject which has a Q_PROPERTY pointing to the inner QObject - #[cxx_qt::qobject(qml_uri = "com.kdab.cxx_qt.demo", qml_version = "1.0")] - #[qproperty(*mut CxxInnerObject, inner)] - pub struct OuterObject { - inner: *mut CxxInnerObject, - } - - impl Default for OuterObject { - fn default() -> Self { - Self { - inner: std::ptr::null_mut(), - } - } - } - extern "RustQt" { + #[cxx_qt::qobject(qml_uri = "com.kdab.cxx_qt.demo", qml_version = "1.0")] + #[qproperty(*mut CxxInnerObject, inner)] + type OuterObject = super::OuterObjectRust; + /// A signal showing how to refer to another QObject as an argument #[qsignal] unsafe fn called(self: Pin<&mut qobject::OuterObject>, inner: *mut CxxInnerObject); @@ -70,9 +55,28 @@ pub mod ffi { use core::pin::Pin; +/// The inner QObject +#[derive(Default)] +pub struct InnerObjectRust { + counter: i32, +} + +/// The outer QObject which has a Q_PROPERTY pointing to the inner QObject +pub struct OuterObjectRust { + inner: *mut ffi::CxxInnerObject, +} + +impl Default for OuterObjectRust { + fn default() -> Self { + Self { + inner: std::ptr::null_mut(), + } + } +} + // TODO: this will change to qobject::OuterObject once // https://github.com/KDAB/cxx-qt/issues/559 is done -impl ffi::OuterObjectQt { +impl ffi::OuterObject { /// Print the count of the given inner QObject // // This method needs to be unsafe otherwise clippy complains that the diff --git a/examples/qml_features/rust/src/properties.rs b/examples/qml_features/rust/src/properties.rs index 972f6bd29..73d4df365 100644 --- a/examples/qml_features/rust/src/properties.rs +++ b/examples/qml_features/rust/src/properties.rs @@ -17,42 +17,16 @@ pub mod ffi { type QUrl = cxx_qt_lib::QUrl; } - /// A QObject which has Q_PROPERTYs - // ANCHOR: book_properties_struct - #[cxx_qt::qobject(qml_uri = "com.kdab.cxx_qt.demo", qml_version = "1.0")] - #[qproperty(bool, connected)] - #[qproperty(QUrl, connected_url)] - #[qproperty(QUrl, previous_connected_url)] - #[qproperty(QString, status_message)] - pub struct RustProperties { - /// A connected Q_PROPERTY - connected: bool, - - /// A connected_url Q_PROPERTY - pub(crate) connected_url: QUrl, - - /// A previous_connected_url Q_PROPERTY - previous_connected_url: QUrl, - - /// A status_message Q_PROPERTY - status_message: QString, - } - // ANCHOR_END: book_properties_struct - - // ANCHOR: book_properties_default - impl Default for RustProperties { - fn default() -> Self { - Self { - connected: false, - connected_url: QUrl::default(), - previous_connected_url: QUrl::default(), - status_message: QString::from("Disconnected"), - } - } - } - // ANCHOR_END: book_properties_default - unsafe extern "RustQt" { + // ANCHOR: book_properties_struct + #[cxx_qt::qobject(qml_uri = "com.kdab.cxx_qt.demo", qml_version = "1.0")] + #[qproperty(bool, connected)] + #[qproperty(QUrl, connected_url)] + #[qproperty(QUrl, previous_connected_url)] + #[qproperty(QString, status_message)] + type RustProperties = super::RustPropertiesRust; + // ANCHOR_END: book_properties_struct + /// Connect to the given url #[qinvokable] fn connect(self: Pin<&mut qobject::RustProperties>, mut url: QUrl); @@ -67,9 +41,37 @@ use core::pin::Pin; use cxx_qt::CxxQtType; use cxx_qt_lib::{QString, QUrl}; +/// A QObject which has Q_PROPERTYs +pub struct RustPropertiesRust { + /// A connected Q_PROPERTY + connected: bool, + + /// A connected_url Q_PROPERTY + pub(crate) connected_url: QUrl, + + /// A previous_connected_url Q_PROPERTY + previous_connected_url: QUrl, + + /// A status_message Q_PROPERTY + status_message: QString, +} + +// ANCHOR: book_properties_default +impl Default for RustPropertiesRust { + fn default() -> Self { + Self { + connected: false, + connected_url: QUrl::default(), + previous_connected_url: QUrl::default(), + status_message: QString::from("Disconnected"), + } + } +} +// ANCHOR_END: book_properties_default + // TODO: this will change to qobject::RustProperties once // https://github.com/KDAB/cxx-qt/issues/559 is done -impl ffi::RustPropertiesQt { +impl ffi::RustProperties { /// Connect to the given url fn connect(mut self: Pin<&mut Self>, mut url: QUrl) { // Check that the url starts with kdab diff --git a/examples/qml_features/rust/src/serialisation.rs b/examples/qml_features/rust/src/serialisation.rs index b618edd45..9e18a6a36 100644 --- a/examples/qml_features/rust/src/serialisation.rs +++ b/examples/qml_features/rust/src/serialisation.rs @@ -17,8 +17,8 @@ pub struct DataSerde { string: String, } -impl From<&Serialisation> for DataSerde { - fn from(value: &Serialisation) -> DataSerde { +impl From<&SerialisationRust> for DataSerde { + fn from(value: &SerialisationRust) -> DataSerde { DataSerde { number: value.number, string: value.string.to_string(), @@ -29,49 +29,22 @@ impl From<&Serialisation> for DataSerde { /// A CXX-Qt bridge which shows how use serde for (de)serialization of the data in a QObjects' QPROPERTY's #[cxx_qt::bridge(cxx_file_stem = "serialisation")] pub mod ffi { - use super::DataSerde; - unsafe extern "C++" { include!("cxx-qt-lib/qstring.h"); /// QString from cxx_qt_lib type QString = cxx_qt_lib::QString; } - /// A QObject which can be serialised - #[cxx_qt::qobject(qml_uri = "com.kdab.cxx_qt.demo", qml_version = "1.0")] - #[qproperty(i32, number)] - #[qproperty(QString, string)] - pub struct Serialisation { - /// The number Q_PROPERTY - pub number: i32, - /// The string Q_PROPERTY - pub string: QString, - } - unsafe extern "RustQt" { + #[cxx_qt::qobject(qml_uri = "com.kdab.cxx_qt.demo", qml_version = "1.0")] + #[qproperty(i32, number)] + #[qproperty(QString, string)] + type Serialisation = super::SerialisationRust; + /// An error signal #[qsignal] fn error(self: Pin<&mut qobject::Serialisation>, message: QString); - } - - impl Default for Serialisation { - fn default() -> Self { - let string = r#"{"number": 4, "string": "Hello World!"}"#; - let data_serde: DataSerde = serde_json::from_str(string).unwrap(); - data_serde.into() - } - } - - impl From for Serialisation { - fn from(value: DataSerde) -> Serialisation { - Serialisation { - number: value.number, - string: QString::from(&value.string), - } - } - } - unsafe extern "RustQt" { /// Retrieve the JSON form of this QObject #[qinvokable] fn as_json_str(self: Pin<&mut qobject::Serialisation>) -> QString; @@ -88,9 +61,34 @@ use core::pin::Pin; use cxx_qt::CxxQtType; use cxx_qt_lib::QString; +/// A QObject which can be serialised +pub struct SerialisationRust { + /// The number Q_PROPERTY + pub number: i32, + /// The string Q_PROPERTY + pub string: QString, +} + +impl Default for SerialisationRust { + fn default() -> Self { + let string = r#"{"number": 4, "string": "Hello World!"}"#; + let data_serde: DataSerde = serde_json::from_str(string).unwrap(); + data_serde.into() + } +} + +impl From for SerialisationRust { + fn from(value: DataSerde) -> Self { + Self { + number: value.number, + string: QString::from(&value.string), + } + } +} + // TODO: this will change to qobject::Serialisation once // https://github.com/KDAB/cxx-qt/issues/559 is done -impl ffi::SerialisationQt { +impl ffi::Serialisation { /// Retrieve the JSON form of this QObject fn as_json_str(self: Pin<&mut Self>) -> QString { let data_serde = DataSerde::from(self.rust()); diff --git a/examples/qml_features/rust/src/signals.rs b/examples/qml_features/rust/src/signals.rs index e0c46e027..6e6251bad 100644 --- a/examples/qml_features/rust/src/signals.rs +++ b/examples/qml_features/rust/src/signals.rs @@ -34,15 +34,11 @@ pub mod ffi { } // ANCHOR_END: book_signals_block - /// A QObject which has Q_SIGNALs - // ANCHOR: book_signals_struct - #[cxx_qt::qobject(qml_uri = "com.kdab.cxx_qt.demo", qml_version = "1.0")] - #[derive(Default)] - #[qproperty(bool, logging_enabled)] - pub struct RustSignals { - pub(crate) connections: Option<[cxx_qt_lib::QMetaObjectConnection; 3]>, - - logging_enabled: bool, + unsafe extern "RustQt" { + // ANCHOR: book_signals_struct + #[cxx_qt::qobject(qml_uri = "com.kdab.cxx_qt.demo", qml_version = "1.0")] + #[qproperty(bool, logging_enabled)] + type RustSignals = super::RustSignalsRust; } // ANCHOR: book_rust_obj_impl @@ -64,9 +60,17 @@ use core::pin::Pin; use cxx_qt::CxxQtType; use cxx_qt_lib::{ConnectionType, QString, QUrl}; +/// A QObject which has Q_SIGNALs +#[derive(Default)] +pub struct RustSignalsRust { + pub(crate) connections: Option<[cxx_qt_lib::QMetaObjectConnection; 3]>, + + logging_enabled: bool, +} + // TODO: this will change to qobject::RustSignals once // https://github.com/KDAB/cxx-qt/issues/559 is done -impl ffi::RustSignalsQt { +impl ffi::RustSignals { /// Connect to the given url fn connect(self: Pin<&mut Self>, url: &QUrl) { // Check that the url starts with kdab diff --git a/examples/qml_features/rust/src/singleton.rs b/examples/qml_features/rust/src/singleton.rs index 7777b1a72..209b89b5b 100644 --- a/examples/qml_features/rust/src/singleton.rs +++ b/examples/qml_features/rust/src/singleton.rs @@ -9,16 +9,11 @@ // ANCHOR: book_macro_code #[cxx_qt::bridge(cxx_file_stem = "rust_singleton")] pub mod ffi { - /// A QObject which is a QML_SINGLETON - #[cxx_qt::qobject(qml_uri = "com.kdab.cxx_qt.demo", qml_version = "1.0", qml_singleton)] - #[derive(Default)] - #[qproperty(i32, persistent_value)] - pub struct RustSingleton { - /// A Q_PROPERTY with a persistent value - persistent_value: i32, - } - unsafe extern "RustQt" { + #[cxx_qt::qobject(qml_uri = "com.kdab.cxx_qt.demo", qml_version = "1.0", qml_singleton)] + #[qproperty(i32, persistent_value)] + type RustSingleton = super::RustSingletonRust; + /// Increment the persistent value Q_PROPERTY of the QML_SINGLETON #[qinvokable] fn increment(self: Pin<&mut qobject::RustSingleton>); @@ -27,9 +22,16 @@ pub mod ffi { use core::pin::Pin; +/// A QObject which is a QML_SINGLETON +#[derive(Default)] +pub struct RustSingletonRust { + /// A Q_PROPERTY with a persistent value + persistent_value: i32, +} + // TODO: this will change to qobject::RustSingleton once // https://github.com/KDAB/cxx-qt/issues/559 is done -impl ffi::RustSingletonQt { +impl ffi::RustSingleton { /// Increment the persistent value Q_PROPERTY of the QML_SINGLETON fn increment(self: Pin<&mut Self>) { let new_value = self.persistent_value() + 1; diff --git a/examples/qml_features/rust/src/threading.rs b/examples/qml_features/rust/src/threading.rs index 97f577e0f..6346edbf2 100644 --- a/examples/qml_features/rust/src/threading.rs +++ b/examples/qml_features/rust/src/threading.rs @@ -21,28 +21,11 @@ pub mod ffi { type QUrl = cxx_qt_lib::QUrl; } - /// A QObject which has threading - #[cxx_qt::qobject(qml_uri = "com.kdab.cxx_qt.demo", qml_version = "1.0")] - #[qproperty(QString, title)] - #[qproperty(QUrl, url)] - pub struct ThreadingWebsite { - /// The title Q_PROPERTY - title: QString, - /// The url Q_PROPERTY - url: QUrl, - - pub(crate) loading: std::sync::atomic::AtomicBool, - } - - impl Default for ThreadingWebsite { - fn default() -> Self { - Self { - url: QUrl::from("https://kdab.com"), - title: QString::from("KDAB"), - - loading: std::sync::atomic::AtomicBool::new(false), - } - } + extern "RustQt" { + #[cxx_qt::qobject(qml_uri = "com.kdab.cxx_qt.demo", qml_version = "1.0")] + #[qproperty(QString, title)] + #[qproperty(QUrl, url)] + type ThreadingWebsite = super::ThreadingWebsiteRust; } // ANCHOR: book_threading_trait @@ -65,9 +48,30 @@ use core::pin::Pin; use cxx_qt::{CxxQtType, Threading}; use cxx_qt_lib::{QString, QUrl}; +/// A QObject which has threading +pub struct ThreadingWebsiteRust { + /// The title Q_PROPERTY + title: QString, + /// The url Q_PROPERTY + url: QUrl, + + pub(crate) loading: std::sync::atomic::AtomicBool, +} + +impl Default for ThreadingWebsiteRust { + fn default() -> Self { + Self { + url: QUrl::from("https://kdab.com"), + title: QString::from("KDAB"), + + loading: std::sync::atomic::AtomicBool::new(false), + } + } +} + // TODO: this will change to qobject::ThreadingWebsite once // https://github.com/KDAB/cxx-qt/issues/559 is done -impl ffi::ThreadingWebsiteQt { +impl ffi::ThreadingWebsite { /// Swap the URL between kdab.com and github.com fn change_url(self: Pin<&mut Self>) { let new_url = if self.url().to_string() == "https://kdab.com" { diff --git a/examples/qml_features/rust/src/types.rs b/examples/qml_features/rust/src/types.rs index b632d5d98..5673b2147 100644 --- a/examples/qml_features/rust/src/types.rs +++ b/examples/qml_features/rust/src/types.rs @@ -73,31 +73,14 @@ pub mod ffi { fn qvariantValueOrDefault(variant: &QVariant) -> CustomStruct; } - /// A QObject which shows custom types - #[cxx_qt::qobject(qml_uri = "com.kdab.cxx_qt.demo", qml_version = "1.0")] - #[qproperty(bool, boolean)] - #[qproperty(QPointF, point)] - #[qproperty(QUrl, url)] - #[qproperty(i32, custom_value)] - pub struct Types { - boolean: bool, - point: QPointF, - url: QUrl, - custom_value: i32, - } - - impl Default for Types { - fn default() -> Self { - Self { - boolean: false, - point: QPointF::new(1.0, 2.0), - url: QUrl::from("https://kdab.com"), - custom_value: 0, - } - } - } - unsafe extern "RustQt" { + #[cxx_qt::qobject(qml_uri = "com.kdab.cxx_qt.demo", qml_version = "1.0")] + #[qproperty(bool, boolean)] + #[qproperty(QPointF, point)] + #[qproperty(QUrl, url)] + #[qproperty(i32, custom_value)] + type Types = super::TypesRust; + /// Load the value from a QVariant #[qinvokable] fn load_from_variant(self: Pin<&mut qobject::Types>, variant: &QVariant); @@ -111,9 +94,28 @@ pub mod ffi { use core::pin::Pin; use cxx_qt_lib::{QPointF, QUrl, QVariant}; +/// A QObject which shows custom types +pub struct TypesRust { + boolean: bool, + point: QPointF, + url: QUrl, + custom_value: i32, +} + +impl Default for TypesRust { + fn default() -> Self { + Self { + boolean: false, + point: QPointF::new(1.0, 2.0), + url: QUrl::from("https://kdab.com"), + custom_value: 0, + } + } +} + // TODO: this will change to qobject::Types once // https://github.com/KDAB/cxx-qt/issues/559 is done -impl ffi::TypesQt { +impl ffi::Types { /// Load the value from a QVariant fn load_from_variant(self: Pin<&mut Self>, variant: &QVariant) { if let Some(boolean) = variant.value::() { diff --git a/examples/qml_features/rust/src/uncreatable.rs b/examples/qml_features/rust/src/uncreatable.rs index 04990fdd6..c36d4c9a3 100644 --- a/examples/qml_features/rust/src/uncreatable.rs +++ b/examples/qml_features/rust/src/uncreatable.rs @@ -9,12 +9,16 @@ // ANCHOR: book_macro_code #[cxx_qt::bridge(cxx_file_stem = "rust_uncreatable")] pub mod ffi { - /// A QObject which is a QML_UNCREATABLE - #[cxx_qt::qobject(qml_uri = "com.kdab.cxx_qt.demo", qml_version = "1.0", qml_uncreatable)] - #[derive(Default)] - #[qproperty(i32, value)] - pub struct RustUncreatable { - /// A value Q_PROPERTY - value: i32, + extern "RustQt" { + #[cxx_qt::qobject(qml_uri = "com.kdab.cxx_qt.demo", qml_version = "1.0", qml_uncreatable)] + #[qproperty(i32, value)] + type RustUncreatable = super::RustUncreatableRust; } } + +/// A QObject which is a QML_UNCREATABLE +#[derive(Default)] +pub struct RustUncreatableRust { + /// A value Q_PROPERTY + value: i32, +} diff --git a/examples/qml_minimal/rust/src/cxxqt_object.rs b/examples/qml_minimal/rust/src/cxxqt_object.rs index fc4f7487f..1bf6bf44f 100644 --- a/examples/qml_minimal/rust/src/cxxqt_object.rs +++ b/examples/qml_minimal/rust/src/cxxqt_object.rs @@ -21,27 +21,14 @@ pub mod ffi { } // ANCHOR_END: book_qstring_import - /// The Rust struct for the QObject - // ANCHOR: book_rustobj_struct - #[cxx_qt::qobject(qml_uri = "com.kdab.cxx_qt.demo", qml_version = "1.0")] - #[qproperty(i32, number)] - #[qproperty(QString, string)] - pub struct MyObject { - number: i32, - string: QString, - } - // ANCHOR_END: book_rustobj_struct - - // ANCHOR: book_rustobj_default - impl Default for MyObject { - fn default() -> Self { - Self { - number: 0, - string: QString::from(""), - } - } + // ANCHOR: book_rustobj_struct_signature + unsafe extern "RustQt" { + #[cxx_qt::qobject(qml_uri = "com.kdab.cxx_qt.demo", qml_version = "1.0")] + #[qproperty(i32, number)] + #[qproperty(QString, string)] + type MyObject = super::MyObjectRust; } - // ANCHOR_END: book_rustobj_default + // ANCHOR_END: book_rustobj_struct_signature // ANCHOR: book_rustobj_invokable_signature unsafe extern "RustQt" { @@ -57,11 +44,30 @@ pub mod ffi { use core::pin::Pin; use cxx_qt_lib::QString; +/// The Rust struct for the QObject +// ANCHOR: book_rustobj_struct +pub struct MyObjectRust { + number: i32, + string: QString, +} +// ANCHOR_END: book_rustobj_struct + +// ANCHOR: book_rustobj_default +impl Default for MyObjectRust { + fn default() -> Self { + Self { + number: 0, + string: QString::from(""), + } + } +} +// ANCHOR_END: book_rustobj_default + // TODO: this will change to qobject::MyObject once // https://github.com/KDAB/cxx-qt/issues/559 is done // // ANCHOR: book_rustobj_invokable_impl -impl ffi::MyObjectQt { +impl ffi::MyObject { /// Increment the number Q_PROPERTY pub fn increment_number(self: Pin<&mut Self>) { let previous = *self.as_ref().number(); diff --git a/tests/basic_cxx_qt/rust/src/data.rs b/tests/basic_cxx_qt/rust/src/data.rs index e99a36363..3a271e510 100644 --- a/tests/basic_cxx_qt/rust/src/data.rs +++ b/tests/basic_cxx_qt/rust/src/data.rs @@ -13,9 +13,9 @@ pub struct DataSerde { string: String, } -impl From<&MyData> for DataSerde { - fn from(value: &MyData) -> DataSerde { - DataSerde { +impl From<&MyDataRust> for DataSerde { + fn from(value: &MyDataRust) -> Self { + Self { number: value.number, string: value.string.to_string(), } @@ -24,40 +24,18 @@ impl From<&MyData> for DataSerde { #[cxx_qt::bridge(cxx_file_stem = "my_data", namespace = "cxx_qt::my_data")] mod ffi { - use super::DataSerde; - #[namespace = ""] unsafe extern "C++" { include!("cxx-qt-lib/qstring.h"); type QString = cxx_qt_lib::QString; } - #[cxx_qt::qobject] - #[qproperty(i32, number)] - #[qproperty(QString, string)] - pub struct MyData { - pub number: i32, - pub string: QString, - } - - impl Default for MyData { - fn default() -> Self { - let string = r#"{"number": 4, "string": "Hello World!"}"#; - let data_serde: DataSerde = serde_json::from_str(string).unwrap(); - data_serde.into() - } - } - - impl From for MyData { - fn from(value: DataSerde) -> MyData { - MyData { - number: value.number, - string: QString::from(&value.string), - } - } - } - unsafe extern "RustQt" { + #[cxx_qt::qobject] + #[qproperty(i32, number)] + #[qproperty(QString, string)] + type MyData = super::MyDataRust; + #[qinvokable] fn as_json_str(self: &qobject::MyData) -> QString; @@ -70,9 +48,31 @@ use core::pin::Pin; use cxx_qt::CxxQtType; use cxx_qt_lib::QString; +pub struct MyDataRust { + pub number: i32, + pub string: QString, +} + +impl Default for MyDataRust { + fn default() -> Self { + let string = r#"{"number": 4, "string": "Hello World!"}"#; + let data_serde: DataSerde = serde_json::from_str(string).unwrap(); + data_serde.into() + } +} + +impl From for MyDataRust { + fn from(value: DataSerde) -> Self { + Self { + number: value.number, + string: QString::from(&value.string), + } + } +} + // TODO: this will change to qobject::MyData once // https://github.com/KDAB/cxx-qt/issues/559 is done -impl ffi::MyDataQt { +impl ffi::MyData { pub fn as_json_str(&self) -> QString { let data_serde = DataSerde::from(self.rust()); let data_string = serde_json::to_string(&data_serde).unwrap(); diff --git a/tests/basic_cxx_qt/rust/src/empty.rs b/tests/basic_cxx_qt/rust/src/empty.rs index 2448f3761..598b5d998 100644 --- a/tests/basic_cxx_qt/rust/src/empty.rs +++ b/tests/basic_cxx_qt/rust/src/empty.rs @@ -5,7 +5,11 @@ #[cxx_qt::bridge(cxx_file_stem = "empty")] mod ffi { - #[cxx_qt::qobject] - #[derive(Default)] - pub struct Empty; + extern "RustQt" { + #[cxx_qt::qobject] + type Empty = super::EmptyRust; + } } + +#[derive(Default)] +pub struct EmptyRust; diff --git a/tests/basic_cxx_qt/rust/src/lib.rs b/tests/basic_cxx_qt/rust/src/lib.rs index 5c8a0d40a..87b7ad951 100644 --- a/tests/basic_cxx_qt/rust/src/lib.rs +++ b/tests/basic_cxx_qt/rust/src/lib.rs @@ -17,24 +17,11 @@ mod ffi { type QString = cxx_qt_lib::QString; } - #[cxx_qt::qobject] - #[qproperty(i32, number)] - #[qproperty(QString, string)] - pub struct MyObject { - number: i32, - string: QString, - - pub(crate) update_call_count: i32, - } - - impl Default for MyObject { - fn default() -> Self { - Self { - number: 0, - string: QString::from(""), - update_call_count: 0, - } - } + unsafe extern "RustQt" { + #[cxx_qt::qobject] + #[qproperty(i32, number)] + #[qproperty(QString, string)] + type MyObject = super::MyObjectRust; } // Enabling threading on the qobject @@ -65,9 +52,26 @@ use core::pin::Pin; use cxx_qt::{CxxQtType, Threading}; use cxx_qt_lib::QString; +pub struct MyObjectRust { + number: i32, + string: QString, + + pub(crate) update_call_count: i32, +} + +impl Default for MyObjectRust { + fn default() -> Self { + Self { + number: 0, + string: QString::from(""), + update_call_count: 0, + } + } +} + // TODO: this will change to qobject::MyObject once // https://github.com/KDAB/cxx-qt/issues/559 is done -impl ffi::MyObjectQt { +impl ffi::MyObject { fn double_number_self(self: Pin<&mut Self>) { let value = self.number() * 2; self.set_number(value); diff --git a/tests/basic_cxx_qt/rust/src/locking.rs b/tests/basic_cxx_qt/rust/src/locking.rs index 10eea393c..8591f350d 100644 --- a/tests/basic_cxx_qt/rust/src/locking.rs +++ b/tests/basic_cxx_qt/rust/src/locking.rs @@ -6,16 +6,11 @@ /// Two QObject that allow for testing that locking works #[cxx_qt::bridge(cxx_file_stem = "locking")] pub mod ffi { - use std::sync::atomic::AtomicU32; - - /// A QObject which has cxx_qt::Locking - #[cxx_qt::qobject] - #[derive(Default)] - pub struct RustLockingEnabled { - pub(crate) counter: AtomicU32, - } - unsafe extern "RustQt" { + /// A QObject which has cxx_qt::Locking + #[cxx_qt::qobject] + type RustLockingEnabled = super::RustLockingEnabledRust; + #[qinvokable] fn get_counter(self: &qobject::RustLockingEnabled) -> u32; @@ -23,31 +18,37 @@ pub mod ffi { fn increment(self: Pin<&mut qobject::RustLockingEnabled>); } - /// A QObject which has !cxx_qt::Locking - #[cxx_qt::qobject] - #[derive(Default)] - pub struct RustLockingDisabled { - pub(crate) counter: AtomicU32, - } - - unsafe impl !cxx_qt::Locking for qobject::RustLockingDisabled {} - unsafe extern "RustQt" { + /// A QObject which has !cxx_qt::Locking + #[cxx_qt::qobject] + type RustLockingDisabled = super::RustLockingDisabledRust; + #[qinvokable] fn get_counter(self: &qobject::RustLockingDisabled) -> u32; #[qinvokable] fn increment(self: Pin<&mut qobject::RustLockingDisabled>); } + + unsafe impl !cxx_qt::Locking for qobject::RustLockingDisabled {} } use core::pin::Pin; use cxx_qt::CxxQtType; -use std::{sync::atomic::Ordering, thread, time::Duration}; +use std::{ + sync::atomic::{AtomicU32, Ordering}, + thread, + time::Duration, +}; + +#[derive(Default)] +pub struct RustLockingEnabledRust { + pub(crate) counter: AtomicU32, +} // TODO: this will change to qobject::RustLockingEnabled once // https://github.com/KDAB/cxx-qt/issues/559 is done -impl ffi::RustLockingEnabledQt { +impl ffi::RustLockingEnabled { fn get_counter(&self) -> u32 { self.rust().counter.load(Ordering::Acquire) } @@ -59,9 +60,14 @@ impl ffi::RustLockingEnabledQt { } } +#[derive(Default)] +pub struct RustLockingDisabledRust { + pub(crate) counter: AtomicU32, +} + // TODO: this will change to qobject::RustLockingDisabled once // https://github.com/KDAB/cxx-qt/issues/559 is done -impl ffi::RustLockingDisabledQt { +impl ffi::RustLockingDisabled { fn get_counter(&self) -> u32 { self.rust().counter.load(Ordering::Acquire) } diff --git a/tests/basic_cxx_qt/rust/src/types.rs b/tests/basic_cxx_qt/rust/src/types.rs index da09b7233..4b48b91d4 100644 --- a/tests/basic_cxx_qt/rust/src/types.rs +++ b/tests/basic_cxx_qt/rust/src/types.rs @@ -6,26 +6,30 @@ #[cxx_qt::bridge(cxx_file_stem = "my_types", namespace = "cxx_qt::my_types")] mod ffi { - #[cxx_qt::qobject] - #[derive(Default)] - #[qproperty(bool, boolean)] - #[qproperty(f32, float_32)] - #[qproperty(f64, float_64)] - #[qproperty(i8, int_8)] - #[qproperty(i16, int_16)] - #[qproperty(i32, int_32)] - #[qproperty(u8, uint_8)] - #[qproperty(u16, uint_16)] - #[qproperty(u32, uint_32)] - pub struct MyTypes { - boolean: bool, - float_32: f32, - float_64: f64, - int_8: i8, - int_16: i16, - int_32: i32, - uint_8: u8, - uint_16: u16, - uint_32: u32, + extern "RustQt" { + #[cxx_qt::qobject] + #[qproperty(bool, boolean)] + #[qproperty(f32, float_32)] + #[qproperty(f64, float_64)] + #[qproperty(i8, int_8)] + #[qproperty(i16, int_16)] + #[qproperty(i32, int_32)] + #[qproperty(u8, uint_8)] + #[qproperty(u16, uint_16)] + #[qproperty(u32, uint_32)] + type MyTypes = super::MyTypesRust; } } + +#[derive(Default)] +pub struct MyTypesRust { + boolean: bool, + float_32: f32, + float_64: f64, + int_8: i8, + int_16: i16, + int_32: i32, + uint_8: u8, + uint_16: u16, + uint_32: u32, +}