qtbridge_gen/
lib.rs

1// Copyright (C) 2026 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only
3
4use proc_macro::TokenStream;
5use qtbridge_gen_common::type_qualified_mapping::CallOrigin;
6
7mod qt_derive;
8mod qt_gen_impl;
9mod qt_resource;
10
11#[proc_macro_attribute]
12pub fn qobject(args: TokenStream, input: TokenStream) -> TokenStream {
13    let mut builder = qt_gen_impl::QObjectModuleBuilder::new(CallOrigin::External);
14    let output = match builder.build_token_stream(input.into(), args.into()) {
15        Ok(tokens) => tokens,
16        Err(err) => err.to_compile_error(),
17    };
18    output.into()
19}
20
21#[doc(hidden)]
22#[proc_macro_attribute]
23pub fn qobject_internal(args: TokenStream, input: TokenStream) -> TokenStream {
24    let mut builder = qt_gen_impl::QObjectModuleBuilder::new(CallOrigin::Internal);
25    let output = match builder.build_token_stream(input.into(), args.into()) {
26        Ok(tokens) => tokens,
27        Err(err) => err.to_compile_error(),
28    };
29    output.into()
30}
31
32#[proc_macro_attribute]
33pub fn qobject_impl(args: TokenStream, input: TokenStream) -> TokenStream {
34    let output = match qt_gen_impl::qobject_impl(input.into(), args.into(), &CallOrigin::External) {
35        Ok(o) => o.to_token_stream(),
36        Err(err) => err.to_compile_error(),
37    };
38    output.into()
39}
40
41#[doc(hidden)]
42#[proc_macro_attribute]
43pub fn qobject_impl_internal(args: TokenStream, input: TokenStream) -> TokenStream {
44    let output = match qt_gen_impl::qobject_impl(input.into(), args.into(), &CallOrigin::Internal) {
45        Ok(o) => o.to_token_stream(),
46        Err(err) => err.to_compile_error(),
47    };
48    output.into()
49}
50
51#[proc_macro_attribute]
52pub fn qsignal(_: TokenStream, _: TokenStream) -> TokenStream {
53    // This macro does nothing but offer an entry point for Rust doc
54    panic!("#[qsignal] proc macro called outside #[qobject] or #[qobject_impl].")
55}
56
57#[proc_macro_attribute]
58pub fn qslot(_: TokenStream, _: TokenStream) -> TokenStream {
59    // This macro does nothing but offer an entry point for Rust doc
60    panic!("#[qslot] proc macro called outside #[qobject] or #[qobject_impl].")
61}
62
63#[proc_macro]
64pub fn qproperty(_: TokenStream) -> TokenStream {
65    // This macro does nothing but offer an entry point for Rust doc
66    panic!("qproperty! macro called outside #[qobject] or #[qobject_impl].");
67}
68
69/// Derive macro that generates a `QModelItem` implementation.
70///
71/// Applying this macro to a struct allows it to be used inside `QVec<T>`
72/// and exposed to QML, where it can be visualized with various views. The
73/// delegates within the view are able to read and write to the struct
74/// through the roles.
75///
76/// ## Roles
77/// - **Named Field Struct:** The generated roles will match the names of the
78///   fileds (e.g., `name`, `age`, …). Fields named `display`, `decoration`,
79///   `edit`, `toolTip`, `statusTip`, or `whatsThis` are recognized as default
80///   roles as used in Qt's default delegates.
81/// - **Tuple Structs:** The generated roles are `"_0"`, `"_1"`, `"_2"`, ...
82///
83/// ## Type requirements
84/// All fields must be convertible to and from `QVariant`.
85///
86/// ## Example
87/// ```rust,ignore
88/// #[derive(QModelItem)]
89/// struct Person {
90///     name: String,   // role "name"
91///     age: u32,       // role "age"
92/// }
93///
94/// #[derive(QModelItem)]
95/// struct Pair(i32, String); // roles "_0", "_1"
96/// ```
97#[proc_macro_derive(QModelItem)]
98pub fn derive_qmodelitem(input: TokenStream) -> TokenStream {
99        match qt_derive::try_derive_qmodelitem(input) {
100        Ok(ts) => ts,
101        Err(e) => e.to_compile_error().into(),
102    }
103}
104
105/// Includes a file and makes it accessible under the Qt resource system.
106///
107/// The macro uses the include_bytes! macro internally so the file path has to be
108/// given relative to the current file.
109///
110/// An optional prefix can be added as a second macro parameter.
111///
112/// # Examples
113///
114/// ```ignore
115/// fn main() {
116///     include_bytes_qml!("icon.png", "images");
117/// }
118/// ```
119///
120/// This makes the file 'icon.png' that has to be in the same folder as
121/// the file with the macro accessible in QML as 'qrc:/images/icon.png'
122/// or ':/images.icon.png'
123///
124/// ```qml
125/// Image {
126///     source: "qrc:/images/icon.png"
127/// }
128/// ```
129#[proc_macro]
130pub fn include_bytes_qml(input: TokenStream) -> TokenStream {
131    qt_resource::include_bytes_qml(input)
132}