diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 614ea9a60..1323a0123 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -19,7 +19,7 @@ SPDX-License-Identifier: MIT OR Apache-2.0 - [Building with Cargo](./getting-started/5-cargo-executable.md) - [QObject](./qobject/index.md) - [`#[cxx_qt::bridge]` - Bridge Macro](./qobject/bridge-macro.md) - - [`#[cxx_qt::qobject]` - Defining QObjects](./qobject/qobject_struct.md) + - [`#[qobject]` - Defining QObjects](./qobject/qobject_struct.md) - [`#[qsignal]` - Signal macro](./qobject/signals.md) - [`qobject::T` - The generated QObject](./qobject/generated-qobject.md) - [CxxQtThread](./qobject/cxxqtthread.md) diff --git a/book/src/concepts/inheritance.md b/book/src/concepts/inheritance.md index 90d071b5a..568714650 100644 --- a/book/src/concepts/inheritance.md +++ b/book/src/concepts/inheritance.md @@ -33,7 +33,7 @@ For this, the `clear` method implemented in Rust needs to call `beginResetModel` See [the Qt docs](https://doc.qt.io/qt-6/qabstractlistmodel.html) for more details on the specific subclassing requirements. Methods in a `extern "RustQt"` block similar to CXX can be tagged with an `#[inherit]` attribute, with the same restrictions regarding which types can be used. -Additionally, the `self` type must be either `self: Pin<&mut qobject::T>` or `self: &qobject::T`, where `qobject::T` must refer to a QObject marked with `#[cxx_qt::qobject]` in the `#[cxx_qt::bridge]` +Additionally, the `self` type must be either `self: Pin<&mut qobject::T>` or `self: &qobject::T`, where `qobject::T` must refer to a QObject marked with `#[qobject]` in the `#[cxx_qt::bridge]` The declared methods will be case-converted as in other CXX-Qt APIs. To explicitly declare the C++ method name, use the `#[cxx_name="myFunctionName"]` attribute. diff --git a/book/src/getting-started/1-qobjects-in-rust.md b/book/src/getting-started/1-qobjects-in-rust.md index 3fddf4d99..0f29faa62 100644 --- a/book/src/getting-started/1-qobjects-in-rust.md +++ b/book/src/getting-started/1-qobjects-in-rust.md @@ -44,14 +44,14 @@ These concepts include: As with CXX, to use these features you mark a Rust module with an attribute macro (`#[cxx_qt::bridge]`). Then you can use the afformentioned features with the help of more macros. -- `#[cxx_qt::qobject]` - Expose a Rust struct to Qt as a QObject subclass. +- `#[qobject]` - Expose a Rust struct to Qt as a QObject subclass. - `#[qproperty]` - Expose a field of the Rust struct to QML/C++ as a [`Q_PROPERTY`](https://doc.qt.io/qt-6/qtqml-cppintegration-exposecppattributes.html#exposing-properties). - `#[qinvokable]` - Expose a function on the QObject to QML and C++ as a [`Q_INVOKABLE`](https://doc.qt.io/qt-6/qtqml-cppintegration-exposecppattributes.html#exposing-methods-including-qt-slots). - `#[qsignal]` - Define the [Signals](https://doc.qt.io/qt-6/signalsandslots.html#signals) of a QObject T. CXX-Qt will then expand this Rust module into two separate parts: -- C++ files that define a QObject subclass for each `#[cxx_qt::qobject]` marked struct. -- The Rust code for the `#[cxx_qt::qobject]` marked Rust struct +- C++ files that define a QObject subclass for each `#[qobject]` marked struct. +- The Rust code for the `#[qobject]` marked Rust struct
@@ -59,11 +59,11 @@ CXX-Qt will then expand this Rust module into two separate parts:
-CXX-Qt also generates the code needed for interaction of the C++ QObject subclass and the `#[cxx_qt::qobject]` marked struct using the [CXX library](https://cxx.rs/). +CXX-Qt also generates the code needed for interaction of the C++ QObject subclass and the `#[qobject]` marked struct using the [CXX library](https://cxx.rs/). For more details, see the [Concepts: Bridge](../concepts/bridge.md) page. The important take away here is the duality of any subclass generated by CXX-Qt. -These classes are made up of the actual QObject subclass instance that C++ interacts with, as well as an instance of the `#[cxx_qt::qobject]` marked struct on the Rust side. +These classes are made up of the actual QObject subclass instance that C++ interacts with, as well as an instance of the `#[qobject]` marked struct on the Rust side. When such a QObject is instantiated, it will always also construct an instance of the Rust struct as well. The lifetime of the Rust struct will be bound to that of the QObject. If the QObject is deleted, the Rust struct will be deleted as well. diff --git a/book/src/getting-started/2-our-first-cxx-qt-module.md b/book/src/getting-started/2-our-first-cxx-qt-module.md index cd970ab87..341195fb8 100644 --- a/book/src/getting-started/2-our-first-cxx-qt-module.md +++ b/book/src/getting-started/2-our-first-cxx-qt-module.md @@ -52,13 +52,13 @@ Additionally, a `#[cxx_qt::bridge]` gives you a few more features that allow you ## QObject struct -To create a new QObject subclass, we can define a struct within our module and mark it with `#[cxx_qt::qobject]`. +To create a new QObject subclass, we can define a struct within our module and mark it with `#[qobject]`. ```rust,ignore {{#include ../../../examples/qml_minimal/rust/src/cxxqt_object.rs:book_rustobj_struct}} ``` -Optionally, add `qml_uri` and `qml_version` inside `#[cxx_qt::qobject]` to tell the Rust build script to generate a QML plugin +Optionally, add `qml_uri` and `qml_version` inside `#[qobject]` to tell the Rust build script to generate a QML plugin that will register the QObject with QML engine at startup. If you want the name of the QML type and the Rust type to be different, you can also add `qml_name = "OtherName"`. This takes the place of the [qt_add_qml_module CMake function](https://doc.qt.io/qt-6/qt-add-qml-module.html) (because that doesn't work with CXX-Qt's build system). @@ -92,7 +92,7 @@ For more details on the available types, see the [Qt types page](../concepts/typ ## qobject::T CXX-Qt will then automatically generate a new QObject subclass for our `MyObject` struct and expose it as an [`extern "C++"` opaque type](https://cxx.rs/extern-c++.html#opaque-c-types) to Rust. -For any Rust struct `T` that is marked with `#[cxx_qt::qobject]`, CXX-Qt will expose the corresponding C++ QObject under `qobject::T`. +For any Rust struct `T` that is marked with `#[qobject]`, CXX-Qt will expose the corresponding C++ QObject under `qobject::T`. In our case, this means we can refer to the C++ QObject for our `MyObject` struct, as `qobject::MyObject`. This type can be used like any other CXX opaque type. diff --git a/book/src/qobject/generated-qobject.md b/book/src/qobject/generated-qobject.md index de45584bb..cdef3fd03 100644 --- a/book/src/qobject/generated-qobject.md +++ b/book/src/qobject/generated-qobject.md @@ -8,10 +8,10 @@ SPDX-License-Identifier: MIT OR Apache-2.0 # `qobject::T` - The generated QObject One of the key features of CXX-Qt is the ability to create your own QObjects from Rust. -This is what the [`#[cxx_qt::qobject]` macro](./qobject_struct.md) is for. +This is what the [`#[qobject]` macro](./qobject_struct.md) is for. This page serves to document the details of what is generated and how to interact with the generated QObject from Rust. -The `#[cxx_qt::qobject]` macro generates a QObject for a given Rust struct. +The `#[qobject]` macro generates a QObject for a given Rust struct. Whilst this QObject is a C++ type, CXX-Qt will automatically wrap it as a [CXX Opaque Type](https://cxx.rs/extern-c++.html#opaque-c-types). These generated QObjects are accessible to Rust in a generated module with the name `qobject`. Each struct `T`'s generated QObject is accessible as `qobject::T`. @@ -37,7 +37,7 @@ Example: // In file qt_types.rs #[cxx_qt::bridge] mod ffi { - #[cxx_qt::qobject] + #[qobject] #[derive(Default)] pub struct MyObject {} } @@ -89,7 +89,7 @@ There is also an advanced way to access the data in the internal Rust struct: fn rust(&self) -> &T fn rust_mut(self: Pin<&mut Self>) -> &mut T ``` -Where `T` is the struct with the `#[cxx_qt::qobject]` macro. +Where `T` is the struct with the `#[qobject]` macro. This allows you to directly manipulate the internal Rust struct without having to use the generated accessor methods. diff --git a/book/src/qobject/index.md b/book/src/qobject/index.md index 345f5b4e5..623b603da 100644 --- a/book/src/qobject/index.md +++ b/book/src/qobject/index.md @@ -14,7 +14,7 @@ For a simpler introduction, take a look at our [Getting Started guide](../gettin QObject Features and Parts: * [`#[cxx_qt::bridge]` - The macro around the module](./bridge-macro.md) - * [`#[cxx_qt::qobject]` - Marking a Rust struct as a QObject](./qobject_struct.md) + * [`#[qobject]` - Marking a Rust struct as a QObject](./qobject_struct.md) * [`#[qsignal]` - A macro for defining signals](./signals.md) * [`qobject:T` - The generated QObject](./generated-qobject.md) * [`CxxQtThread` - Queueing closures onto the Qt event loop](./cxxqtthread.md) diff --git a/book/src/qobject/qobject_struct.md b/book/src/qobject/qobject_struct.md index 6eba2ca75..f89a73a3a 100644 --- a/book/src/qobject/qobject_struct.md +++ b/book/src/qobject/qobject_struct.md @@ -5,14 +5,14 @@ SPDX-FileContributor: Andrew Hayzen SPDX-License-Identifier: MIT OR Apache-2.0 --> -# `#[cxx_qt::qobject]` Macro - Defining QObjects in Rust +# `#[qobject]` Macro - Defining QObjects in Rust Defining QObjects is at the heart of CXX-Qt. -Therefore `#[cxx_qt::qobject]` can be considered the most important macro in CXX-Qt. +Therefore `#[qobject]` can be considered the most important macro in CXX-Qt. ## Requirements - Like most other CXX-Qt macros, it can only be used from within a [`#[cxx_qt::bridge]`](./bridge-macro.md). -- The `#[cxx_qt::qobject]` macro must be placed on a Rust struct. +- The `#[qobject]` macro must be placed on a Rust struct. - The struct must [`impl Default`](#default), so that it can be constructed as part of a QObject. ## Effects @@ -30,10 +30,10 @@ The macro does multiple other things for you though: - Generate signals if paired with a [`#[qsignal]` macro](./signals.md). ## Exposing to QML -`#[cxx_qt::qobject]` supports registering the Qt object as a QML type directly at build time. +`#[qobject]` supports registering the Qt object as a QML type directly at build time. This is comparable to [adding `QML_ELEMENT` in C++](https://doc.qt.io/qt-6/qtqml-cppintegration-definetypes.html). -For this, add the `qml_uri` and `qml_version` attributes to the `#[cxx_qt::qobject]` macro. +For this, add the `qml_uri` and `qml_version` attributes to the `#[qobject]` macro. ``` rust,ignore,noplayground {{#include ../../../examples/qml_minimal/rust/src/cxxqt_object.rs:book_rustobj_struct}} ``` @@ -65,7 +65,7 @@ For more information on inheritance and how to override methods see the [Inherit ## Properties -Fields within the `#[cxx_qt::qobject]` marked struct can be tagged with `#[qproperty]` to be exposed as [`Q_PROPERTY`s](https://doc.qt.io/qt-6/properties.html) on the generated QObject: +Fields within the `#[qobject]` marked struct can be tagged with `#[qproperty]` to be exposed as [`Q_PROPERTY`s](https://doc.qt.io/qt-6/properties.html) on the generated QObject: ```rust,ignore,noplayground {{#include ../../../examples/qml_features/rust/src/properties.rs:book_properties_struct}} @@ -95,7 +95,7 @@ See the [Private fields section](#private-methods-and-fields) ## Default -The [`Default` trait](https://doc.rust-lang.org/std/default/trait.Default.html) needs to be implemented for the `#[cxx_qt::qobject]` marked struct either by hand or by using the derive macro `#[derive(Default)]`. +The [`Default` trait](https://doc.rust-lang.org/std/default/trait.Default.html) needs to be implemented for the `#[qobject]` marked struct either by hand or by using the derive macro `#[derive(Default)]`. This needs to provide default values for every [`#[qproperty]`](#properties) and [private field](#private-methods-and-fields) @@ -114,7 +114,7 @@ CXX-Qt allows you to define invokables using Rust code. This way you can easily add a Rust-powered backend to your QML frontend. Invokables, by definition, must be defined on a C++ class however. -This is where the QObject subclass generated by `#[cxx_qt::qobject]` comes into play. +This is where the QObject subclass generated by `#[qobject]` comes into play. For details on this, see the [`qobject::T` page](./generated-qobject.md). The important part for invokables is that they need to be implemented on the `qobject::T`, not `T`. @@ -144,7 +144,7 @@ These are normal Rust methods, so they aren't restricted to CXX-compatible types ## Private Methods and Fields -Fields within your `#[cxx_qt::qobject]` struct that aren't tagged as `#[qproperty]` are not exposed as properties to Qt. These can be considered as "private to Rust" fields, and are useful for storing channels for threading or internal information for the QObject. +Fields within your `#[qobject]` struct that aren't tagged as `#[qproperty]` are not exposed as properties to Qt. These can be considered as "private to Rust" fields, and are useful for storing channels for threading or internal information for the QObject. Because they aren't available from C++, they also don't have any special type requirements and can be any Rust type. Use the `rust` and `rust_mut` methods to access the struct and therefore the fields. diff --git a/crates/cxx-qt-gen/src/generator/cpp/mod.rs b/crates/cxx-qt-gen/src/generator/cpp/mod.rs index 246eaddfc..dcd8341d3 100644 --- a/crates/cxx-qt-gen/src/generator/cpp/mod.rs +++ b/crates/cxx-qt-gen/src/generator/cpp/mod.rs @@ -54,7 +54,7 @@ mod tests { #[cxx_qt::bridge] mod ffi { extern "RustQt" { - #[cxx_qt::qobject] + #[qobject] type MyObject = super::MyObjectRust; } } @@ -73,7 +73,7 @@ mod tests { #[cxx_qt::bridge(cxx_file_stem = "my_object")] mod ffi { extern "RustQt" { - #[cxx_qt::qobject] + #[qobject] type MyObject = super::MyObjectRust; } } @@ -92,7 +92,7 @@ mod tests { #[cxx_qt::bridge(namespace = "cxx_qt")] mod ffi { extern "RustQt" { - #[cxx_qt::qobject] + #[qobject] type MyObject = super::MyObjectRust; } } diff --git a/crates/cxx-qt-gen/src/generator/cpp/qobject.rs b/crates/cxx-qt-gen/src/generator/cpp/qobject.rs index 83833c254..a34542d57 100644 --- a/crates/cxx-qt-gen/src/generator/cpp/qobject.rs +++ b/crates/cxx-qt-gen/src/generator/cpp/qobject.rs @@ -166,7 +166,7 @@ mod tests { #[cxx_qt::bridge] mod ffi { extern "RustQt" { - #[cxx_qt::qobject] + #[qobject] type MyObject = super::MyObjectRust; } } @@ -191,7 +191,8 @@ mod tests { #[cxx_qt::bridge(namespace = "cxx_qt")] mod ffi { extern "RustQt" { - #[cxx_qt::qobject(base = "QStringListModel")] + #[qobject] + #[base = "QStringListModel"] type MyObject = super::MyObjectRust; } } @@ -214,7 +215,8 @@ mod tests { #[cxx_qt::bridge(namespace = "cxx_qt")] mod ffi { extern "RustQt" { - #[cxx_qt::qobject(qml_element = "MyQmlElement")] + #[qobject] + #[qml_element = "MyQmlElement"] type MyNamedObject = super::MyNamedObjectRust; } } @@ -240,7 +242,9 @@ mod tests { #[cxx_qt::bridge(namespace = "cxx_qt")] mod ffi { extern "RustQt" { - #[cxx_qt::qobject(qml_element, qml_singleton)] + #[qobject] + #[qml_element] + #[qml_singleton] type MyObject = super::MyObjectRust; } } @@ -267,7 +271,9 @@ mod tests { #[cxx_qt::bridge(namespace = "cxx_qt")] mod ffi { extern "RustQt" { - #[cxx_qt::qobject(qml_element, qml_uncreatable)] + #[qobject] + #[qml_element] + #[qml_uncreatable] type MyObject = super::MyObjectRust; } } diff --git a/crates/cxx-qt-gen/src/generator/rust/mod.rs b/crates/cxx-qt-gen/src/generator/rust/mod.rs index 798059965..eefb5d93e 100644 --- a/crates/cxx-qt-gen/src/generator/rust/mod.rs +++ b/crates/cxx-qt-gen/src/generator/rust/mod.rs @@ -80,7 +80,7 @@ mod tests { #[cxx_qt::bridge] mod ffi { extern "RustQt" { - #[cxx_qt::qobject] + #[qobject] type MyObject = super::MyObjectRust; } } @@ -109,7 +109,7 @@ mod tests { #[cxx_qt::bridge(namespace = "cxx_qt")] mod ffi { extern "RustQt" { - #[cxx_qt::qobject] + #[qobject] type MyObject = super::MyObjectRust; } } @@ -130,7 +130,7 @@ mod tests { #[cxx_qt::bridge(cxx_file_stem = "my_object")] mod ffi { extern "RustQt" { - #[cxx_qt::qobject] + #[qobject] type MyObject = super::MyObjectRust; } } diff --git a/crates/cxx-qt-gen/src/generator/rust/qobject.rs b/crates/cxx-qt-gen/src/generator/rust/qobject.rs index 06600225d..8fe702962 100644 --- a/crates/cxx-qt-gen/src/generator/rust/qobject.rs +++ b/crates/cxx-qt-gen/src/generator/rust/qobject.rs @@ -206,7 +206,9 @@ mod tests { #[cxx_qt::bridge(namespace = "cxx_qt")] mod ffi { extern "RustQt" { - #[cxx_qt::qobject(qml_element, qml_singleton)] + #[qobject] + #[qml_element] + #[qml_singleton] type MyObject = super::MyObjectRust; } } diff --git a/crates/cxx-qt-gen/src/parser/cxxqtdata.rs b/crates/cxx-qt-gen/src/parser/cxxqtdata.rs index df379dfe2..f28483247 100644 --- a/crates/cxx-qt-gen/src/parser/cxxqtdata.rs +++ b/crates/cxx-qt-gen/src/parser/cxxqtdata.rs @@ -87,15 +87,18 @@ impl ParsedCxxQtData { { for foreign_item in &foreign_mod.items { if let ForeignItem::Verbatim(tokens) = foreign_item { - let foreign_alias: ForeignTypeIdentAlias = syn::parse2(tokens.clone())?; + let mut foreign_alias: ForeignTypeIdentAlias = + syn::parse2(tokens.clone())?; - // TODO: in the future qobject macro will be removed and all types in RustQt will be QObjects + // Check this type is tagged with a #[qobject] if let Some(index) = - attribute_find_path(&foreign_alias.attrs, &["cxx_qt", "qobject"]) + attribute_find_path(&foreign_alias.attrs, &["qobject"]) { + foreign_alias.attrs.remove(index); + // Load the QObject let mut qobject = - ParsedQObject::from_foreign_item_type(&foreign_alias, index)?; + ParsedQObject::from_foreign_item_type(&foreign_alias)?; // Inject the bridge namespace if the qobject one is empty if qobject.namespace.is_empty() && !self.namespace.is_empty() { @@ -346,7 +349,7 @@ mod tests { extern "RustQt" { type Other = super::OtherRust; - #[cxx_qt::qobject] + #[qobject] type MyObject = super::MyObjectRust; } } @@ -366,9 +369,9 @@ mod tests { extern "RustQt" { type Other = super::OtherRust; - #[cxx_qt::qobject] + #[qobject] type MyObject = super::MyObjectRust; - #[cxx_qt::qobject] + #[qobject] type SecondObject = super::SecondObjectRust; } } @@ -391,9 +394,10 @@ mod tests { mod module { extern "RustQt" { type Other = super::OtherRust; - #[cxx_qt::qobject(namespace = "qobject_namespace")] + #[qobject] + #[namespace = "qobject_namespace"] type MyObject = super::MyObjectRust; - #[cxx_qt::qobject] + #[qobject] type SecondObject = super::SecondObjectRust; } } diff --git a/crates/cxx-qt-gen/src/parser/mod.rs b/crates/cxx-qt-gen/src/parser/mod.rs index 4275f0dc8..35437963b 100644 --- a/crates/cxx-qt-gen/src/parser/mod.rs +++ b/crates/cxx-qt-gen/src/parser/mod.rs @@ -12,7 +12,7 @@ pub mod property; pub mod qobject; pub mod signals; -use crate::syntax::attribute::{attribute_find_path, attribute_tokens_to_map, AttributeDefault}; +use crate::syntax::attribute::{attribute_find_path, attribute_tokens_to_map}; use cxxqtdata::ParsedCxxQtData; use syn::{spanned::Spanned, token::Brace, Error, Ident, ItemMod, LitStr, Result}; @@ -38,10 +38,7 @@ impl Parser { // Remove the cxx_qt::bridge attribute if let Some(index) = attribute_find_path(&module.attrs, &["cxx_qt", "bridge"]) { - let attr_map = attribute_tokens_to_map::( - &module.attrs[index], - AttributeDefault::None, - )?; + let attr_map = attribute_tokens_to_map::(&module.attrs[index])?; // Parse any namespace in the cxx_qt::bridge macro if let Some(lit_str) = attr_map.get("e::format_ident!("namespace")) { @@ -150,7 +147,7 @@ mod tests { #[cxx_qt::bridge(namespace = "cxx_qt")] mod ffi { extern "RustQt" { - #[cxx_qt::qobject] + #[qobject] type MyObject = super::MyObjectRust; } @@ -186,7 +183,7 @@ mod tests { #[cxx_qt::bridge] mod ffi { extern "RustQt" { - #[cxx_qt::qobject] + #[qobject] type MyObject = super::MyObjectRust; } @@ -217,7 +214,7 @@ mod tests { #[cxx_qt::bridge] mod ffi { extern "RustQt" { - #[cxx_qt::qobject] + #[qobject] type MyObject = super::MyObjectRust; } diff --git a/crates/cxx-qt-gen/src/parser/qobject.rs b/crates/cxx-qt-gen/src/parser/qobject.rs index b71fbf46d..5e66eaa71 100644 --- a/crates/cxx-qt-gen/src/parser/qobject.rs +++ b/crates/cxx-qt-gen/src/parser/qobject.rs @@ -9,12 +9,11 @@ use crate::{ property::ParsedQProperty, signals::ParsedSignal, }, syntax::{ - attribute::{attribute_find_path, attribute_tokens_to_map, AttributeDefault}, - foreignmod::ForeignTypeIdentAlias, + attribute::attribute_find_path, expr::expr_to_string, foreignmod::ForeignTypeIdentAlias, path::path_compare_str, }, }; -use syn::{Attribute, Error, Ident, ImplItem, Item, ItemImpl, LitStr, Result}; +use syn::{Attribute, Error, Ident, ImplItem, Item, ItemImpl, Meta, Result}; /// Metadata for registering QML element #[derive(Clone, Debug, Default, Eq, PartialEq)] @@ -66,31 +65,29 @@ pub struct ParsedQObject { } impl ParsedQObject { - /// 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_ty.attrs[attr_index], - AttributeDefault::Some(|span| LitStr::new("", span)), - )?; + /// Parse a ForeignTypeIdentAlias into a [ParsedQObject] with the index of the #[qobject] specified + pub fn from_foreign_item_type(qobject_ty: &ForeignTypeIdentAlias) -> Result { + let mut qobject_ty = qobject_ty.clone(); + + // Find any QML metadata + let qml_metadata = Self::parse_qml_metadata(&qobject_ty.ident_left, &mut qobject_ty.attrs)?; // Find if there is any base class - let base_class = attrs_map - .get("e::format_ident!("base")) - .map(|base| base.value()); + let base_class = if let Some(index) = attribute_find_path(&qobject_ty.attrs, &["base"]) { + let attr = qobject_ty.attrs.remove(index); + Some(expr_to_string(&attr.meta.require_name_value()?.value)?) + } else { + None + }; // Load the namespace, if it is empty then the ParsedCxxQtData will inject any global namespace - let namespace = attrs_map - .get("e::format_ident!("namespace")) - .map_or_else(|| "".to_owned(), |base| base.value()); - - // Remove the macro from the type - let mut qobject_ty = qobject_ty.clone(); - qobject_ty.attrs.remove(attr_index); + let namespace = if let Some(index) = attribute_find_path(&qobject_ty.attrs, &["namespace"]) + { + let attr = qobject_ty.attrs.remove(index); + expr_to_string(&attr.meta.require_name_value()?.value)? + } else { + "".to_owned() + }; // Parse any properties in the type // and remove the #[qproperty] attribute @@ -114,30 +111,42 @@ impl ParsedQObject { } fn parse_qml_metadata( - qobject_ty: &ForeignTypeIdentAlias, - attr_index: usize, + qobject_ident: &Ident, + attrs: &mut Vec, ) -> Result> { - let attrs_map = attribute_tokens_to_map::( - &qobject_ty.attrs[attr_index], - AttributeDefault::Some(|span| LitStr::new("", span)), - )?; - match attrs_map.get("e::format_ident!("qml_element")) { - Some(qml_element) => { - let name = if qml_element.value().is_empty() { - qobject_ty.ident_left.to_string() - } else { - qml_element.value() - }; - let qml_uncreatable = attrs_map.get("e::format_ident!("qml_uncreatable")); - let qml_singleton = attrs_map.get("e::format_ident!("qml_singleton")); - Ok(Some(QmlElementMetadata { - name, - uncreatable: qml_uncreatable.is_some(), - singleton: qml_singleton.is_some(), - })) - } - None => Ok(None), + // Find if there is a qml_element attribute + if let Some(index) = attribute_find_path(attrs, &["qml_element"]) { + // Extract the name of the qml_element + let name = match attrs.remove(index).meta { + Meta::NameValue(name_value) => expr_to_string(&name_value.value)?, + _ => qobject_ident.to_string(), + }; + + // Determine if this element is uncreatable + let uncreatable = if let Some(index) = attribute_find_path(attrs, &["qml_uncreatable"]) + { + attrs.remove(index); + true + } else { + false + }; + + // Determine if this element is a singleton + let singleton = if let Some(index) = attribute_find_path(attrs, &["qml_singleton"]) { + attrs.remove(index); + true + } else { + false + }; + + return Ok(Some(QmlElementMetadata { + name, + uncreatable, + singleton, + })); } + + Ok(None) } pub fn parse_trait_impl(&mut self, imp: ItemImpl) -> Result<()> { @@ -232,20 +241,20 @@ pub mod tests { pub fn create_parsed_qobject() -> ParsedQObject { let qobject_struct: ForeignTypeIdentAlias = parse_quote! { - #[cxx_qt::qobject] + #[qobject] type MyObject = super::MyObjectRust; }; - ParsedQObject::from_foreign_item_type(&qobject_struct, 0).unwrap() + ParsedQObject::from_foreign_item_type(&qobject_struct).unwrap() } #[test] fn test_from_struct_no_base_class() { let qobject_struct: ForeignTypeIdentAlias = parse_quote! { - #[cxx_qt::qobject] + #[qobject] type MyObject = super::MyObjectRust; }; - let qobject = ParsedQObject::from_foreign_item_type(&qobject_struct, 0).unwrap(); + let qobject = ParsedQObject::from_foreign_item_type(&qobject_struct).unwrap(); assert!(qobject.base_class.is_none()); assert!(qobject.qml_metadata.is_none()); } @@ -253,35 +262,36 @@ pub mod tests { #[test] fn test_from_struct_base_class() { let qobject_struct: ForeignTypeIdentAlias = parse_quote! { - #[cxx_qt::qobject(base = "QStringListModel")] + #[qobject] + #[base = "QStringListModel"] type MyObject = super::MyObjectRust; }; - let qobject = ParsedQObject::from_foreign_item_type(&qobject_struct, 0).unwrap(); + let qobject = ParsedQObject::from_foreign_item_type(&qobject_struct).unwrap(); assert_eq!(qobject.base_class.as_ref().unwrap(), "QStringListModel"); } #[test] fn test_from_struct_properties_and_fields() { let qobject_struct: ForeignTypeIdentAlias = parse_quote! { - #[cxx_qt::qobject] + #[qobject] #[qproperty(i32, int_property)] #[qproperty(i32, public_property)] type MyObject = super::MyObjectRust; }; - let qobject = ParsedQObject::from_foreign_item_type(&qobject_struct, 0).unwrap(); + let qobject = ParsedQObject::from_foreign_item_type(&qobject_struct).unwrap(); assert_eq!(qobject.properties.len(), 2); } #[test] fn test_from_struct_fields() { let qobject_struct: ForeignTypeIdentAlias = parse_quote! { - #[cxx_qt::qobject] + #[qobject] type MyObject = super::MyObjectRust; }; - let qobject = ParsedQObject::from_foreign_item_type(&qobject_struct, 0).unwrap(); + let qobject = ParsedQObject::from_foreign_item_type(&qobject_struct).unwrap(); assert_eq!(qobject.properties.len(), 0); } @@ -330,12 +340,12 @@ pub mod tests { #[test] fn test_parse_struct_fields_valid() { let item: ForeignTypeIdentAlias = parse_quote! { - #[cxx_qt::qobject] + #[qobject] #[qproperty(f64, f64_property)] #[qproperty(f64, public_property)] type T = super::TRust; }; - let properties = ParsedQObject::from_foreign_item_type(&item, 0) + let properties = ParsedQObject::from_foreign_item_type(&item) .unwrap() .properties; assert_eq!(properties.len(), 2); @@ -350,10 +360,11 @@ pub mod tests { #[test] fn test_qml_metadata() { let item: ForeignTypeIdentAlias = parse_quote! { - #[cxx_qt::qobject(qml_element)] + #[qobject] + #[qml_element] type MyObject = super::MyObjectRust; }; - let qobject = ParsedQObject::from_foreign_item_type(&item, 0).unwrap(); + let qobject = ParsedQObject::from_foreign_item_type(&item).unwrap(); assert_eq!( qobject.qml_metadata, Some(QmlElementMetadata { @@ -367,10 +378,11 @@ pub mod tests { #[test] fn test_qml_metadata_named() { let item: ForeignTypeIdentAlias = parse_quote! { - #[cxx_qt::qobject(qml_element = "OtherName")] + #[qobject] + #[qml_element = "OtherName"] type MyObject = super::MyObjectRust; }; - let qobject = ParsedQObject::from_foreign_item_type(&item, 0).unwrap(); + let qobject = ParsedQObject::from_foreign_item_type(&item).unwrap(); assert_eq!( qobject.qml_metadata, Some(QmlElementMetadata { @@ -384,10 +396,12 @@ pub mod tests { #[test] fn test_qml_metadata_singleton() { let item: ForeignTypeIdentAlias = parse_quote! { - #[cxx_qt::qobject(qml_element, qml_singleton)] + #[qobject] + #[qml_element] + #[qml_singleton] type MyObject = super::MyObjectRust; }; - let qobject = ParsedQObject::from_foreign_item_type(&item, 0).unwrap(); + let qobject = ParsedQObject::from_foreign_item_type(&item).unwrap(); assert_eq!( qobject.qml_metadata, Some(QmlElementMetadata { @@ -401,10 +415,12 @@ pub mod tests { #[test] fn test_qml_metadata_uncreatable() { let item: ForeignTypeIdentAlias = parse_quote! { - #[cxx_qt::qobject(qml_element, qml_uncreatable)] + #[qobject] + #[qml_element] + #[qml_uncreatable] type MyObject = super::MyObjectRust; }; - let qobject = ParsedQObject::from_foreign_item_type(&item, 0).unwrap(); + let qobject = ParsedQObject::from_foreign_item_type(&item).unwrap(); assert_eq!( qobject.qml_metadata, Some(QmlElementMetadata { diff --git a/crates/cxx-qt-gen/src/syntax/attribute.rs b/crates/cxx-qt-gen/src/syntax/attribute.rs index 789d435a7..5ad449e1b 100644 --- a/crates/cxx-qt-gen/src/syntax/attribute.rs +++ b/crates/cxx-qt-gen/src/syntax/attribute.rs @@ -4,7 +4,6 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 use crate::syntax::path::path_compare_str; -use proc_macro2::Span; use std::collections::HashMap; use syn::{ // ext::IdentExt, @@ -47,20 +46,11 @@ pub fn attribute_find_path(attrs: &[Attribute], path: &[&str]) -> Option None } -/// Whether the attribute has a default value if there is one missing -/// -/// This is useful in attribute maps where only a key may be specified. -pub enum AttributeDefault { - Some(fn(Span) -> V), - None, -} - /// Returns a map of keys and values from an attribute, eg attribute(a = b, c = d) /// /// A default value can be specified by using [AttributeDefault]. pub fn attribute_tokens_to_map( attr: &Attribute, - default_value: AttributeDefault, ) -> Result> { if let Meta::List(meta_list) = &attr.meta { meta_list.parse_args_with(|input: ParseStream| -> Result> { @@ -69,8 +59,6 @@ pub fn attribute_tokens_to_map(&module.attrs[0], AttributeDefault::None) + attribute_tokens_to_map::(&module.attrs[0]) .unwrap() .len(), 0 ); assert_eq!( - attribute_tokens_to_map::(&module.attrs[1], AttributeDefault::None) + attribute_tokens_to_map::(&module.attrs[1]) .unwrap() .len(), 0 ); - assert!( - attribute_tokens_to_map::(&module.attrs[2], AttributeDefault::None) - .is_err() - ); + assert!(attribute_tokens_to_map::(&module.attrs[2]).is_err()); - let result = - attribute_tokens_to_map::(&module.attrs[3], AttributeDefault::None) - .unwrap(); + let result = attribute_tokens_to_map::(&module.attrs[3]).unwrap(); let ident = format_ident!("namespace"); assert_eq!(result.len(), 1); assert!(result.contains_key(&ident)); assert_eq!(result[&ident].value(), "my::namespace"); - assert!( - attribute_tokens_to_map::(&module.attrs[4], AttributeDefault::None) - .is_err() - ); + assert!(attribute_tokens_to_map::(&module.attrs[4]).is_err()); - let result = - attribute_tokens_to_map::(&module.attrs[5], AttributeDefault::None) - .unwrap(); + let result = attribute_tokens_to_map::(&module.attrs[5]).unwrap(); let ident = format_ident!("namespace"); assert_eq!(result.len(), 2); assert!(result.contains_key(&ident)); assert_eq!(result[&ident].value(), "my::namespace"); - assert!( - attribute_tokens_to_map::(&module.attrs[6], AttributeDefault::None) - .is_err() - ); + assert!(attribute_tokens_to_map::(&module.attrs[6]).is_err()); - let result = - attribute_tokens_to_map::(&module.attrs[7], AttributeDefault::None) - .unwrap(); + let result = attribute_tokens_to_map::(&module.attrs[7]).unwrap(); assert_eq!(result.len(), 0); - assert!( - attribute_tokens_to_map::(&module.attrs[8], AttributeDefault::None) - .is_err() - ); - let result = attribute_tokens_to_map::( - &module.attrs[8], - AttributeDefault::Some(|span| LitStr::new("", span)), - ) - .unwrap(); - assert_eq!(result.len(), 1); - assert!(result.contains_key(&format_ident!("inner"))); + assert!(attribute_tokens_to_map::(&module.attrs[8]).is_err()); } } diff --git a/crates/cxx-qt-gen/test_inputs/inheritance.rs b/crates/cxx-qt-gen/test_inputs/inheritance.rs index c28bfd0b9..f3a9cf6e7 100644 --- a/crates/cxx-qt-gen/test_inputs/inheritance.rs +++ b/crates/cxx-qt-gen/test_inputs/inheritance.rs @@ -8,7 +8,8 @@ mod inheritance { } extern "RustQt" { - #[cxx_qt::qobject(base = "QAbstractItemModel")] + #[qobject] + #[base = "QAbstractItemModel"] type MyObject = super::MyObjectRust; } diff --git a/crates/cxx-qt-gen/test_inputs/invokables.rs b/crates/cxx-qt-gen/test_inputs/invokables.rs index 167d9e898..de6aee48a 100644 --- a/crates/cxx-qt-gen/test_inputs/invokables.rs +++ b/crates/cxx-qt-gen/test_inputs/invokables.rs @@ -11,7 +11,7 @@ mod ffi { } unsafe extern "RustQt" { - #[cxx_qt::qobject] + #[qobject] type MyObject = super::MyObjectRust; fn cpp_method(self: &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 d5f2134b4..bc2a5bf01 100644 --- a/crates/cxx-qt-gen/test_inputs/passthrough_and_naming.rs +++ b/crates/cxx-qt-gen/test_inputs/passthrough_and_naming.rs @@ -80,7 +80,8 @@ pub mod ffi { } extern "RustQt" { - #[cxx_qt::qobject(base = "QStringListModel")] + #[qobject] + #[base = "QStringListModel"] #[qproperty(i32, property_name)] type MyObject = super::MyObjectRust; } @@ -94,7 +95,7 @@ pub mod ffi { } extern "RustQt" { - #[cxx_qt::qobject] + #[qobject] #[qproperty(i32, property_name)] type SecondObject = super::SecondObjectRust; } diff --git a/crates/cxx-qt-gen/test_inputs/properties.rs b/crates/cxx-qt-gen/test_inputs/properties.rs index 9943a1e81..d7ec0204a 100644 --- a/crates/cxx-qt-gen/test_inputs/properties.rs +++ b/crates/cxx-qt-gen/test_inputs/properties.rs @@ -7,7 +7,7 @@ mod ffi { } extern "RustQt" { - #[cxx_qt::qobject] + #[qobject] #[derive(Default)] #[qproperty(i32, primitive)] #[qproperty(QPoint, trivial)] diff --git a/crates/cxx-qt-gen/test_inputs/signals.rs b/crates/cxx-qt-gen/test_inputs/signals.rs index e6d9323a9..ca53aecc4 100644 --- a/crates/cxx-qt-gen/test_inputs/signals.rs +++ b/crates/cxx-qt-gen/test_inputs/signals.rs @@ -7,7 +7,7 @@ mod ffi { } unsafe extern "RustQt" { - #[cxx_qt::qobject] + #[qobject] type MyObject = super::MyObjectRust; #[qsignal] diff --git a/crates/cxx-qt-macro/src/lib.rs b/crates/cxx-qt-macro/src/lib.rs index 9911f7d29..8f2378177 100644 --- a/crates/cxx-qt-macro/src/lib.rs +++ b/crates/cxx-qt-macro/src/lib.rs @@ -20,7 +20,7 @@ use cxx_qt_gen::{write_rust, GeneratedRustBlocks, Parser}; /// #[cxx_qt::bridge(namespace = "cxx_qt::my_object")] /// mod qobject { /// unsafe extern "RustQt" { -/// #[cxx_qt::qobject] +/// #[qobject] /// # // Note that we can't use properties as this confuses the linker on Windows /// type MyObject = super::MyObjectRust; /// @@ -73,7 +73,7 @@ pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream { /// #[cxx_qt::bridge] /// mod my_object { /// extern "RustQt" { -/// #[cxx_qt::qobject] +/// #[qobject] /// # // Note that we can't use properties as this confuses the linker on Windows /// type MyObject = super::MyObjectRust; /// } @@ -86,7 +86,7 @@ pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream { /// # fn main() {} /// ``` /// -/// You can also specify a custom base class by using `#[cxx_qt::qobject(base = "QStringListModel")]`, you must then use CXX to add any includes needed. +/// You can also specify a custom base class by using `#[base = "QStringListModel"]`, you must then use CXX to add any includes needed. /// /// # Example /// @@ -94,7 +94,8 @@ pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream { /// #[cxx_qt::bridge] /// mod my_object { /// extern "RustQt" { -/// #[cxx_qt::qobject(base = "QStringListModel")] +/// #[qobject] +/// #[base = "QStringListModel"] /// # // Note that we can't use properties as this confuses the linker on Windows /// type MyModel = super::MyModelRust; /// } @@ -112,7 +113,7 @@ pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream { /// ``` #[proc_macro_attribute] 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") + unreachable!("qobject 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 diff --git a/crates/cxx-qt/src/lib.rs b/crates/cxx-qt/src/lib.rs index 560bac010..85d70c1e7 100644 --- a/crates/cxx-qt/src/lib.rs +++ b/crates/cxx-qt/src/lib.rs @@ -16,7 +16,7 @@ pub use cxx_qt_macro::qobject; pub use cxxqtthread::CxxQtThread; -/// This trait is automatically implemented for all types which are marked as `#[cxx_qt::qobject]`. +/// This trait is automatically implemented for all types which are marked as `#[qobject]`. /// It provides information about the type that is wrapped by the QObject, as well as the methods /// that Cxx-Qt will generate for the QObject. pub trait CxxQtType { @@ -94,7 +94,7 @@ pub trait Threading: Locking + Sized { /// #[cxx_qt::bridge] /// mod qobject { /// extern "RustQt" { -/// #[cxx_qt::qobject] +/// #[qobject] /// type MyStruct = super::MyStructRust; /// } /// diff --git a/examples/demo_threading/rust/src/lib.rs b/examples/demo_threading/rust/src/lib.rs index 5d81b3db1..f8b844310 100644 --- a/examples/demo_threading/rust/src/lib.rs +++ b/examples/demo_threading/rust/src/lib.rs @@ -18,7 +18,8 @@ mod qobject { } extern "RustQt" { - #[cxx_qt::qobject(qml_element)] + #[qobject] + #[qml_element] #[qproperty(f64, average_use)] #[qproperty(u32, sensors)] #[qproperty(f64, total_use)] diff --git a/examples/qml_extension_plugin/plugin/rust/src/lib.rs b/examples/qml_extension_plugin/plugin/rust/src/lib.rs index d2f0766b9..ef89dc6cd 100644 --- a/examples/qml_extension_plugin/plugin/rust/src/lib.rs +++ b/examples/qml_extension_plugin/plugin/rust/src/lib.rs @@ -35,7 +35,7 @@ mod qobject { } unsafe extern "RustQt" { - #[cxx_qt::qobject] + #[qobject] #[qproperty(i32, number)] #[qproperty(QString, string)] type MyObject = super::MyObjectRust; diff --git a/examples/qml_features/rust/src/containers.rs b/examples/qml_features/rust/src/containers.rs index ad620990e..a4f57116f 100644 --- a/examples/qml_features/rust/src/containers.rs +++ b/examples/qml_features/rust/src/containers.rs @@ -33,7 +33,8 @@ pub mod qobject { } unsafe extern "RustQt" { - #[cxx_qt::qobject(qml_element)] + #[qobject] + #[qml_element] #[qproperty(QString, string_hash)] #[qproperty(QString, string_list)] #[qproperty(QString, string_map)] diff --git a/examples/qml_features/rust/src/custom_base_class.rs b/examples/qml_features/rust/src/custom_base_class.rs index 13e5bb888..65b365b02 100644 --- a/examples/qml_features/rust/src/custom_base_class.rs +++ b/examples/qml_features/rust/src/custom_base_class.rs @@ -34,7 +34,9 @@ pub mod qobject { // ANCHOR: book_inherit_qalm // ANCHOR: book_qobject_base extern "RustQt" { - #[cxx_qt::qobject(base = "QAbstractListModel", qml_element)] + #[qobject] + #[base = "QAbstractListModel"] + #[qml_element] type CustomBaseClass = super::CustomBaseClassRust; } // ANCHOR_END: book_qobject_base diff --git a/examples/qml_features/rust/src/custom_parent_class.rs b/examples/qml_features/rust/src/custom_parent_class.rs index 2fbb12578..8cfc5f8a5 100644 --- a/examples/qml_features/rust/src/custom_parent_class.rs +++ b/examples/qml_features/rust/src/custom_parent_class.rs @@ -43,11 +43,8 @@ mod qobject { } unsafe extern "RustQt" { - #[cxx_qt::qobject( - base = "QQuickPaintedItem", - qml_uri = "com.kdab.cxx_qt.demo", - qml_version = "1.0" - )] + #[qobject] + #[base = "QQuickPaintedItem"] #[qproperty(QColor, color)] type CustomParentClass = super::CustomParentClassRust; diff --git a/examples/qml_features/rust/src/invokables.rs b/examples/qml_features/rust/src/invokables.rs index 69488bdb9..b77089e6f 100644 --- a/examples/qml_features/rust/src/invokables.rs +++ b/examples/qml_features/rust/src/invokables.rs @@ -16,7 +16,8 @@ pub mod qobject { } unsafe extern "RustQt" { - #[cxx_qt::qobject(qml_element)] + #[qobject] + #[qml_element] type RustInvokables = super::RustInvokablesRust; } diff --git a/examples/qml_features/rust/src/multiple_qobjects.rs b/examples/qml_features/rust/src/multiple_qobjects.rs index ea1729735..8da36ee17 100644 --- a/examples/qml_features/rust/src/multiple_qobjects.rs +++ b/examples/qml_features/rust/src/multiple_qobjects.rs @@ -18,7 +18,8 @@ pub mod qobject { } extern "RustQt" { - #[cxx_qt::qobject(qml_element)] + #[qobject] + #[qml_element] #[qproperty(i32, counter)] #[qproperty(QColor, color)] type FirstObject = super::FirstObjectRust; @@ -44,7 +45,8 @@ pub mod qobject { } extern "RustQt" { - #[cxx_qt::qobject(qml_element)] + #[qobject] + #[qml_element] #[qproperty(i32, counter)] #[qproperty(QUrl, url)] type SecondObject = super::SecondObjectRust; diff --git a/examples/qml_features/rust/src/nested_qobjects.rs b/examples/qml_features/rust/src/nested_qobjects.rs index 2ab825173..ef58b8b5a 100644 --- a/examples/qml_features/rust/src/nested_qobjects.rs +++ b/examples/qml_features/rust/src/nested_qobjects.rs @@ -11,7 +11,8 @@ pub mod qobject { // ANCHOR: book_extern_block extern "RustQt" { - #[cxx_qt::qobject(qml_element)] + #[qobject] + #[qml_element] #[qproperty(i32, counter)] type InnerObject = super::InnerObjectRust; } @@ -24,7 +25,8 @@ pub mod qobject { } extern "RustQt" { - #[cxx_qt::qobject(qml_element)] + #[qobject] + #[qml_element] #[qproperty(*mut InnerObject, inner)] type OuterObject = super::OuterObjectRust; diff --git a/examples/qml_features/rust/src/properties.rs b/examples/qml_features/rust/src/properties.rs index 348d5d5c9..621f8a048 100644 --- a/examples/qml_features/rust/src/properties.rs +++ b/examples/qml_features/rust/src/properties.rs @@ -19,7 +19,8 @@ pub mod qobject { unsafe extern "RustQt" { // ANCHOR: book_properties_struct - #[cxx_qt::qobject(qml_element)] + #[qobject] + #[qml_element] #[qproperty(bool, connected)] #[qproperty(QUrl, connected_url)] #[qproperty(QUrl, previous_connected_url)] diff --git a/examples/qml_features/rust/src/serialisation.rs b/examples/qml_features/rust/src/serialisation.rs index f0e47fe7e..3b30b4802 100644 --- a/examples/qml_features/rust/src/serialisation.rs +++ b/examples/qml_features/rust/src/serialisation.rs @@ -36,7 +36,8 @@ pub mod qobject { } unsafe extern "RustQt" { - #[cxx_qt::qobject(qml_element)] + #[qobject] + #[qml_element] #[qproperty(i32, number)] #[qproperty(QString, string)] type Serialisation = super::SerialisationRust; diff --git a/examples/qml_features/rust/src/signals.rs b/examples/qml_features/rust/src/signals.rs index 1896ff426..c6bbc191b 100644 --- a/examples/qml_features/rust/src/signals.rs +++ b/examples/qml_features/rust/src/signals.rs @@ -36,7 +36,8 @@ pub mod qobject { unsafe extern "RustQt" { // ANCHOR: book_signals_struct - #[cxx_qt::qobject(qml_element)] + #[qobject] + #[qml_element] #[qproperty(bool, logging_enabled)] type RustSignals = super::RustSignalsRust; } diff --git a/examples/qml_features/rust/src/singleton.rs b/examples/qml_features/rust/src/singleton.rs index 01052d577..5f03d4062 100644 --- a/examples/qml_features/rust/src/singleton.rs +++ b/examples/qml_features/rust/src/singleton.rs @@ -10,7 +10,9 @@ #[cxx_qt::bridge(cxx_file_stem = "rust_singleton")] pub mod qobject { unsafe extern "RustQt" { - #[cxx_qt::qobject(qml_element, qml_singleton)] + #[qobject] + #[qml_element] + #[qml_singleton] #[qproperty(i32, persistent_value)] type RustSingleton = super::RustSingletonRust; diff --git a/examples/qml_features/rust/src/threading.rs b/examples/qml_features/rust/src/threading.rs index b03a660cb..0349a5eef 100644 --- a/examples/qml_features/rust/src/threading.rs +++ b/examples/qml_features/rust/src/threading.rs @@ -22,7 +22,8 @@ pub mod qobject { } extern "RustQt" { - #[cxx_qt::qobject(qml_element)] + #[qobject] + #[qml_element] #[qproperty(QString, title)] #[qproperty(QUrl, url)] type ThreadingWebsite = super::ThreadingWebsiteRust; diff --git a/examples/qml_features/rust/src/types.rs b/examples/qml_features/rust/src/types.rs index b753d77df..ec88be553 100644 --- a/examples/qml_features/rust/src/types.rs +++ b/examples/qml_features/rust/src/types.rs @@ -74,7 +74,8 @@ pub mod ffi { } unsafe extern "RustQt" { - #[cxx_qt::qobject(qml_element)] + #[qobject] + #[qml_element] #[qproperty(bool, boolean)] #[qproperty(QPointF, point)] #[qproperty(QUrl, url)] diff --git a/examples/qml_features/rust/src/uncreatable.rs b/examples/qml_features/rust/src/uncreatable.rs index 33ab655a1..68f8da92e 100644 --- a/examples/qml_features/rust/src/uncreatable.rs +++ b/examples/qml_features/rust/src/uncreatable.rs @@ -10,7 +10,9 @@ #[cxx_qt::bridge(cxx_file_stem = "rust_uncreatable")] pub mod ffi { extern "RustQt" { - #[cxx_qt::qobject(qml_element, qml_uncreatable)] + #[qobject] + #[qml_element] + #[qml_uncreatable] #[qproperty(i32, value)] type RustUncreatable = super::RustUncreatableRust; } diff --git a/examples/qml_minimal/qml/main.qml b/examples/qml_minimal/qml/main.qml index e4ab8035f..4151a7fe4 100644 --- a/examples/qml_minimal/qml/main.qml +++ b/examples/qml_minimal/qml/main.qml @@ -11,7 +11,7 @@ import QtQuick.Window 2.12 // ANCHOR: book_qml_import // This must match the qml_uri and qml_version -// specified with the #[cxx_qt::qobject] macro in Rust. +// specified with the #[qobject] macro in Rust. import com.kdab.cxx_qt.demo 1.0 // ANCHOR_END: book_qml_import diff --git a/examples/qml_minimal/rust/src/cxxqt_object.rs b/examples/qml_minimal/rust/src/cxxqt_object.rs index 38f4649de..9fb7a6a48 100644 --- a/examples/qml_minimal/rust/src/cxxqt_object.rs +++ b/examples/qml_minimal/rust/src/cxxqt_object.rs @@ -23,7 +23,8 @@ pub mod qobject { // ANCHOR: book_rustobj_struct_signature unsafe extern "RustQt" { - #[cxx_qt::qobject(qml_element)] + #[qobject] + #[qml_element] #[qproperty(i32, number)] #[qproperty(QString, string)] type MyObject = super::MyObjectRust; diff --git a/tests/basic_cxx_qt/rust/src/data.rs b/tests/basic_cxx_qt/rust/src/data.rs index 1c1b468bd..1b4112299 100644 --- a/tests/basic_cxx_qt/rust/src/data.rs +++ b/tests/basic_cxx_qt/rust/src/data.rs @@ -31,7 +31,7 @@ mod qobject { } unsafe extern "RustQt" { - #[cxx_qt::qobject] + #[qobject] #[qproperty(i32, number)] #[qproperty(QString, string)] type MyData = super::MyDataRust; diff --git a/tests/basic_cxx_qt/rust/src/empty.rs b/tests/basic_cxx_qt/rust/src/empty.rs index 598b5d998..a54e74d1d 100644 --- a/tests/basic_cxx_qt/rust/src/empty.rs +++ b/tests/basic_cxx_qt/rust/src/empty.rs @@ -6,7 +6,7 @@ #[cxx_qt::bridge(cxx_file_stem = "empty")] mod ffi { extern "RustQt" { - #[cxx_qt::qobject] + #[qobject] type Empty = super::EmptyRust; } } diff --git a/tests/basic_cxx_qt/rust/src/lib.rs b/tests/basic_cxx_qt/rust/src/lib.rs index 5a7937aa5..b4c81e491 100644 --- a/tests/basic_cxx_qt/rust/src/lib.rs +++ b/tests/basic_cxx_qt/rust/src/lib.rs @@ -18,7 +18,7 @@ mod qobject { } unsafe extern "RustQt" { - #[cxx_qt::qobject] + #[qobject] #[qproperty(i32, number)] #[qproperty(QString, string)] type MyObject = super::MyObjectRust; diff --git a/tests/basic_cxx_qt/rust/src/locking.rs b/tests/basic_cxx_qt/rust/src/locking.rs index 700b4dd51..e3b8db181 100644 --- a/tests/basic_cxx_qt/rust/src/locking.rs +++ b/tests/basic_cxx_qt/rust/src/locking.rs @@ -8,7 +8,7 @@ pub mod qobject { unsafe extern "RustQt" { /// A QObject which has cxx_qt::Locking - #[cxx_qt::qobject] + #[qobject] type RustLockingEnabled = super::RustLockingEnabledRust; fn get_counter(self: &RustLockingEnabled) -> u32; @@ -18,7 +18,7 @@ pub mod qobject { unsafe extern "RustQt" { /// A QObject which has !cxx_qt::Locking - #[cxx_qt::qobject] + #[qobject] type RustLockingDisabled = super::RustLockingDisabledRust; fn get_counter(self: &RustLockingDisabled) -> u32; diff --git a/tests/basic_cxx_qt/rust/src/types.rs b/tests/basic_cxx_qt/rust/src/types.rs index 4b48b91d4..bddd2e070 100644 --- a/tests/basic_cxx_qt/rust/src/types.rs +++ b/tests/basic_cxx_qt/rust/src/types.rs @@ -7,7 +7,7 @@ #[cxx_qt::bridge(cxx_file_stem = "my_types", namespace = "cxx_qt::my_types")] mod ffi { extern "RustQt" { - #[cxx_qt::qobject] + #[qobject] #[qproperty(bool, boolean)] #[qproperty(f32, float_32)] #[qproperty(f64, float_64)]