-
Notifications
You must be signed in to change notification settings - Fork 68
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into fix/macos_qt_libs_as_framework
- Loading branch information
Showing
86 changed files
with
1,297 additions
and
682 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,14 +5,14 @@ SPDX-FileContributor: Andrew Hayzen <[email protected]> | |
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. | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
// SPDX-FileCopyrightText: 2023 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]> | ||
// SPDX-FileContributor: Andrew Hayzen <[email protected]> | ||
// | ||
// SPDX-License-Identifier: MIT OR Apache-2.0 | ||
|
||
use crate::generator::{ | ||
cpp::{fragment::CppFragment, qobject::GeneratedCppQObjectBlocks}, | ||
naming::qobject::QObjectName, | ||
}; | ||
use indoc::formatdoc; | ||
use syn::Result; | ||
|
||
pub fn generate(qobject_idents: &QObjectName) -> Result<GeneratedCppQObjectBlocks> { | ||
let mut result = GeneratedCppQObjectBlocks::default(); | ||
|
||
let rust_ident = qobject_idents.rust_struct.cpp.to_string(); | ||
let qobject_ident = qobject_idents.cpp_class.cpp.to_string(); | ||
|
||
result.includes.insert("#include <memory>".to_owned()); | ||
|
||
result.methods.push(CppFragment::Pair { | ||
header: formatdoc! { | ||
r#" | ||
{rust_ident} const& unsafeRust() const; | ||
{rust_ident}& unsafeRustMut(); | ||
"# | ||
}, | ||
source: formatdoc! { | ||
r#" | ||
{rust_ident} const& | ||
{qobject_ident}::unsafeRust() const | ||
{{ | ||
return *m_rustObj; | ||
}} | ||
{rust_ident}& | ||
{qobject_ident}::unsafeRustMut() | ||
{{ | ||
return *m_rustObj; | ||
}} | ||
"# | ||
}, | ||
}); | ||
|
||
result | ||
.members | ||
.push(format!("::rust::Box<{rust_ident}> m_rustObj;")); | ||
|
||
Ok(result) | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
use crate::generator::naming::qobject::tests::create_qobjectname; | ||
use indoc::indoc; | ||
use pretty_assertions::assert_str_eq; | ||
|
||
#[test] | ||
fn test_generate_cpp_locking() { | ||
let qobject_idents = create_qobjectname(); | ||
|
||
let generated = generate(&qobject_idents).unwrap(); | ||
|
||
// includes | ||
assert_eq!(generated.includes.len(), 1); | ||
assert!(generated.includes.contains("#include <memory>")); | ||
|
||
// members | ||
assert_eq!(generated.members.len(), 1); | ||
assert_str_eq!( | ||
&generated.members[0], | ||
"::rust::Box<MyObjectRust> m_rustObj;" | ||
); | ||
|
||
// methods | ||
assert_eq!(generated.methods.len(), 1); | ||
|
||
let (header, source) = if let CppFragment::Pair { header, source } = &generated.methods[0] { | ||
(header, source) | ||
} else { | ||
panic!("Expected pair") | ||
}; | ||
assert_str_eq!( | ||
header, | ||
indoc! {r#" | ||
MyObjectRust const& unsafeRust() const; | ||
MyObjectRust& unsafeRustMut(); | ||
"#} | ||
); | ||
assert_str_eq!( | ||
source, | ||
indoc! {r#" | ||
MyObjectRust const& | ||
MyObject::unsafeRust() const | ||
{ | ||
return *m_rustObj; | ||
} | ||
MyObjectRust& | ||
MyObject::unsafeRustMut() | ||
{ | ||
return *m_rustObj; | ||
} | ||
"#} | ||
); | ||
} | ||
} |
Oops, something went wrong.