Skip to main content

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 {}