qtbridge_runtime/qmlobject.rs
1// Copyright (C) 2026 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only
3
4use qtbridge_type_lib::core::qobject;
5use crate::QThreadHandle;
6use crate::qobjectholder::QObjectHolder;
7use crate::registry::Owner;
8
9pub trait QmlObject: QObjectHolder {
10 /// Creates a default-initialized instance and attaches its
11 /// [`QObject`](qtbridge_type_lib::QObject) eagerly.
12 ///
13 /// The returned `Rc<RefCell<Self>>` is an ordinary handle, shared with
14 /// QML. Droping the handle does not drop the instance if it is in use by
15 /// QML or until the garbage collection delete the QML instance.
16 fn default_with_attached_qobject() -> std::rc::Rc<std::cell::RefCell<Self>>
17 where
18 Self: Default,
19 {
20 let instance = Default::default();
21 Self::attach_qobject(&instance);
22 instance
23 }
24
25 /// Attaches a dedicated [`QObject`](qtbridge_type_lib::QObject) to an existing `instance`,
26 /// enabling its use in QML.
27 fn attach_qobject(instance: &std::rc::Rc<std::cell::RefCell<Self>>) {
28 Self::register_instance(instance.clone(), Owner::RustRegistry);
29 }
30
31 /// Detaches and deletes the dedicated [`QObject`](qtbridge_type_lib::QObject) of this instance.
32 ///
33 /// The instance continues as a plain Rust value and heals with a
34 /// fresh `QObject` on its next exposure to QML.
35 fn detach_qobject(&self) {
36 let qobj_ptr = self.get_qobject_ptr();
37 if !qobj_ptr.is_null() {
38 unsafe { qobject::delete(qobj_ptr) };
39 }
40 }
41
42 /// Returns a [`QThreadHandle`] that can schedule Rust closures to run
43 /// on this object on the Qt thread, from any thread.
44 ///
45 /// This function can only be called on the Qt thread for QmlObject that
46 /// live in this thread.
47 ///
48 /// # Example
49 ///
50 /// ```
51 /// # use qtbridge::{qobject, QmlObject};
52 /// # #[qobject]
53 /// # pub mod example {
54 /// # #[derive(Default)]
55 /// # pub struct Backend { pub value: i32 }
56 /// # }
57 /// # use example::Backend;
58 /// let backend = Backend::default_with_attached_qobject();
59 /// let handle = backend.borrow().get_thread_handle();
60 /// handle.invoke_mut(|b| b.value = 42);
61 /// ```
62 fn get_thread_handle(&self) -> QThreadHandle<Self>
63 {
64 QThreadHandle::new(self)
65 }
66}
67
68impl<T: QObjectHolder> QmlObject for T {}