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