From 86eb41e58acfa0252d290abc64c89857f3e83946 Mon Sep 17 00:00:00 2001 From: Andrew Hayzen Date: Wed, 7 Jun 2023 18:30:58 +0100 Subject: [PATCH] WIP: cxx-qt-gen: use extern "RustQt" block for inherit and signals Closes #557 --- crates/cxx-qt-gen/src/parser/cxxqtdata.rs | 148 +++++++++--------- crates/cxx-qt-gen/src/parser/inherit.rs | 109 +------------ crates/cxx-qt-gen/src/parser/mod.rs | 12 +- crates/cxx-qt-gen/src/parser/signals.rs | 68 +------- crates/cxx-qt-gen/src/syntax/attribute.rs | 6 +- crates/cxx-qt-gen/test_inputs/inheritance.rs | 8 +- .../test_inputs/passthrough_and_naming.rs | 8 +- crates/cxx-qt-gen/test_inputs/signals.rs | 6 +- crates/cxx-qt-macro/src/lib.rs | 70 --------- crates/cxx-qt/src/lib.rs | 2 - examples/demo_threading/rust/src/lib.rs | 6 +- .../rust/src/custom_base_class.rs | 18 ++- .../rust/src/multiple_qobjects.rs | 10 +- .../qml_features/rust/src/nested_qobjects.rs | 8 +- .../qml_features/rust/src/serialisation.rs | 4 +- examples/qml_features/rust/src/signals.rs | 6 +- 16 files changed, 128 insertions(+), 361 deletions(-) diff --git a/crates/cxx-qt-gen/src/parser/cxxqtdata.rs b/crates/cxx-qt-gen/src/parser/cxxqtdata.rs index 92f30ff3b..96ddd26ff 100644 --- a/crates/cxx-qt-gen/src/parser/cxxqtdata.rs +++ b/crates/cxx-qt-gen/src/parser/cxxqtdata.rs @@ -4,18 +4,14 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 use crate::syntax::foreignmod::foreign_mod_to_foreign_item_types; +use crate::syntax::safety::Safety; use crate::syntax::{attribute::attribute_find_path, path::path_to_single_ident}; use crate::{ - parser::{ - inherit::{InheritMethods, ParsedInheritedMethod}, - qobject::ParsedQObject, - signals::{ParsedSignal, SignalMethods}, - }, + parser::{inherit::ParsedInheritedMethod, qobject::ParsedQObject, signals::ParsedSignal}, syntax::expr::expr_to_string, }; -use proc_macro2::TokenStream; -use quote::ToTokens; use std::collections::BTreeMap; +use syn::ForeignItem; use syn::{ spanned::Spanned, Attribute, Error, Ident, Item, ItemForeignMod, ItemImpl, Result, Type, TypePath, @@ -184,75 +180,60 @@ impl ParsedCxxQtData { } } - fn parse_inherit_mod(&mut self, tokens: TokenStream) -> Result<()> { - let inherited: InheritMethods = syn::parse2(tokens)?; - - self.add_inherited_methods(inherited) - } - - fn add_inherited_methods(&mut self, inherited: InheritMethods) -> Result<()> { - for method in inherited.base_functions.into_iter() { - let parsed_inherited_method = ParsedInheritedMethod::parse(method, inherited.safety)?; - - if let Some(ref mut qobject) = self - .qobjects - .get_mut(&parsed_inherited_method.qobject_ident) - { - qobject.inherited_methods.push(parsed_inherited_method); - } else { - return Err(Error::new_spanned( - parsed_inherited_method.qobject_ident, - "No QObject with this name found.", - )); + fn parse_foreign_mod(&mut self, foreign_mod: ItemForeignMod) -> Result> { + if let Some(lit_str) = &foreign_mod.abi.name { + match lit_str.value().as_str() { + "RustQt" => { + self.parse_foreign_mod_rust_qt(foreign_mod)?; + return Ok(None); + } + // TODO: look for "C++Qt" later + _others => {} } } - Ok(()) - } - - fn parse_signals_mod(&mut self, tokens: TokenStream) -> Result<()> { - let signals: SignalMethods = syn::parse2(tokens)?; - self.add_signal_methods(signals) - } - - fn add_signal_methods(&mut self, signals: SignalMethods) -> Result<()> { - for method in signals.base_functions.into_iter() { - let parsed_signal_method = ParsedSignal::parse(method, signals.safety)?; - - if let Some(ref mut qobject) = - self.qobjects.get_mut(&parsed_signal_method.qobject_ident) - { - qobject.signals.push(parsed_signal_method); - } else { - return Err(Error::new_spanned( - parsed_signal_method.qobject_ident, - "No QObject with this name found.", - )); - } - } - Ok(()) + Ok(Some(Item::ForeignMod(foreign_mod))) } - fn parse_foreign_mod(&mut self, mut foreign_mod: ItemForeignMod) -> Result> { - // Check if the foreign mod has cxx_qt::inherit on it - if let Some(index) = attribute_find_path(&foreign_mod.attrs, &["cxx_qt", "inherit"]) { - // Remove the inherit attribute - foreign_mod.attrs.remove(index); - - self.parse_inherit_mod(foreign_mod.into_token_stream())?; - return Ok(None); - } + fn parse_foreign_mod_rust_qt(&mut self, mut foreign_mod: ItemForeignMod) -> Result<()> { + let safe_call = if foreign_mod.unsafety.is_some() { + Safety::Safe + } else { + Safety::Unsafe + }; - // Check if the foreign mod has cxx_qt::qsignals on it - if let Some(index) = attribute_find_path(&foreign_mod.attrs, &["cxx_qt", "qsignals"]) { - // Remove the signals attribute - foreign_mod.attrs.remove(index); + for item in foreign_mod.items.drain(..) { + if let ForeignItem::Fn(mut foreign_fn) = item { + // Test if the function is a signal + if let Some(index) = attribute_find_path(&foreign_fn.attrs, &["qsignal"]) { + // Remove the signals attribute + foreign_fn.attrs.remove(index); + + let parsed_signal_method = ParsedSignal::parse(foreign_fn, safe_call)?; + + self.with_qobject(&parsed_signal_method.qobject_ident)? + .signals + .push(parsed_signal_method); + // Test if the function is an inheritance method + // + // Note that we need to test for qsignal first as qsignals have their own inherit meaning + } else if let Some(index) = attribute_find_path(&foreign_fn.attrs, &["inherit"]) { + // Remove the inherit attribute + foreign_fn.attrs.remove(index); + + let parsed_inherited_method = + ParsedInheritedMethod::parse(foreign_fn, safe_call)?; + + self.with_qobject(&parsed_inherited_method.qobject_ident)? + .inherited_methods + .push(parsed_inherited_method); + } - self.parse_signals_mod(foreign_mod.into_token_stream())?; - return Ok(None); + // TODO: test for qinvokable later + } } - Ok(Some(Item::ForeignMod(foreign_mod))) + Ok(()) } /// Parse a [syn::ItemImpl] into the qobjects if it's a CXX-Qt implementation @@ -287,6 +268,17 @@ impl ParsedCxxQtData { Ok(Some(Item::Impl(imp))) } + + fn with_qobject(&mut self, qobject_ident: &Ident) -> Result<&mut ParsedQObject> { + if let Some(qobject) = self.qobjects.get_mut(qobject_ident) { + Ok(qobject) + } else { + Err(Error::new_spanned( + qobject_ident, + "No QObject with this name found.", + )) + } + } } #[cfg(test)] @@ -732,17 +724,18 @@ mod tests { let mut cxxqtdata = create_parsed_cxx_qt_data(); let unsafe_block: Item = parse_quote! { - #[cxx_qt::inherit] - unsafe extern "C++" { + unsafe extern "RustQt" { + #[inherit] fn test(self: &qobject::MyObject); + #[inherit] fn with_args(self: &qobject::MyObject, arg: i32); } }; let safe_block: Item = parse_quote! { - #[cxx_qt::inherit] - extern "C++" { + extern "RustQt" { #[cxx_name="withRename"] + #[inherit] unsafe fn with_rename(self: Pin<&mut qobject::MyObject>, arg: i32); } }; @@ -771,12 +764,13 @@ mod tests { fn test_parse_qsignals_safe() { let mut cxxqtdata = create_parsed_cxx_qt_data(); let block: Item = parse_quote! { - #[cxx_qt::qsignals] - unsafe extern "C++" { + unsafe extern "RustQt" { + #[qsignal] fn ready(self: Pin<&mut qobject::MyObject>); #[cxx_name="cppDataChanged"] #[inherit] + #[qsignal] fn data_changed(self: Pin<&mut qobject::MyObject>, data: i32); } }; @@ -815,8 +809,8 @@ mod tests { fn test_parse_qsignals_unknown_obj() { let mut cxxqtdata = create_parsed_cxx_qt_data(); let block: Item = parse_quote! { - #[cxx_qt::qsignals] - unsafe extern "C++" { + unsafe extern "RustQt" { + #[qsignal] fn ready(self: Pin<&mut qobject::UnknownObj>); } }; @@ -827,8 +821,8 @@ mod tests { fn test_parse_qsignals_unsafe() { let mut cxxqtdata = create_parsed_cxx_qt_data(); let block: Item = parse_quote! { - #[cxx_qt::qsignals] - extern "C++" { + extern "RustQt" { + #[qsignal] unsafe fn unsafe_signal(self: Pin<&mut qobject::MyObject>, arg: *mut T); } }; diff --git a/crates/cxx-qt-gen/src/parser/inherit.rs b/crates/cxx-qt-gen/src/parser/inherit.rs index 6e0ae85ec..b33218a45 100644 --- a/crates/cxx-qt-gen/src/parser/inherit.rs +++ b/crates/cxx-qt-gen/src/parser/inherit.rs @@ -11,74 +11,9 @@ use crate::{ }, }; use quote::format_ident; -use syn::{ - parse::{Parse, ParseStream}, - spanned::Spanned, - Attribute, Error, ForeignItem, ForeignItemFn, Ident, ItemForeignMod, LitStr, Result, Token, -}; - -/// This type is used when parsing the `#[cxx_qt::inherit]` macro contents into raw ForeignItemFn items -pub struct InheritMethods { - pub safety: Safety, - pub base_functions: Vec, -} - -impl Parse for InheritMethods { - fn parse(input: ParseStream) -> Result { - let mut base_functions = Vec::new(); - - // Ensure that any attributes on the block have been removed - // - // Otherwise parsing of unsafe can fail due to #[doc] - let attrs = input.call(Attribute::parse_outer)?; - if !attrs.is_empty() { - return Err(Error::new( - attrs.first().span(), - "Unexpected attribute on #[cxx_qt::qsignals] block.", - )); - } - - // This looks somewhat counter-intuitive, but if we add `unsafe` - // to the `extern "C++"` block, the contained functions will be safe to call. - let safety = if input.peek(Token![unsafe]) { - Safety::Safe - } else { - Safety::Unsafe - }; - if safety == Safety::Safe { - input.parse::()?; - } - - let extern_block = input.parse::()?; - if extern_block.abi.name != Some(LitStr::new("C++", extern_block.abi.span())) { - return Err(Error::new( - extern_block.abi.span(), - "Inherit blocks must be marked with `extern \"C++\"`", - )); - } - - for item in extern_block.items { - match item { - ForeignItem::Fn(function) => { - base_functions.push(function); - } - _ => { - return Err(Error::new( - item.span(), - "Only functions are allowed in #[cxx_qt::inherit] blocks", - )) - } - } - } +use syn::{spanned::Spanned, Error, ForeignItemFn, Ident, Result}; - Ok(InheritMethods { - safety, - base_functions, - }) - } -} - -/// Describes a method found in #[cxx_qt::inherit] +/// Describes a method found in an extern "RustQt" with #[inherit] pub struct ParsedInheritedMethod { /// The original [syn::ForeignItemFn] of the inherited method declaration pub method: ForeignItemFn, @@ -141,46 +76,8 @@ impl ParsedInheritedMethod { #[cfg(test)] mod tests { use super::*; - use quote::quote; - use syn::parse_quote; - - #[test] - fn test_parse_unsafe_mod() { - let module = quote! { - extern "C++" { - unsafe fn test(self: &qobject::T); - } - }; - let parsed: InheritMethods = syn::parse2(module).unwrap(); - assert_eq!(parsed.base_functions.len(), 1); - assert_eq!(parsed.safety, Safety::Unsafe); - } - #[test] - fn test_parse_safe_mod() { - let module = quote! { - unsafe extern "C++" { - fn test(self: &qobject::T); - unsafe fn test2(self: &qobject::T); - } - }; - let parsed: InheritMethods = syn::parse2(module).unwrap(); - assert_eq!(parsed.base_functions.len(), 2); - assert_eq!(parsed.safety, Safety::Safe); - } - - #[test] - fn test_parse_attributes() { - let module = quote! { - unsafe extern "C++" { - #[attribute] - fn test(self: &qobject::T); - } - }; - let parsed: InheritMethods = syn::parse2(module).unwrap(); - assert_eq!(parsed.base_functions.len(), 1); - assert_eq!(parsed.base_functions[0].attrs.len(), 1); - } + use syn::parse_quote; fn assert_parse_error(function: ForeignItemFn) { let result = ParsedInheritedMethod::parse(function, Safety::Safe); diff --git a/crates/cxx-qt-gen/src/parser/mod.rs b/crates/cxx-qt-gen/src/parser/mod.rs index 01240e5c9..fe3ee11bd 100644 --- a/crates/cxx-qt-gen/src/parser/mod.rs +++ b/crates/cxx-qt-gen/src/parser/mod.rs @@ -162,8 +162,8 @@ mod tests { #[cxx_qt::qobject] pub struct MyObject; - #[cxx_qt::qsignals] - unsafe extern "C++" { + unsafe extern "RustQt" { + #[qsignal] fn ready(self: Pin<&mut qobject::MyObject>); } } @@ -187,8 +187,8 @@ mod tests { #[cxx_qt::qobject] pub struct MyObject; - #[cxx_qt::qsignals] - unsafe extern "C++" { + unsafe extern "RustQt" { + #[qsignal] fn ready(self: Pin<&mut qobject::MyObject>); } @@ -216,8 +216,8 @@ mod tests { #[cxx_qt::qobject] pub struct MyObject; - #[cxx_qt::qsignals] - unsafe extern "C++" { + unsafe extern "RustQt" { + #[qsignal] fn ready(self: Pin<&mut qobject::UnknownObject>); } } diff --git a/crates/cxx-qt-gen/src/parser/signals.rs b/crates/cxx-qt-gen/src/parser/signals.rs index ae7830cb7..dc0720286 100644 --- a/crates/cxx-qt-gen/src/parser/signals.rs +++ b/crates/cxx-qt-gen/src/parser/signals.rs @@ -10,73 +10,7 @@ use crate::syntax::foreignmod; use crate::syntax::safety::Safety; use crate::{generator::naming::CombinedIdent, syntax::types}; use quote::format_ident; -use syn::Attribute; -use syn::{ - parse::{Parse, ParseStream}, - spanned::Spanned, - Error, ForeignItem, ForeignItemFn, Ident, ItemForeignMod, LitStr, Result, Token, -}; - -/// This type is used when parsing the `#[cxx_qt::qsignals]` macro contents into raw ForeignItemFn items -pub struct SignalMethods { - pub safety: Safety, - pub base_functions: Vec, -} - -impl Parse for SignalMethods { - fn parse(input: ParseStream) -> Result { - let mut base_functions = Vec::new(); - - // Ensure that any attributes on the block have been removed - // - // Otherwise parsing of unsafe can fail due to #[doc] - let attrs = input.call(Attribute::parse_outer)?; - if !attrs.is_empty() { - return Err(Error::new( - attrs.first().span(), - "Unexpected attribute on #[cxx_qt::inherit] block.", - )); - } - - // This looks somewhat counter-intuitive, but if we add `unsafe` - // to the `extern "C++"` block, the contained functions will be safe to call. - let safety = if input.peek(Token![unsafe]) { - Safety::Safe - } else { - Safety::Unsafe - }; - if safety == Safety::Safe { - input.parse::()?; - } - - let extern_block = input.parse::()?; - if extern_block.abi.name != Some(LitStr::new("C++", extern_block.abi.span())) { - return Err(Error::new( - extern_block.abi.span(), - "qsignals blocks must be marked with `extern \"C++\"`", - )); - } - - for item in extern_block.items { - match item { - ForeignItem::Fn(function) => { - base_functions.push(function); - } - _ => { - return Err(Error::new( - item.span(), - "Only functions are allowed in #[cxx_qt::qsignals] blocks", - )) - } - } - } - - Ok(SignalMethods { - safety, - base_functions, - }) - } -} +use syn::{spanned::Spanned, Error, ForeignItemFn, Ident, Result}; /// Describes an individual Signal pub struct ParsedSignal { diff --git a/crates/cxx-qt-gen/src/syntax/attribute.rs b/crates/cxx-qt-gen/src/syntax/attribute.rs index 4d17dfb89..a8bac4307 100644 --- a/crates/cxx-qt-gen/src/syntax/attribute.rs +++ b/crates/cxx-qt-gen/src/syntax/attribute.rs @@ -97,14 +97,14 @@ mod tests { let module: ItemMod = parse_quote! { #[qinvokable] #[cxx_qt::bridge] - #[cxx_qt::qsignals(MyObject)] + #[cxx_qt::object(MyObject)] #[cxx_qt::bridge(namespace = "my::namespace")] mod module; }; assert!(attribute_find_path(&module.attrs, &["qinvokable"]).is_some()); assert!(attribute_find_path(&module.attrs, &["cxx_qt", "bridge"]).is_some()); - assert!(attribute_find_path(&module.attrs, &["cxx_qt", "qsignals"]).is_some()); + assert!(attribute_find_path(&module.attrs, &["cxx_qt", "object"]).is_some()); assert!(attribute_find_path(&module.attrs, &["cxx_qt", "missing"]).is_none()); } @@ -113,7 +113,7 @@ mod tests { let module: ItemMod = parse_quote! { #[qinvokable] #[cxx_qt::bridge] - #[cxx_qt::qsignals(MyObject)] + #[cxx_qt::object(MyObject)] #[cxx_qt::bridge(namespace = "my::namespace")] #[cxx_qt::list(A, B, C)] #[cxx_qt::bridge(a = "b", namespace = "my::namespace")] diff --git a/crates/cxx-qt-gen/test_inputs/inheritance.rs b/crates/cxx-qt-gen/test_inputs/inheritance.rs index feed2de87..b076f261a 100644 --- a/crates/cxx-qt-gen/test_inputs/inheritance.rs +++ b/crates/cxx-qt-gen/test_inputs/inheritance.rs @@ -13,16 +13,16 @@ mod inheritance { data: Vec, } - #[cxx_qt::inherit] - unsafe extern "C++" { + unsafe extern "RustQt" { /// Inherited hasChildren from the base class #[cxx_name = "hasChildren"] + #[inherit] fn has_children_super(self: &qobject::MyObject, parent: &QModelIndex) -> bool; } - #[cxx_qt::inherit] - extern "C++" { + extern "RustQt" { /// Inherited fetchMore from the base class + #[inherit] unsafe fn fetch_more(self: Pin<&mut qobject::MyObject>, index: &QModelIndex); } 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 823dc1325..4929b9b87 100644 --- a/crates/cxx-qt-gen/test_inputs/passthrough_and_naming.rs +++ b/crates/cxx-qt-gen/test_inputs/passthrough_and_naming.rs @@ -91,8 +91,8 @@ pub mod ffi { } } - #[cxx_qt::qsignals] - unsafe extern "C++" { + unsafe extern "RustQt" { + #[qsignal] fn ready(self: Pin<&mut qobject::MyObject>); } @@ -140,9 +140,9 @@ pub mod ffi { } } - #[cxx_qt::qsignals] - unsafe extern "C++" { + unsafe extern "RustQt" { #[my_attribute] + #[qsignal] fn ready(self: Pin<&mut qobject::SecondObject>); } diff --git a/crates/cxx-qt-gen/test_inputs/signals.rs b/crates/cxx-qt-gen/test_inputs/signals.rs index 21b92e184..94d86a084 100644 --- a/crates/cxx-qt-gen/test_inputs/signals.rs +++ b/crates/cxx-qt-gen/test_inputs/signals.rs @@ -6,10 +6,11 @@ mod ffi { type QPoint = cxx_qt_lib::QPoint; } - #[cxx_qt::qsignals] - unsafe extern "C++" { + unsafe extern "RustQt" { + #[qsignal] fn ready(self: Pin<&mut qobject::MyObject>); + #[qsignal] fn data_changed( self: Pin<&mut qobject::MyObject>, first: i32, @@ -20,6 +21,7 @@ mod ffi { #[cxx_name = "newData"] #[inherit] + #[qsignal] fn base_class_new_data( self: Pin<&mut qobject::MyObject>, first: i32, diff --git a/crates/cxx-qt-macro/src/lib.rs b/crates/cxx-qt-macro/src/lib.rs index 859d44085..6a110fb89 100644 --- a/crates/cxx-qt-macro/src/lib.rs +++ b/crates/cxx-qt-macro/src/lib.rs @@ -57,34 +57,6 @@ pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream { extract_and_generate(module) } -/// A macro which describes that an enum defines the signals for a QObject. -/// -/// It should not be used by itself and instead should be used inside a cxx_qt::bridge definition. -/// -/// # Example -/// -/// ```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; -/// -/// #[cxx_qt::qsignals] -/// unsafe extern "C++" { -/// fn ready(self: Pin<&mut qobject::MyObject>); -/// } -/// } -/// -/// # // Note that we need a fake main for doc tests to build -/// # fn main() {} -/// ``` -#[proc_macro_attribute] -pub fn qsignals(_args: TokenStream, _input: TokenStream) -> TokenStream { - unreachable!("cxx_qt::qsignals should not be used as a macro by itself. Instead it should be used within a cxx_qt::bridge definition") -} - /// A macro which describes that a struct should be made into a QObject. /// /// It should not be used by itself and instead should be used inside a cxx_qt::bridge definition. @@ -129,48 +101,6 @@ pub fn qobject(_args: TokenStream, _input: TokenStream) -> TokenStream { unreachable!("cxx_qt::qobject should not be used as a macro by itself. Instead it should be used within a cxx_qt::bridge definition") } -/// A macro which allows you to access base class methods from within Rust. -/// -/// It should not be used by itself and instead should be used inside a cxx_qt::bridge definition. -/// Furthermore, the macro must be placed within the `impl` block of a `qobject::T`. -/// See [the book page](https://kdab.github.io/cxx-qt/book/concepts/inheritance.html) for more -/// details. -/// -/// # Example -/// ``` rust -/// #[cxx_qt::bridge] -/// mod my_object { -/// extern "C++" { -/// include!("cxx-qt-lib/qmodelindex.h"); -/// type QModelIndex = cxx_qt_lib::QModelIndex; -/// } -/// -/// #[cxx_qt::qobject(base="QAbstractListModel")] -/// #[derive(Default)] -/// # // Note that we can't use properties as this confuses the linker on Windows -/// pub struct MyObject; -/// -/// #[cxx_qt::inherit] -/// extern "C++" { -/// // Unsafe to call -/// unsafe fn begin_insert_rows(self: Pin<&mut qobject::MyObject>, parent: &QModelIndex, first: i32, last: i32); -/// } -/// -/// #[cxx_qt::inherit] -/// unsafe extern "C++" { -/// // Safe to call - you are responsible to ensure this is true! -/// fn end_insert_rows(self: Pin<&mut qobject::MyObject>); -/// } -/// } -/// -/// # // Note that we need a fake main for doc tests to build -/// # fn main() {} -/// ``` -#[proc_macro_attribute] -pub fn inherit(_args: TokenStream, _input: TokenStream) -> TokenStream { - unreachable!("cxx_qt::inherit should not be used as a macro by itself. Instead it should be used within a cxx_qt::bridge definition") -} - // Take the module and C++ namespace and generate the rust code fn extract_and_generate(module: ItemMod) -> TokenStream { Parser::from(module) diff --git a/crates/cxx-qt/src/lib.rs b/crates/cxx-qt/src/lib.rs index f1bc2bfe5..831d88b0d 100644 --- a/crates/cxx-qt/src/lib.rs +++ b/crates/cxx-qt/src/lib.rs @@ -10,9 +10,7 @@ //! See the [book](https://kdab.github.io/cxx-qt/book/) for more information. pub use cxx_qt_macro::bridge; -pub use cxx_qt_macro::inherit; pub use cxx_qt_macro::qobject; -pub use cxx_qt_macro::qsignals; /// This trait is automatically implemented for all types which are marked as `#[cxx_qt::qobject]`. /// It provides information about the type that is wrapped by the QObject, as well as the methods diff --git a/examples/demo_threading/rust/src/lib.rs b/examples/demo_threading/rust/src/lib.rs index 8c766c8cd..0e17bbfdc 100644 --- a/examples/demo_threading/rust/src/lib.rs +++ b/examples/demo_threading/rust/src/lib.rs @@ -70,13 +70,15 @@ mod ffi { // Enabling threading on the qobject impl cxx_qt::Threading for qobject::EnergyUsage {} - #[cxx_qt::qsignals] - unsafe extern "C++" { + unsafe extern "RustQt" { /// A new sensor has been detected + #[qsignal] fn sensor_added(self: Pin<&mut qobject::EnergyUsage>, uuid: QString); /// A value on an existing sensor has changed + #[qsignal] fn sensor_changed(self: Pin<&mut qobject::EnergyUsage>, uuid: QString); /// An existing sensor has been removed + #[qsignal] fn sensor_removed(self: Pin<&mut qobject::EnergyUsage>, uuid: QString); } diff --git a/examples/qml_features/rust/src/custom_base_class.rs b/examples/qml_features/rust/src/custom_base_class.rs index 3e8d5d314..17d70b25d 100644 --- a/examples/qml_features/rust/src/custom_base_class.rs +++ b/examples/qml_features/rust/src/custom_base_class.rs @@ -51,10 +51,10 @@ pub mod ffi { impl cxx_qt::Threading for qobject::CustomBaseClass {} // ANCHOR: book_qsignals_inherit - #[cxx_qt::qsignals] - unsafe extern "C++" { + unsafe extern "RustQt" { /// Inherit the DataChanged signal from the QAbstractListModel base class #[inherit] + #[qsignal] fn data_changed( self: Pin<&mut qobject::CustomBaseClass>, top_left: &QModelIndex, @@ -153,9 +153,9 @@ pub mod ffi { // ANCHOR: book_inherit_qalm_impl_unsafe // Create Rust bindings for C++ functions of the base class (QAbstractItemModel) - #[cxx_qt::inherit] - extern "C++" { + extern "RustQt" { /// Inherited beginInsertRows from the base class + #[inherit] unsafe fn begin_insert_rows( self: Pin<&mut qobject::CustomBaseClass>, parent: &QModelIndex, @@ -163,9 +163,11 @@ pub mod ffi { last: i32, ); /// Inherited endInsertRows from the base class + #[inherit] unsafe fn end_insert_rows(self: Pin<&mut qobject::CustomBaseClass>); /// Inherited beginRemoveRows from the base class + #[inherit] unsafe fn begin_remove_rows( self: Pin<&mut qobject::CustomBaseClass>, parent: &QModelIndex, @@ -173,23 +175,27 @@ pub mod ffi { last: i32, ); /// Inherited endRemoveRows from the base class + #[inherit] unsafe fn end_remove_rows(self: Pin<&mut qobject::CustomBaseClass>); /// Inherited beginResetModel from the base class + #[inherit] unsafe fn begin_reset_model(self: Pin<&mut qobject::CustomBaseClass>); /// Inherited endResetModel from the base class + #[inherit] unsafe fn end_reset_model(self: Pin<&mut qobject::CustomBaseClass>); } // ANCHOR_END: book_inherit_qalm_impl_unsafe // ANCHOR: book_inherit_qalm_impl_safe - #[cxx_qt::inherit] - unsafe extern "C++" { + unsafe extern "RustQt" { /// Inherited canFetchMore from the base class #[cxx_name = "canFetchMore"] + #[inherit] fn base_can_fetch_more(self: &qobject::CustomBaseClass, parent: &QModelIndex) -> bool; /// Inherited index from the base class + #[inherit] fn index( self: &qobject::CustomBaseClass, row: i32, diff --git a/examples/qml_features/rust/src/multiple_qobjects.rs b/examples/qml_features/rust/src/multiple_qobjects.rs index 899a023df..18bae1eff 100644 --- a/examples/qml_features/rust/src/multiple_qobjects.rs +++ b/examples/qml_features/rust/src/multiple_qobjects.rs @@ -38,12 +38,13 @@ pub mod ffi { // Enabling threading on the qobject impl cxx_qt::Threading for qobject::FirstObject {} - #[cxx_qt::qsignals] - unsafe extern "C++" { + unsafe extern "RustQt" { /// Accepted Q_SIGNAL + #[qsignal] fn accepted(self: Pin<&mut qobject::FirstObject>); /// Rejected Q_SIGNAL + #[qsignal] fn rejected(self: Pin<&mut qobject::FirstObject>); } @@ -85,12 +86,13 @@ pub mod ffi { // Enabling threading on the qobject impl cxx_qt::Threading for qobject::SecondObject {} - #[cxx_qt::qsignals] - unsafe extern "C++" { + unsafe extern "RustQt" { /// Accepted Q_SIGNAL + #[qsignal] fn accepted(self: Pin<&mut qobject::SecondObject>); /// Rejected Q_SIGNAL + #[qsignal] fn rejected(self: Pin<&mut qobject::SecondObject>); } diff --git a/examples/qml_features/rust/src/nested_qobjects.rs b/examples/qml_features/rust/src/nested_qobjects.rs index df9e014f8..fbecbea97 100644 --- a/examples/qml_features/rust/src/nested_qobjects.rs +++ b/examples/qml_features/rust/src/nested_qobjects.rs @@ -25,9 +25,9 @@ pub mod ffi { counter: i32, } - #[cxx_qt::qsignals] - extern "C++" { + extern "RustQt" { /// A signal showing how to refer to another QObject as an argument + #[qsignal] unsafe fn called(self: Pin<&mut qobject::InnerObject>, inner: *mut CxxInnerObject); } @@ -46,9 +46,9 @@ pub mod ffi { } } - #[cxx_qt::qsignals] - extern "C++" { + extern "RustQt" { /// A signal showing how to refer to another QObject as an argument + #[qsignal] unsafe fn called(self: Pin<&mut qobject::OuterObject>, inner: *mut CxxInnerObject); } diff --git a/examples/qml_features/rust/src/serialisation.rs b/examples/qml_features/rust/src/serialisation.rs index a1092f348..4d3bf2e61 100644 --- a/examples/qml_features/rust/src/serialisation.rs +++ b/examples/qml_features/rust/src/serialisation.rs @@ -48,9 +48,9 @@ pub mod ffi { pub string: QString, } - #[cxx_qt::qsignals] - unsafe extern "C++" { + unsafe extern "RustQt" { /// An error signal + #[qsignal] fn error(self: Pin<&mut qobject::Serialisation>, message: QString); } diff --git a/examples/qml_features/rust/src/signals.rs b/examples/qml_features/rust/src/signals.rs index 33132e90f..baa898479 100644 --- a/examples/qml_features/rust/src/signals.rs +++ b/examples/qml_features/rust/src/signals.rs @@ -21,15 +21,17 @@ pub mod ffi { } // ANCHOR: book_signals_block - #[cxx_qt::qsignals] - unsafe extern "C++" { + unsafe extern "RustQt" { /// A Q_SIGNAL emitted when a connection occurs + #[qsignal] fn connected(self: Pin<&mut qobject::RustSignals>, url: &QUrl); /// A Q_SIGNAL emitted when a disconnect occurs + #[qsignal] fn disconnected(self: Pin<&mut qobject::RustSignals>); /// A Q_SIGNAL emitted when an error occurs + #[qsignal] fn error(self: Pin<&mut qobject::RustSignals>, message: QString); } // ANCHOR_END: book_signals_block