qtbridge/lib.rs
1// Copyright (C) 2025 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only
3
4#![doc = include_str!("../README.md")]
5
6#[doc(hidden)]
7pub use qtbridge_runtime;
8pub use qtbridge_runtime::QModelItem;
9pub use qtbridge_runtime::invoke_method;
10pub use qtbridge_runtime::QMetaCallArg;
11pub use qtbridge_runtime::QPropertyMember;
12#[doc(hidden)]
13pub use qtbridge_gen;
14#[doc(hidden)]
15pub use qtbridge_interfaces;
16#[doc(hidden)]
17pub use qtbridge_type_lib;
18#[doc(hidden)]
19pub use qtbridge_build_utils;
20
21pub mod special_traits {
22 //! Traits that enable Rust types to fulfill specific QML roles.
23 //!
24 //! Implement one of these on your struct and pass it as `Base = ...`
25 //! to [`qobject`](crate::qobject).
26 //!
27 //! Note that only one of these traits can be implemented for the same
28 //! type.
29 //!
30 //! - [`QListModel`](crate::QListModel) exposes a list to QML ListView / Repeater
31 //! - [`QTableModel`](crate::QTableModel) exposes a table to QML TableView
32 //! - [`QParserStatus`](crate::QParserStatus) receives notifications during component construction
33}
34
35/// Annotate an `impl` or `mod` block to make its struct accessible from QML.
36///
37/// The macro implements a range of traits that enable bridging from Rust
38/// to QML. The mechanism is based on the implementation of various traits with
39/// some code generated at macro expansion time. You should not implement these
40/// traits yourself. As a user, you should only interact with:
41///
42/// * [`QObjectHolder`]
43/// * [`QmlRegister`] (only non-generic types)
44///
45/// This macro makes it possible to declare the following items within the
46/// `impl` block:
47///
48/// * signals with the [`qsignal`] attribute macro
49/// * invokable functions with the [`qslot`] attribute macro
50/// * struct properties with the [`qproperty`] macro
51///
52/// Further, it allows the struct to implement traits to fulfill specific QML purposes.
53/// These are called `Base` traits. The available base traits are:
54///
55/// * [`QParserStatus`] to receive notifications during QML component construction.
56/// * [`QListModel`] to make a `struct` accessible by QML ListView, QML Repeater, or similar.
57/// * [`QTableModel`] to make a `struct` accessible by QML TableView.
58///
59/// Only one of those traits can be implemented at the same time.
60///
61/// # Usage
62///
63/// The [`qobject`] macro can be applied to a `impl` block of the
64/// target `struct`. Only a single `impl` block can be annotated with this macro and
65/// all applications of [`qsignal`], [`qslot`] and [`qproperty`] have to be limited to
66/// this block.
67///
68/// Alternatively, it may be applied to the `mod` block that contains the `struct`
69/// definition and its associated `impl` blocks.
70///
71/// In order to communicate with QML, the macro creates bridging objects that are attached
72/// to the respective structs. Therefore, objects created with [`qobject`] should be
73/// created with [`default_with_attached_qobject`](QObjectHolder::default_with_attached_qobject)
74/// or expanded with [`attach_qobject`](QObjectHolder::attach_qobject). This is not necessary if
75/// the struct is instantiated in QML.
76///
77/// When [`register`](QmlRegister::register) is called, the macro creates a QML
78/// module whose name matches your Cargo package name. So for a `Cargo.toml` with
79/// ```toml
80/// [package]
81/// name = "hello_world"
82///
83/// [dependencies]
84/// qtbridge
85/// ```
86/// the QML file has to contain
87///
88/// ```qml
89/// import hello_world
90/// ```
91///
92/// ## Requirements
93///
94/// A `struct` using [`qobject`] must implement the [`Default`] trait.
95/// The static function [`register`](QmlRegister::register) has to be called at the start of the
96/// main function to make this `struct` instantiable from QML.
97/// The macro implements [`Drop`] to call [`detach_qobject`](QObjectHolder::detach_qobject),
98/// cleaning up the QML parts of the object. You can implement [`Drop`] yourself when using the
99/// `NoDrop` option (see below). In that case, [`detach_qobject`](QObjectHolder::detach_qobject)
100/// has to be called manually.
101///
102/// ## Parameters
103///
104/// Parameters to adjust the macro behavior are passed as comma-separated keywords or keyword-value pairs.
105///
106/// **Base = BaseTrait**
107///
108/// Set the base trait. Must be one of the [`special_traits`] and must be
109/// implemented for the corresponding `struct`. Only one base trait can be set
110/// per type.
111///
112/// **ConvertToCamelCase**
113///
114/// Rust uses snake_case for function names, while in QML camelCase is more common. Use this option
115/// to convert function names to camelCase when exposed to QML.
116///
117/// **NoQmlElement**
118///
119/// Do not implement [`QmlRegister`]. [`QmlRegister`] registers the `struct` in the QML type system,
120/// allowing you to instantiate this type in QML. The `NoQmlElement` option can be useful to turn off
121/// instantiatability within QML or to provide a manual implementation of this trait with better control
122/// over naming and versioning.
123///
124/// **Singleton**
125///
126/// Implement [`QmlRegister`] as a [singleton](https://doc.qt.io/qt-6/qml-singleton.html). A singleton
127/// is accessed from QML as a single shared instance of the type, using the type name as identifier.
128/// This is useful for application-wide data, global settings, or service objects.
129///
130/// **NoDrop**
131///
132/// Do not implement [`Drop`] in the macro. This option has to be set when a custom [`Drop`]
133/// implementation is required. The function [`detach_qobject`](QObjectHolder::detach_qobject)
134/// has to be called manually to avoid memory leaks.
135///
136/// **LinkMe**
137///
138/// This option calls [`register`](QmlRegister::register) at application without any additional code.
139/// The crate [`Linkme`](https://crates.io/crates/linkme) is used for this purpose and needs to be
140/// added to Cargo.toml.
141///
142/// ## Example
143///
144/// ```rust
145/// use qtbridge::{QApp, qobject};
146///
147/// #[derive(Default)]
148/// pub struct Counter {
149/// value: i32,
150/// }
151///
152/// #[qobject(Singleton)]
153/// impl Counter {
154/// qproperty!("value", Member = value, Notify = value_changed);
155///
156/// #[qsignal]
157/// fn value_changed(&mut self);
158///
159/// #[qslot]
160/// fn change_value(&mut self, inc: bool) {
161/// self.value = match inc {
162/// true => self.value.saturating_add(1),
163/// false => self.value.saturating_sub(1),
164/// };
165/// self.value_changed();
166/// }
167/// }
168///
169/// const QML_CODE: &str =
170/// r#"
171/// import QtQuick
172/// import QtQuick.Controls
173/// import QtQuick.Layouts
174/// import qtbridge // must match your cargo package name
175///
176/// ApplicationWindow {
177/// visible: true
178/// title: qsTr("Counter QML app")
179/// # Component.onCompleted: closeTimer.start()
180/// # Timer {
181/// # id: closeTimer
182/// # interval: 1
183/// # onTriggered: Qt.quit()
184/// # }
185/// RowLayout {
186/// anchors.centerIn: parent
187/// Button {
188/// text: "-"
189/// onClicked: Counter.changeValue(false)
190/// }
191/// Button {
192/// text: "+"
193/// onClicked: Counter.changeValue(true)
194/// }
195/// }
196/// }
197/// "#;
198///
199/// fn main() {
200/// QApp::new()
201/// .register::<Counter>()
202/// .load_qml(QML_CODE.as_bytes())
203/// .run();
204/// }
205/// ```
206///
207#[doc(inline)]
208pub use qtbridge_gen::qobject;
209
210
211/// Annotates a function as a signal that can be handled in QML.
212///
213/// Signals can be called from Rust and the signal handler can be defined in QML. This is the
214/// recommended way to invoke QML code from Rust.
215///
216/// ### Requirements
217///
218/// - The signal must be defined within a `mod` or `impl` block, annotated with [`qobject`].
219/// - The first argument of the annotated function must be `&mut self`.
220/// - All other parameter types and the return type must implement [`QMetaCallArg`].
221/// - The function must not have a body (end with a semicolon or empty curly braces `{}`).
222///
223/// ```rust
224/// # use qtbridge::qobject;
225/// # #[derive(Default)]
226/// # pub struct Backend {
227/// # }
228/// #
229/// #[qobject]
230/// impl Backend {
231/// #[qsignal]
232/// fn value_changed(&mut self, new_value: i32);
233/// #[qsignal]
234/// fn event_triggered(&mut self){}
235/// }
236/// ```
237///
238/// To receive a notification on the QML side, the object definition has to declare a signal handler named
239/// `on<Signal>`, where `<Signal>` is the name of the signal, with the first letter capitalized. Note that
240/// the rest of the function name is not affected and the signal handler for e.g. `value_changed` will be
241/// `onValue_changed`.
242///
243/// ```qml,ignore
244/// Backend {
245/// onValue_changed: console.log("Value changed");
246/// }
247/// ```
248/// Alternatively you can instantiate a `Connection` object with the respective signal handler.
249/// ```qml,ignore
250/// Connection {
251/// target: backend
252/// function onValue_changed() {
253/// console.log("Value changed");
254/// }
255/// }
256/// ```
257///
258/// For more details see <https://doc.qt.io/qt-6/qtqml-syntax-signals.html>
259///
260/// ### Parameters
261///
262/// ***qml_name***
263///
264/// The signal name as seen in QML. Defaults to the Rust function name.
265///
266#[doc(inline)]
267pub use qtbridge_gen::qsignal;
268
269/// Annotates a function as invokable from QML.
270///
271/// Such a function is also registered as a Qt slot, so it can be the target of a
272/// [signal-slot connection](https://doc.qt.io/qt-6/signalsandslots.html), or be
273/// invoked by name from Rust through a [`QmlMethodInvoker`].
274///
275/// ### Requirements
276///
277/// - Has to be defined within a `mod` or `impl` block, annotated with [`qobject`].
278/// - The annotated function must have a body.
279/// - The first argument of the annotated function must be `&self` or `&mut self`.
280/// - All other parameter types and the return type must implement [`QMetaCallArg`].
281///
282/// ### Example
283/// ```rust
284/// # use qtbridge::qobject;
285/// # #[derive(Default)]
286/// # pub struct Backend {
287/// # value: i32,
288/// # }
289/// #
290/// # #[qobject]
291/// # impl Backend {
292/// #[qslot]
293/// fn set_value(&mut self, new_value: i32) {
294/// self.value = new_value;
295/// }
296/// # }
297/// ```
298///
299/// ### Parameters
300///
301/// **qml_name**
302///
303/// The function name as seen from QML. Defaults to the Rust function name.
304#[doc(inline)]
305pub use qtbridge_gen::qslot;
306
307// TODO: Remove name mangling from doc snippets.
308/// Registers a property to be accessible from QML.
309///
310/// ### Requirements
311///
312/// - The property must be defined within a `mod` or `impl` block, annotated with [`qobject`].
313/// - The first parameter is the property name. It must begin with a lower case letter and
314/// can only contain letters, numbers and underscores.
315/// - The property type must implement [`QPropertyMember`].
316/// - The return value of the getter (specified via `Read` parameter) must match the property type.
317/// - The value parameter of the setter (specified via `Write` parameter) must match the property type.
318/// - The member of the `struct` (specified via `Member` parameter) must match the property type.
319/// - A signal indicating any property changes (specified via `Notify` parameter) must be
320/// emitted explicitly by any code that changes the property. The framework does not emit
321/// it automatically.
322/// - Getter and setter methods must be defined within the same `impl` block in which the property
323/// is declared.
324///
325/// A property may be **accessor-based** or **member-based** or a mix of both (see the
326/// [syntax](#qproperty-syntax) section for details).
327///
328/// ### Accessor based property
329///
330/// A pure accessor-based property can be declared together with a range of functions:
331/// ```rust
332/// # use qtbridge::qobject;
333/// # #[derive(Default)]
334/// # pub struct Backend {
335/// # value: i32,
336/// # }
337/// #
338/// # #[qobject]
339/// # impl Backend {
340/// qproperty!("myProperty", Read = get_value, Write = set_value, Notify = my_property_changed);
341///
342/// pub fn get_value(&self) -> i32 { self.value }
343/// pub fn set_value(&mut self, value: i32) {
344/// self.value = value;
345/// self.my_property_changed();
346/// }
347/// #[qsignal]
348/// pub fn my_property_changed(&mut self);
349/// # }
350/// ```
351/// The getter method that returns the current value of the property, the setter (if provided) must
352/// take the input value of the property as its first argument (after `&mut self`).
353///
354/// ### Member based property
355///
356/// Member based properties do not require a setter or getter and QML will directly read and write
357/// to the member. A `Notify` signal must be provided. Qt emits it automatically when QML writes
358/// the property, but when Rust code changes the member directly the notify signal must be emitted
359/// explicitly.
360///
361/// A `struct` containing a member-based property may look like:
362/// ```rust
363/// # use qtbridge::qobject;
364/// #[derive(Default)]
365/// struct Text {
366/// msg: String
367/// }
368///
369/// #[qobject]
370/// impl Text {
371/// qproperty!("message", Member = msg, Notify = message_changed);
372///
373/// #[qsignal]
374/// fn message_changed(&mut self);
375/// }
376/// ```
377///
378/// More information about Qt properties: <https://doc.qt.io/qt-6/properties.html>.
379///
380/// ### Parameters of `qproperty!`
381///
382/// **Name**
383///
384/// The first argument is a string literal specifying the name of the Qt property.
385/// This is the name under which the property is exposed to QML and should follow the
386/// naming rules from [requirements](#requirements-2).
387///
388/// **Read**
389///
390/// Specifies the getter method for the property in the format `Read = getter_name`.
391///
392/// **Write**
393///
394/// Specifies the setter method for the property in the format `Write = setter_name`.
395///
396/// **Member**
397///
398/// Specifies the struct member variable that will be accessed if no getter or setter
399/// are provided. Expected format: `Member = var_name`.
400///
401/// **Notify**
402///
403/// Specifies the name of the signal that has to be emitted when the property changes.
404/// Expected format: `Notify = signal_name`.
405///
406/// **Constant**
407///
408/// A constant property is not allowed to have `Write` or `Notify` parameters. If no
409/// `Notify` is provided in combination with member, `Constant` is required.
410/// Expected as a single keyword without an assignment expression.
411///
412/// **Default**
413///
414/// Marks this as the QML default property. Content placed inside an object literal
415/// without an explicit property assignment is written to it.
416/// Expected as a single keyword without an assignment expression.
417///
418#[doc(inline)]
419pub use qtbridge_gen::qproperty;
420
421pub use qtbridge_runtime::{QApp, qresource, QmlMethodInvoker};
422
423/// Provides access to the underlying QObject for types exposed to QML.
424///
425/// Automatically implemented by [`qobject`]. Do not implement this trait manually.
426///
427#[doc(inline)]
428pub use qtbridge_runtime::QObjectHolder;
429
430/// QmlRegister enables QML to instantiate types of this trait.
431///
432/// The trait is usually implemented by [`qobject`]. If you
433/// want to implement this trait manually, you have to add the `NoQmlElement`
434/// option.
435///
436/// [`QmlRegister`] defines the [`ELEMENT_NAME`](QmlRegister::ELEMENT_NAME)
437/// with which the `struct` can be instantiated in QML and the module name,
438/// [`URI`](QmlRegister::URI), which has to be used as import in QML to
439/// use this `struct`.
440///
441/// [`QmlRegister`] knows two ways of registering a type. The ordinary way
442/// is to register as an element that can be instantiated in QML:
443///
444/// ```rust
445/// # use qtbridge::qobject;
446/// # #[derive(Default)]
447/// # pub struct Backend {
448/// # }
449/// #
450/// #[qobject(NoQmlElement)]
451/// impl Backend {
452/// #[qslot]
453/// fn say_hello(&self) {
454/// println!("Hello World!")
455/// }
456/// }
457/// impl qtbridge::qtbridge_runtime::QmlRegister for Backend {
458/// const URI: &str = "rust_backend";
459/// const ELEMENT_NAME: &str = "Backend";
460/// const MINOR_VERSION: u8 = 0u8;
461/// const MAJOR_VERSION: u8 = 1u8;
462/// const IS_SINGLETON: bool = false;
463/// }
464/// ```
465///
466/// ```qml
467/// import rust_backend
468/// Backend {
469/// id: backend
470/// }
471/// Button {
472/// anchors.centerIn: parent
473/// text: "Hello World!"
474/// onClicked: backend.sayHello()
475/// }
476/// ```
477///
478/// Alternatively, by setting [`IS_SINGLETON`](QmlRegister::IS_SINGLETON)
479/// to true, the type is registered as a singleton. That means that only
480/// one instance can be created. It can be accessed with the
481/// [`ELEMENT_NAME`](QmlRegister::ELEMENT_NAME):
482///
483/// ```rust
484/// # use qtbridge::qobject;
485/// # #[derive(Default)]
486/// # pub struct Backend {
487/// # }
488/// #
489/// #[qobject(NoQmlElement)]
490/// impl Backend {
491/// #[qslot]
492/// fn say_hello(&self) {
493/// println!("Hello World!")
494/// }
495/// }
496/// impl qtbridge::qtbridge_runtime::QmlRegister for Backend {
497/// const URI: &str = "rust_backend";
498/// const ELEMENT_NAME: &str = "Backend";
499/// const MINOR_VERSION: u8 = 0u8;
500/// const MAJOR_VERSION: u8 = 1u8;
501/// const IS_SINGLETON: bool = true;
502/// }
503/// ```
504///
505/// ```qml
506/// import rust_backend
507/// Button {
508/// anchors.centerIn: parent
509/// text: "Hello World!"
510/// onClicked: Backend.sayHello()
511/// }
512/// ```
513///
514/// Further, [`MAJOR_VERSION`](QmlRegister::MAJOR_VERSION) and
515/// [`MINOR_VERSION`](QmlRegister::MINOR_VERSION) define the version of the
516/// QML module. These fields are mandatory but QML can load a module without
517/// specifying the version
518///
519#[doc(inline)]
520pub use qtbridge_runtime::QmlRegister;
521
522pub use qtbridge_gen::QModelItem;
523
524pub use qtbridge_gen::include_bytes_qml;
525
526pub use qtbridge_interfaces::QParserStatus;
527pub use qtbridge_interfaces::{QListModel, QListModelBase};
528pub use qtbridge_interfaces::{QTableModel, QTableModelBase};
529
530#[doc(hidden)]
531pub use qtbridge_interfaces::{QAbstractItemModel, QAbstractItemModelBase};