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::QObject;
5use crate::QmlMethodInvoker;
6use crate::qobjectholder::QObjectHolder;
7use crate::registry::Owner;
8
9pub trait QmlObject: QObjectHolder {
10    /// Creates a default-initialized instance and attaches its [`QObject`]
11    /// 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`] 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, None);
29    }
30
31    /// Detaches and deletes the dedicated [`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            QObject::delete(qobj_ptr);
39        }
40    }
41
42    /// Returns a [`QmlMethodInvoker`] that can invoke methods on the underlying
43    /// `QObject` from any thread.
44    ///
45    /// # Example
46    ///
47    /// ```
48    /// # use qtbridge::{qobject, QmlObject};
49    /// # #[qobject]
50    /// # pub mod example {
51    /// #     #[derive(Default)]
52    /// #     pub struct Backend {}
53    /// #     impl Backend {
54    /// #         #[qsignal]
55    /// #         pub fn data_ready(&mut self);
56    /// #     }
57    /// # }
58    /// # use example::Backend;
59    /// let backend = Backend::default_with_attached_qobject();
60    /// let invoker = backend.borrow().get_qml_method_invoker();
61    /// invoker.invoke_method("dataReady");
62    /// ```
63    fn get_qml_method_invoker(&self) -> QmlMethodInvoker
64    {
65        QmlMethodInvoker::new(self)
66    }
67}
68
69impl<T: QObjectHolder> QmlObject for T {}