Skip to content

Commit

Permalink
cxx-qt-gen: remove support for cxx_type and cxx_return_type
Browse files Browse the repository at this point in the history
These aren't needed anymore as most Qt types are trivial.
This prevents us directly binding to things like signal later.
And these can all be worked around in C++ with proxies.

Closes KDAB#289
  • Loading branch information
ahayzen-kdab committed May 29, 2023
1 parent c26161c commit 4b2e670
Show file tree
Hide file tree
Showing 33 changed files with 75 additions and 396 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Always call `qt_build_utils::setup_linker()` in `CxxQtBuilder` and remove the proxy method
- Moved to `syn` 2.0 internally and for any exported `syn` types

### Removed

- Removed support for `cxx_type` and `cxx_return_type` and related conversion methods.

## [0.5.3](https://github.com/KDAB/cxx-qt/compare/v0.5.2...v0.5.3) - 2023-05-19

### Fixed
Expand Down
1 change: 0 additions & 1 deletion book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ SPDX-License-Identifier: MIT OR Apache-2.0
- [Bridge](./concepts/bridge.md)
- [Qt](./concepts/qt.md)
- [Types](./concepts/types.md)
- [Type Conversions](./concepts/type-conversions.md)
- [Build Systems](./concepts/build_systems.md)
- [Threading](./concepts/threading.md)
- [Nested Objects](./concepts/nested_objects.md)
Expand Down
66 changes: 0 additions & 66 deletions book/src/concepts/type-conversions.md

This file was deleted.

46 changes: 0 additions & 46 deletions book/src/concepts/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,49 +67,3 @@ To use a custom type with `QVariant` implement the `QVariantValue` trait for you
A full example of implementing a custom struct with `QVariant` is shown in the [qml_features types example](https://github.com/KDAB/cxx-qt/blob/main/examples/qml_features/rust/src/types.rs).

Also any custom types or alias in C++ should be registered with Qt using `qRegisterMetaType<T>("TYPE")` to ensure that they work with QML.

## Opaque Type Conversions

If your type can't be marked as trivial for CXX, but the Qt API needs to take the type by value (eg `T` rather than `const T&` or `::std::unique_ptr<T>`),
then you can define [type conversions](type-conversions.md) in C++ that convert between pointers / references and values.
Then when using properties, invokables, or signals an attribute in the macro can be used.

### Properties

In the following example using `cxx_type` means that `OpaqueExampleType` will be the type of the `Q_PROPERTY`, getter, and setter in C++.
On the Rust side `cxx::UniquePtr<OpaqueExampleType>` will be the type and CXX-Qt will perform the conversions between.

```rust,ignore
#[cxx_qt::qobject]
struct MyStruct {
#[qproperty(cxx_type = "OpaqueExampleType")]
my_property: cxx::UniquePtr<OpaqueExampleType>
}
```

### Invokables

In the following example using `return_cxx_type` means that `OpaqueExampleType` will be the return type of the `Q_INVOKABLE` in C++.
On the Rust side `cxx::UniquePtr<OpaqueExampleType>` will be the return type and CXX-Qt will perform the conversion between.

```rust,ignore
impl qobject::MyStruct {
#[qinvokable(return_cxx_type = "OpaqueExampleType")]
pub fn invokable(&self) -> cxx::UniquePtr<OpaqueExampleType> {
...
}
}
```

### Signals

In the following example using `cxx_type` means that `OpaqueExampleType` will be the parameter type of the `Q_SIGNAL` in C++.
On the Rust side `cxx::UniquePtr<OpaqueExampleType>` will be the type in the enum and CXX-Qt will perform the conversion between.

```rust,ignore
#[cxx_qt::qsignals(MyStruct)]
pub enum Signals {
#[cxx_type = "OpaqueExampleType"]
NewData { value: cxx::UniquePtr<OpaqueExampleType> },
}
```
21 changes: 0 additions & 21 deletions book/src/qobject/qobject_struct.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,27 +93,6 @@ These setters and getters assure that the changed signal is emitted every time t
Any field that's not marked as `#[qproperty]` won't be accessible from C++, but it will be accessible from Rust.
See the [Private fields section](#private-methods-and-fields)

### `cxx_type`

You can change the C++ type that your property uses by adding the `cxx_type` attribute to the `#[qproperty]` macro.

This is especially useful if your property type is an opaque C++ type and can't be owned directly by Rust.
Then it might be necessary to wrap it in a [cxx::UniquePtr](https://docs.rs/cxx/latest/cxx/struct.UniquePtr.html).

However, you may still want your `Q_PROPERTY` to use the opaque type directly.
This can easily be achieved by using `cxx_type`.

``` rust,ignore,noplayground
#[cxx_qt::qobject]
struct MyStruct {
#[qproperty(cxx_type="OpaqueExampleType")]
my_property: cxx::UniquePtr<OpaqueExampleType>
}
```
In this case, CXX-Qt will automatically convert the `::std::unique_ptr<OpaqueExampleType>` to `OpaqueExampleType`.

For details, see the [page on type conversions](../concepts/type-conversions.md).

## 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)]`.
Expand Down
4 changes: 1 addition & 3 deletions crates/cxx-qt-gen/src/generator/cpp/inherit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ pub fn generate(

for method in inherited_methods {
let return_type = if let ReturnType::Type(_, ty) = &method.method.sig.output {
CppType::from(ty, &None, cxx_mappings)?
.as_cxx_ty()
.to_owned()
CppType::from(ty, cxx_mappings)?.as_cxx_ty().to_owned()
} else {
"void".to_owned()
};
Expand Down
19 changes: 5 additions & 14 deletions crates/cxx-qt-gen/src/generator/cpp/invokable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub fn generate_cpp_invokables(
for invokable in invokables {
let idents = QInvokableName::from(invokable);
let cxx_ty = if let ReturnType::Type(_, ty) = &invokable.method.sig.output {
Some(CppType::from(ty, &invokable.return_cxx_type, cxx_mappings)?)
Some(CppType::from(ty, cxx_mappings)?)
} else {
None
};
Expand All @@ -56,7 +56,7 @@ pub fn generate_cpp_invokables(
} else {
Ok(Some(CppNamedType {
ident: ident.to_string(),
ty: CppType::from(ty, &None, cxx_mappings)?,
ty: CppType::from(ty, cxx_mappings)?,
}))
}
} else {
Expand Down Expand Up @@ -169,7 +169,6 @@ mod tests {
method: parse_quote! { fn void_invokable(&self) {} },
mutable: false,
parameters: vec![],
return_cxx_type: None,
specifiers: HashSet::new(),
},
ParsedQInvokable {
Expand All @@ -178,9 +177,7 @@ mod tests {
parameters: vec![ParsedFunctionParameter {
ident: format_ident!("param"),
ty: parse_quote! { i32 },
cxx_type: None,
}],
return_cxx_type: None,
specifiers: HashSet::new(),
},
ParsedQInvokable {
Expand All @@ -189,9 +186,7 @@ mod tests {
parameters: vec![ParsedFunctionParameter {
ident: format_ident!("param"),
ty: parse_quote! { &QColor },
cxx_type: None,
}],
return_cxx_type: Some("QColor".to_owned()),
specifiers: HashSet::new(),
},
ParsedQInvokable {
Expand All @@ -200,9 +195,7 @@ mod tests {
parameters: vec![ParsedFunctionParameter {
ident: format_ident!("param"),
ty: parse_quote! { i32 },
cxx_type: None,
}],
return_cxx_type: None,
specifiers: {
let mut specifiers = HashSet::new();
specifiers.insert(ParsedQInvokableSpecifiers::Final);
Expand Down Expand Up @@ -267,16 +260,16 @@ mod tests {
};
assert_str_eq!(
header,
"Q_INVOKABLE QColor opaqueInvokable(QColor const& param);"
"Q_INVOKABLE ::std::unique_ptr<QColor> opaqueInvokable(QColor const& param);"
);
assert_str_eq!(
source,
indoc! {r#"
QColor
::std::unique_ptr<QColor>
MyObject::opaqueInvokable(QColor const& param)
{
const ::std::lock_guard<::std::recursive_mutex> guard(*m_rustObjMutex);
return ::rust::cxxqtlib1::cxx_qt_convert<QColor, ::std::unique_ptr<QColor>>{}(m_rustObj->opaqueInvokableWrapper(*this, param));
return ::rust::cxxqtlib1::cxx_qt_convert<::std::unique_ptr<QColor>, ::std::unique_ptr<QColor>>{}(m_rustObj->opaqueInvokableWrapper(*this, param));
}
"#}
);
Expand Down Expand Up @@ -311,9 +304,7 @@ mod tests {
parameters: vec![ParsedFunctionParameter {
ident: format_ident!("param"),
ty: parse_quote! { i32 },
cxx_type: None,
}],
return_cxx_type: None,
specifiers: HashSet::new(),
}];
let qobject_idents = create_qobjectname();
Expand Down
22 changes: 11 additions & 11 deletions crates/cxx-qt-gen/src/generator/cpp/property/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub fn generate_cpp_properties(
for property in properties {
// Cache the idents as they are used in multiple places
let idents = QPropertyName::from(property);
let cxx_ty = CppType::from(&property.ty, &property.cxx_type, cxx_mappings)?;
let cxx_ty = CppType::from(&property.ty, cxx_mappings)?;

generated.metaobjects.push(meta::generate(&idents, &cxx_ty));
generated
Expand Down Expand Up @@ -58,13 +58,11 @@ mod tests {
ident: format_ident!("trivial_property"),
ty: parse_quote! { i32 },
vis: syn::Visibility::Inherited,
cxx_type: None,
},
ParsedQProperty {
ident: format_ident!("opaque_property"),
ty: parse_quote! { UniquePtr<QColor> },
vis: syn::Visibility::Inherited,
cxx_type: Some("QColor".to_owned()),
},
];
let qobject_idents = create_qobjectname();
Expand All @@ -76,7 +74,7 @@ mod tests {
// metaobjects
assert_eq!(generated.metaobjects.len(), 2);
assert_str_eq!(generated.metaobjects[0], "Q_PROPERTY(::std::int32_t trivialProperty READ getTrivialProperty WRITE setTrivialProperty NOTIFY trivialPropertyChanged)");
assert_str_eq!(generated.metaobjects[1], "Q_PROPERTY(QColor opaqueProperty READ getOpaqueProperty WRITE setOpaqueProperty NOTIFY opaquePropertyChanged)");
assert_str_eq!(generated.metaobjects[1], "Q_PROPERTY(::std::unique_ptr<QColor> opaqueProperty READ getOpaqueProperty WRITE setOpaqueProperty NOTIFY opaquePropertyChanged)");

// methods
assert_eq!(generated.methods.len(), 6);
Expand Down Expand Up @@ -129,15 +127,18 @@ mod tests {
} else {
panic!("Expected pair!")
};
assert_str_eq!(header, "QColor const& getOpaqueProperty() const;");
assert_str_eq!(
header,
"::std::unique_ptr<QColor> const& getOpaqueProperty() const;"
);
assert_str_eq!(
source,
indoc! {r#"
QColor const&
::std::unique_ptr<QColor> const&
MyObject::getOpaqueProperty() const
{
const ::std::lock_guard<::std::recursive_mutex> guard(*m_rustObjMutex);
return ::rust::cxxqtlib1::cxx_qt_convert<QColor const&, ::std::unique_ptr<QColor> const&>{}(m_rustObj->getOpaqueProperty(*this));
return ::rust::cxxqtlib1::cxx_qt_convert<::std::unique_ptr<QColor> const&, ::std::unique_ptr<QColor> const&>{}(m_rustObj->getOpaqueProperty(*this));
}
"#}
);
Expand All @@ -149,16 +150,16 @@ mod tests {
};
assert_str_eq!(
header,
"Q_SLOT void setOpaqueProperty(QColor const& value);"
"Q_SLOT void setOpaqueProperty(::std::unique_ptr<QColor> const& value);"
);
assert_str_eq!(
source,
indoc! {r#"
void
MyObject::setOpaqueProperty(QColor const& value)
MyObject::setOpaqueProperty(::std::unique_ptr<QColor> const& value)
{
const ::std::lock_guard<::std::recursive_mutex> guard(*m_rustObjMutex);
m_rustObj->setOpaqueProperty(*this, ::rust::cxxqtlib1::cxx_qt_convert<::std::unique_ptr<QColor>, QColor const&>{}(value));
m_rustObj->setOpaqueProperty(*this, ::rust::cxxqtlib1::cxx_qt_convert<::std::unique_ptr<QColor>, ::std::unique_ptr<QColor> const&>{}(value));
}
"#}
);
Expand All @@ -177,7 +178,6 @@ mod tests {
ident: format_ident!("mapped_property"),
ty: parse_quote! { A1 },
vis: syn::Visibility::Inherited,
cxx_type: None,
}];
let qobject_idents = create_qobjectname();

Expand Down
Loading

0 comments on commit 4b2e670

Please sign in to comment.