Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion book/src/bridge/extern_rustqt.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ is equivalent to writing
impl cxx_qt::Constructor<()> for x {}
```

inside the bridge.
inside the bridge. You can then implement your constructors outside the bridge, using either of these traits.

For further documentation see the [traits page](./traits.md).

Expand Down
2 changes: 1 addition & 1 deletion book/src/bridge/traits.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ For further documentation, refer to the documentation of the individual traits:

- [CxxQtType](https://docs.rs/cxx-qt/latest/cxx_qt/trait.CxxQtType.html) - trait to reach the Rust implementation of a `QObject`
- This trait is automatically implemented for any `#[qobject]` type inside `extern "RustQt"` blocks.
- [Constructor](https://docs.rs/cxx-qt/latest/cxx_qt/trait.Constructor.html) - custom constructor
- [Constructor](https://docs.rs/cxx-qt/latest/cxx_qt/trait.Constructor.html) - custom constructor. This must be declared in the bridge in order for you to implement it outside the bridge
- [Initialize](https://docs.rs/cxx-qt/latest/cxx_qt/trait.Initialize.html) - execute Rust code when the object is constructed, or as shorthand for an empty constructor
- [Threading](https://docs.rs/cxx-qt/latest/cxx_qt/trait.Threading.html) - marker trait whether CXX-Qt threading should be enabled
- [QObjectExt](https://docs.rs/cxx-qt/latest/cxx_qt_lib/trait.QObjectExt.html) - Trait which exposes some key methods of QObject
Expand Down
40 changes: 34 additions & 6 deletions crates/cxx-qt-gen/src/generator/rust/constructor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,11 +208,24 @@ pub fn generate(
let rust_struct_name_rust = qobject_names.rust_struct.rust_unqualified();

for (index, constructor) in constructors.iter().enumerate() {
let mut arguments = TokenStream::new();
for elem in &constructor.arguments {
arguments.extend(quote!(#elem,));
}

let lifetime = constructor.lifetime.as_ref().map(|lifetime| {
quote! {
< #lifetime >
}
});

result
.cxx_qt_mod_contents
.append(&mut vec![parse_quote_spanned! {
constructor.imp.span() =>
impl #lifetime ::cxx_qt::ConstructorDeclared<(#arguments) > for #qobject_name_rust_qualified {}
}]);

let arguments_lifetime =
lifetime_of_arguments(&constructor.lifetime, &constructor.arguments)?;
let base_lifetime =
Expand Down Expand Up @@ -599,8 +612,16 @@ mod tests {
},
);

// Shim impl only appears once
assert_tokens_eq(
&blocks.cxx_qt_mod_contents[0],
quote! {
impl ::cxx_qt::ConstructorDeclared<()> for qobject::MyObject {}
},
);

assert_tokens_eq(
&blocks.cxx_qt_mod_contents[1],
quote! {
#[doc(hidden)]
pub fn route_arguments_MyObject_0() -> qobject::CxxQtConstructorArgumentsMyObject0
Expand All @@ -619,7 +640,7 @@ mod tests {
},
);
assert_tokens_eq(
&blocks.cxx_qt_mod_contents[1],
&blocks.cxx_qt_mod_contents[2],
quote! {
#[doc(hidden)]
#[allow(unused_variables)]
Expand All @@ -633,7 +654,7 @@ mod tests {
},
);
assert_tokens_eq(
&blocks.cxx_qt_mod_contents[2],
&blocks.cxx_qt_mod_contents[3],
quote! {
#[doc(hidden)]
#[allow(unused_variables)]
Expand Down Expand Up @@ -725,7 +746,14 @@ mod tests {
);

assert_tokens_eq(
&blocks.cxx_qt_mod_contents[3],
&blocks.cxx_qt_mod_contents[4],
quote! {
impl<'lifetime> ::cxx_qt::ConstructorDeclared<(*const QObject,)> for qobject::MyObject {}
},
);

assert_tokens_eq(
&blocks.cxx_qt_mod_contents[5],
quote! {
#[doc(hidden)]
pub fn route_arguments_MyObject_1<'lifetime>(arg0: *const QObject) -> qobject::CxxQtConstructorArgumentsMyObject1<'lifetime>
Expand Down Expand Up @@ -753,7 +781,7 @@ mod tests {
},
);
assert_tokens_eq(
&blocks.cxx_qt_mod_contents[4],
&blocks.cxx_qt_mod_contents[6],
quote! {
#[doc(hidden)]
#[allow(unused_variables)]
Expand All @@ -767,7 +795,7 @@ mod tests {
},
);
assert_tokens_eq(
&blocks.cxx_qt_mod_contents[5],
&blocks.cxx_qt_mod_contents[7],
quote! {
#[doc(hidden)]
#[allow(unused_variables)]
Expand Down Expand Up @@ -806,7 +834,7 @@ mod tests {
]);

assert_eq!(blocks.cxx_mod_contents.len(), 10);
assert_eq!(blocks.cxx_qt_mod_contents.len(), 6);
assert_eq!(blocks.cxx_qt_mod_contents.len(), 8);

let namespace_attr = quote! {
#[namespace = "qobject::cxx_qt_MyObject"]
Expand Down
2 changes: 2 additions & 0 deletions crates/cxx-qt-gen/test_outputs/invokables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ unsafe impl ::cxx_qt::casting::Upcast<::cxx_qt::QObject> for ffi::MyObject {
ffi::cxx_qt_ffi_MyObject_downcastPtr(base)
}
}
impl<'a> ::cxx_qt::ConstructorDeclared<(i32, &'a QString)> for ffi::MyObject {}
#[doc(hidden)]
pub fn route_arguments_MyObject_0<'a>(
arg0: i32,
Expand Down Expand Up @@ -376,6 +377,7 @@ pub fn initialize_MyObject_0<'a>(
) {
<ffi::MyObject as cxx_qt::Constructor<(i32, &'a ffi::QString)>>::initialize(qobject, ());
}
impl ::cxx_qt::ConstructorDeclared<()> for ffi::MyObject {}
#[doc(hidden)]
pub fn route_arguments_MyObject_1() -> ffi::CxxQtConstructorArgumentsMyObject1 {
#[allow(unused_variables)]
Expand Down
7 changes: 5 additions & 2 deletions crates/cxx-qt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,9 @@ pub trait Threading: Sized {
fn threading_drop(cxx_qt_thread: core::pin::Pin<&mut CxxQtThread<Self>>);
}

#[doc(hidden)]
pub trait ConstructorDeclared<Arguments> {}

/// This trait can be implemented on any [CxxQtType] to define a
/// custom constructor in C++ for the QObject.
///
Expand Down Expand Up @@ -307,7 +310,7 @@ pub trait Threading: Sized {
///
/// If a QObject implements the `Initialize` trait, and the inner Rust struct is [Default]-constructible it will automatically implement `cxx_qt::Constructor<()>`.
/// Additionally, implementing `impl cxx_qt::Initialize` will act as shorthand for `cxx_qt::Constructor<()>`.
pub trait Constructor<Arguments>: CxxQtType {
pub trait Constructor<Arguments>: CxxQtType + ConstructorDeclared<Arguments> {
/// The arguments that are passed to the [`new()`](Self::new) function to construct the inner Rust struct.
/// This must be a tuple of CXX compatible types.
///
Expand Down Expand Up @@ -394,7 +397,7 @@ pub trait Constructor<Arguments>: CxxQtType {
/// ```
// TODO: Once the QObject type is available in the cxx-qt crate, also auto-generate a default
// constructor that takes QObject and passes it to the parent.
pub trait Initialize: CxxQtType {
pub trait Initialize: CxxQtType + ConstructorDeclared<()> {
/// This function is called to initialize the QObject after construction.
fn initialize(self: core::pin::Pin<&mut Self>);
}
Expand Down
Loading