Skip to main content

qtbridge_runtime/
qmetacallarg.rs

1// Copyright (C) 2026 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only
3
4use std::cell::RefCell;
5use std::rc::Rc;
6
7use qtbridge_type_lib::{
8    QMetaType, QMetaTypeGet, QObject, QString, QObjectList,
9    QList_bool, QList_i8, QList_u8, QList_i16, QList_u16,
10    QList_i32, QList_u32, QList_i64, QList_u64, QList_isize, QList_usize,
11    QList_f32, QList_f64, QList_QString,
12};
13
14#[cfg(feature = "serde_json")]
15use qtbridge_type_lib::{QJsonArray, QJsonValue};
16
17use crate::{QObjectHolder, QmlRegister};
18
19/// Enables a type to be used as a signal or slot argument.
20///
21/// Implemented for:
22/// - Primitive numeric types and `bool`
23/// - [`String`]
24/// - [`Vec<T>`] where `T` is one of the above
25/// - [`Rc<RefCell<T>>`] where `T` implements [`QObjectHolder`]
26/// - [`Vec<Rc<RefCell<T>>>`] where `T` implements [`QmlRegister`]
27///
28/// You will not need to implement this trait yourself; adding support for custom types requires CXX/C++ bindings.
29pub trait QMetaCallArg: Sized {
30    type WireType: Sized;
31
32    fn to_wire(&self) -> Self::WireType;
33    fn from_wire(wire: &Self::WireType) -> Self;
34    fn wire_metatype() -> QMetaType;
35}
36
37macro_rules! impl_direct {
38    ($($t:ty),*) => {
39        $(impl QMetaCallArg for $t {
40            type WireType = $t;
41            fn to_wire(&self) -> $t { *self }
42            fn from_wire(wire: &$t) -> $t { *wire }
43            fn wire_metatype() -> QMetaType { <$t as QMetaTypeGet>::get_qmetatype() }
44        })*
45    }
46}
47
48impl_direct!(bool, i8, u8, i16, u16, i32, u32, i64, u64, isize, usize, f32, f64);
49
50macro_rules! impl_vec_direct {
51    ($($t:ty => $qlist:ty),*) => {
52        $(impl QMetaCallArg for Vec<$t> {
53            type WireType = $qlist;
54            fn to_wire(&self) -> $qlist { self.into() }
55            fn from_wire(wire: &$qlist) -> Vec<$t> { wire.into() }
56            fn wire_metatype() -> QMetaType { <$qlist as QMetaTypeGet>::get_qmetatype() }
57        })*
58    }
59}
60
61impl_vec_direct!(
62    bool   => QList_bool,
63    i8     => QList_i8,
64    u8     => QList_u8,
65    i16    => QList_i16,
66    u16    => QList_u16,
67    i32    => QList_i32,
68    u32    => QList_u32,
69    i64    => QList_i64,
70    u64    => QList_u64,
71    isize  => QList_isize,
72    usize  => QList_usize,
73    f32    => QList_f32,
74    f64    => QList_f64,
75    String => QList_QString
76);
77
78impl QMetaCallArg for String {
79    type WireType = QString;
80    fn to_wire(&self) -> QString { self.into() }
81    fn from_wire(wire: &QString) -> String { wire.into() }
82    fn wire_metatype() -> QMetaType { <QString as QMetaTypeGet>::get_qmetatype() }
83}
84
85impl<T: QObjectHolder> QMetaCallArg for Rc<RefCell<T>> {
86    type WireType = *mut QObject;
87
88    fn to_wire(&self) -> *mut QObject {
89        T::rc_ref_cell_to_qobject(self).cast_mut()
90    }
91
92    fn from_wire(wire: &*mut QObject) -> Self {
93        unsafe { T::qobject_to_rc_ref_cell(*wire) }
94    }
95
96    fn wire_metatype() -> QMetaType {
97        <*mut QObject as QMetaTypeGet>::get_qmetatype()
98    }
99}
100
101impl<T: QmlRegister> QMetaCallArg for Vec<Rc<RefCell<T>>> {
102    type WireType = QObjectList;
103
104    fn to_wire(&self) -> QObjectList {
105        let mut list = QObjectList::default();
106        for rc in self {
107            list.append(T::rc_ref_cell_to_qobject(rc).cast_mut());
108        }
109        list
110    }
111
112    fn from_wire(wire: &QObjectList) -> Self {
113        (0..wire.len())
114            .map(|i| unsafe { T::qobject_to_rc_ref_cell(wire[i]) })
115            .collect()
116    }
117
118    fn wire_metatype() -> QMetaType {
119        QObjectList::get_qmetatype()
120    }
121}
122
123#[cfg(feature = "serde_json")]
124impl QMetaCallArg for serde_json::Value {
125    type WireType = QJsonValue;
126    fn to_wire(&self) -> QJsonValue { crate::serde_tools::serde_to_qjsonvalue(self) }
127    fn from_wire(wire: &QJsonValue) -> serde_json::Value { crate::serde_tools::qjsonvalue_to_serde(wire) }
128    fn wire_metatype() -> QMetaType { <QJsonValue as QMetaTypeGet>::get_qmetatype() }
129}
130
131#[cfg(feature = "serde_json")]
132impl QMetaCallArg for Vec<serde_json::Value> {
133    type WireType = QJsonArray;
134    fn to_wire(&self) -> QJsonArray { crate::serde_tools::serde_to_qjsonarray(self) }
135    fn from_wire(wire: &QJsonArray) -> Vec<serde_json::Value> {
136        (0..wire.size()).map(|i| crate::serde_tools::qjsonvalue_to_serde(&wire.at(i))).collect()
137    }
138    fn wire_metatype() -> QMetaType { <QJsonArray as QMetaTypeGet>::get_qmetatype() }
139}