#[qobject_impl]Expand description
Annotate an impl block to make its struct accessible from QML.
The macro implements a range of traits that are enable bridging from Rust to QML. The mechanism is based on the implementation of various traits with some code generated at macro expandsion time. You should not implement these traits yourself. As a user, you should only interact with:
QObjectHolderQmlRegister(only non-generic types)
This macro makes it possible to declare the following items within the
impl block:
- signals with the
qsignalattribute macro - invokable functions with the
qslotattribute macro - struct properties with the
qpropertymacro
Further, it allows the struct to implement traits to fulfill specific QML purposes.
These are called Base traits. The available base traits are:
QListModelto make astructaccessible by QML ListView, QML Repeater, or similar.QTableModelto make astructaccessible by QML TableView.
Only one of those traits can be implemented at the same time.
§Usage
The qobject_impl macro must be applied to a impl block of the
target struct. Only a single impl block can be annotated with this macro and
all applications of qsignal, qslot and qproperty have to be limited to
this block.
In order to communicate with QML, the macro creates briding objects that are attached
to the respective structs. Therefore, objects created with qobject_impl should be
created with default_with_attached_qobject
or expanded with attach_qobject. This is not necessary if
the struct is instantiated in QML.
The macro creates, when register is called a QML module with name
matching your Cargo package name. So for a Cargo.toml with
[package]
name = "hello_world"
[dependencies]
qtbridgethe QML file has to contain
import hello_world§Requirements
A struct annotated with qobject_impl must implement the Default trait.
The static function register has to be called at the start of the
main function to make this struct instantiable from QML.
The macro implements Drop to call detach_qobject,
cleaning up the QML parts of the object. You can implement Drop yourself when using the
NoDrop option (see below). In that case, detach_qobject
has to be called manually.
§Parameters
Parameters to adjust the macro behaviour are passed as comma-separated keywords or keyword-value pairs.
Base = BaseTrait
Set the ‘base’ trait. Requires that the specified trait is implemented for the corresponding struct.
NoQmlElement
Do not implement QmlRegister. QmlRegister registers the struct in the QML type system,
allowing you to instantiate this type in QML. The NoQmlElement option can be useful to turn off
instantiatability within QML or to provide a manual implementation of this trait with better control
over naming and versioning.
Singleton
Implement QmlRegister as a singleton. A singleton
is accessed from QML as a single shared instance of the type, using the type name as identifier.
This is useful for application-wide data, global settings, or service objects.
NoDrop
Do not implement Drop in the macro. This option has to be set when a custom Drop
implementation is required. The function attach_qobject
has to be called manually to avoid memory leaks.
LinkMe
This option calls register at application without any additional code.
The crate Linkme is used for this purpose and needs to be
added to Cargo.toml.
§Example
use qtbridge::{QApp, qobject_impl};
#[derive(Default)]
pub struct Counter {
value: i32,
}
#[qobject_impl(Singleton)]
impl Counter {
qproperty!("value", Member = value, Notify = "valueChanged");
#[qsignal]
fn value_changed(&self);
#[qslot]
fn change_value(&mut self, inc: bool) {
self.value = match inc {
true => self.value.saturating_add(1),
false => self.value.saturating_sub(1),
};
self.value_changed();
}
}
const QML_CODE: &str =
r#"
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import qtbridge // must match your cargo package name
ApplicationWindow {
visible: true
title: qsTr("Counter QML app")
RowLayout {
anchors.centerIn: parent
Button {
text: "-"
onClicked: Counter.changeValue(false)
}
Button {
text: "+"
onClicked: Counter.changeValue(true)
}
}
}
"#;
fn main() {
QApp::new()
.register::<Counter>()
.load_qml(QML_CODE.as_bytes())
.run();
}