Skip to main content

qtbridge_interfaces/
lib.rs

1// Copyright (C) 2025 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only
3
4//! # Qt Interfaces (Internal Documentation)
5//!
6//! This crate provides proxies for various Qt (C++) interfaces using Cxx.
7//! Proxies serve as the bridge between Rust and C++ implementations of Qt
8//! interfaces, allowing Rust types to implement behavior expected by C++
9//! code and to access C++ functionality from Rust.
10//!
11//! ## The proxy
12//!
13//! Each Qt interface has a corresponding **proxy** in Rust. This proxy has
14//! to implement the [`qtbridge_runtime::qproxies::QRustProxy`] trait and interacts mostly with
15//! the [`qtbridge_runtime::QObjectHolder`] trait, that is automatically implemented for all
16//! user types by the `qobject` macro.
17//!
18//! The demands on proxies are baked into the [`qtbridge_runtime::qproxies::QRustProxy`] trait.
19//! For example, there
20//! is the demand to provide a Qt static meta object, usually from the "base" this proxy
21//! is derived from. Further, the proxy has to provide a marker trait called `AdapterType`
22//! that is at a minimum used to store a reference to the user object as
23//! `Rc<RefCell<dyn AdapterType>>`. Otherwise the proxy is mostly free in its design.
24//!
25//! All proxies provided in this module follow a similar architecture. The proxy works
26//! together with a set of traits. The QObject proxy is very different since it is the
27//! proxy that is used if only QMetaObject functionality needs to be provided but no
28//! interface implementation.
29//!
30//! ## Traits
31//!
32//! 1. **User-implemented functionality**: Rust implementations of Qt virtual functions.
33//! 2. **Rust access to C++ functionality**: Rust wrappers around C++ methods of the interface.
34//! 3. **Internal type erasure and proxy plumbing**: Allows dynamic behavior when types
35//!    are not fully known at compile time.
36//!
37//! These proxies rely on the following Rust traits to define functionality and structure,
38//! shown on the example of `QListModel`.
39//!
40//! ### 1. `QListModel`
41//! * **Responsibility**: Must be implemented by the user.
42//! * **Purpose**: Functions in this trait are called from C++ via the proxy, providing Rust
43//!   implementations of Qt virtual functions. Some modifications can be done in the functions
44//!   to shape the API and to erase Qt types (e.g. QVariant and QModelIndex).
45//! * **Associated Types**: Defines types (e.g., `Item`) that are part of the interface contract.
46//! * **Notes**: Users implement function as expected from the Qt API. Default implementation
47//!   can exist for non-pure virtual functions.
48//!
49//! ### 2. `QListModelBase`
50//! * **Responsibility**: Default / blank implementation for all `QListModel`.
51//! * **Purpose**: Provides access to C++ functions from Rust and other convenience functions
52//!   that should not be overridden. Serves as a bridge between user logic and C++ functionality.
53//!   Functions that should not be overridden by the user are implemented here.
54//! * **Notes**: This trait forms the core Rust interface to call C++ functions for types implementing
55//!   `QListModel`.
56//!
57//! ### 3. `QListModelAdapter` (Internal Only)
58//! * **Responsibility**: Default / blank implementation for all `QListModel`.
59//! * **Purpose**: Provides a type-erased interface for internal machinery. Traits with associated
60//!   types (like `QListModel::Item`) cannot be used as `dyn` traits in Rust. `QListModelAdapter`
61//!   erases unknown types while exposing the necessary interface internally.
62//! * **Notes**: Never meant for user implementation or usage. Facilitates dynamic behavior and
63//!   internal bridging without exposing associated types to user code.
64//!
65//! ## Memory Ownership and Lifetimes
66//!
67//! Every instance of a user-defined Rust struct annotated with `#[qobject]`
68//! has two auxiliary parts invisible to the user:
69//!
70//! - **`CppProxy`** - a C++ class derived from `QObject` or `QAbstractItemModel` (or another base
71//!   interface). This is the object the QML engine sees and interacts with. It is allocated with
72//!   a regular `new` for Rust-created objects, or with placement `new` at a QML-engine-supplied
73//!   address for QML-created elements.
74//! - **[`RustProxy`](crate::genericrustproxy::GenericRustProxy)** - the Rust-side bridge,
75//!   heap-allocated via [`Box::into_raw`] in
76//!   [`QRustProxy::new`](qtbridge_runtime::qproxies::QRustProxy::new). It holds a pointer to
77//!   `CppProxy` and, in [`RustObjAccess`], the strong `Rc<RefCell<UserStruct>>` that keeps the
78//!   user struct alive.
79//!
80//! A user struct therefore lives exactly as long as its `QObject`, plus any user handles,
81//! which are plain `Rc<RefCell<UserStruct>>`s. There is one teardown chain, no matter who
82//! initiates the deletion:
83//!
84//! ```text
85//! QObject dies (the engine, a parent, or registry::collect_garbage())
86//!   → virtual ~CppProxy()
87//!     → GenericRustProxy::drop_self
88//!       → on_drop() (removes the registry entry)
89//!       → RustProxy drops its Rc
90//!         → UserStruct::drop()          (only if this was the last strong Rc)
91//! ```
92//!
93//! Who may initiate the deletion is the registry's policy: the per-entry owner state,
94//! the `CppOwnership` pin for Rust-created objects, and the collection rules live in
95//! `qtbridge_runtime::registry`.
96
97pub mod genericrustproxy;
98pub use qtbridge_runtime::live_proxy_count;
99
100pub mod qobject;
101
102pub mod qabstract_item_model;
103pub use qabstract_item_model::{QAbstractItemModel, QAbstractItemModelBase};
104
105pub mod qlist_model;
106pub use qlist_model::{QListModel, QListModelBase};
107
108pub mod qparser_status;
109pub use qparser_status::QParserStatus;
110
111pub mod qtable_model;
112pub use qtable_model::{QTableModel, QTableModelBase};
113
114pub mod object_access;
115pub use object_access::rust_object_access::RustObjAccess;