Skip to main content

qtbridge_runtime/
qvariant_convert.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::QVariant;
5
6use crate::QMetaTypeCompatible;
7
8/// A type that cross to and from QML by value.
9///
10/// This is the bound for values stored in a model role (see
11/// [`QModelItem`](crate::QModelItem)) and for value-typed properties and
12/// method arguments. Implemented for:
13/// - Primitive numeric types and `bool`
14/// - [`String`]
15/// - [`Vec<T>`] where `T` is one of the above
16///
17/// `QObject` handles (`Rc<RefCell<T>>`) are deliberately not
18/// `QVariantConvertible` as they cross as a pointer.
19pub trait QVariantConvertible: Sized {
20    /// Convert to QVariant. Intended for use with references only.
21    fn to_qvariant(&self) -> QVariant;
22    /// Fallible conversion from QVariant to a value type.
23    fn try_from_qvariant(value: &QVariant) -> Result<Self, ()>;
24
25}
26
27/// Implement `QVariantConvertible` traits using `QMetaTypeCompatible`.
28macro_rules! impl_to_qvariant_and_try_from_qvariant {
29    ($($t:ty),*) => {
30        $(
31            impl QVariantConvertible for $t {
32                // Conversion from referenced value to QVariant.
33                fn to_qvariant(&self) -> QVariant {
34                    let compat = QMetaTypeCompatible::to_compatible(self);
35                    (&compat).into()
36                }
37                // Conversion from a QVariant to value.
38                fn try_from_qvariant(value: &QVariant) -> Result<Self, ()> {
39                    let compat: <$t as QMetaTypeCompatible>::CompatibleType = value.value()
40                        .ok_or(())?;
41                    Ok(<Self as QMetaTypeCompatible>::from_compatible(&compat))
42                }
43            }
44        )*
45    }
46}
47
48impl_to_qvariant_and_try_from_qvariant!(
49    bool, i8, u8, i16, u16, i32, u32, i64, u64, isize, usize, f32, f64, String,
50    Vec<bool>, Vec<i8>, Vec<u8>, Vec<i16>, Vec<u16>, Vec<i32>, Vec<u32>, Vec<i64>, Vec<u64>,
51    Vec<isize>, Vec<usize>, Vec<f32>, Vec<f64>, Vec<String>
52);
53
54impl QVariantConvertible for () {
55    fn to_qvariant(&self) -> QVariant {
56        QVariant::default()
57    }
58    fn try_from_qvariant(value: &QVariant) -> Result<Self, ()> {
59        match value.is_valid() {
60            true => Err(()),
61            false => Ok(()),
62        }
63    }
64}
65
66#[cfg(feature = "serde_json")]
67impl QVariantConvertible for serde_json::Value {
68    fn to_qvariant(&self) -> QVariant {
69        let jv = crate::serde_tools::serde_to_qjsonvalue(self);
70        (&jv).into()
71    }
72    fn try_from_qvariant(value: &QVariant) -> Result<Self, ()> {
73        crate::serde_tools::qvariant_to_serde(value)
74    }
75}
76
77#[cfg(feature = "serde_json")]
78impl QVariantConvertible for Vec<serde_json::Value> {
79    fn to_qvariant(&self) -> QVariant {
80        let ja = crate::serde_tools::serde_to_qjsonarray(self);
81        (&ja).into()
82    }
83    fn try_from_qvariant(value: &QVariant) -> Result<Self, ()> {
84        match crate::serde_tools::qvariant_to_serde(value)? {
85            serde_json::Value::Array(arr) => Ok(arr),
86            _ => Err(()),
87        }
88    }
89}