cxx_qt_lib/core/qvariant/
mod.rs1use cxx::{type_id, ExternType};
7use std::fmt;
8use std::mem::MaybeUninit;
9
10use crate::{QMetaTypeType, QObjectMutPtr};
11
12#[cxx::bridge]
13mod ffi {
14 unsafe extern "C++" {
15 include!("cxx-qt-lib/qstring.h");
16 type QString = crate::QString;
17
18 include!("cxx-qt-lib/qvariant.h");
19 }
20
21 unsafe extern "C++" {
22 type QVariant = super::QVariant;
23
24 fn clear(&mut self);
26 #[rust_name = "is_null"]
31 fn isNull(&self) -> bool;
32 #[rust_name = "is_valid"]
34 fn isValid(&self) -> bool;
35
36 #[doc(hidden)]
37 #[rust_name = "user_type"]
38 fn userType(&self) -> i32;
39 }
40
41 #[namespace = "rust::cxxqtlib1"]
42 unsafe extern "C++" {
43 include!("cxx-qt-lib/common.h");
44
45 #[doc(hidden)]
46 #[rust_name = "qvariant_drop"]
47 fn drop(variant: &mut QVariant);
48 #[doc(hidden)]
49 #[rust_name = "qvariant_default"]
50 fn construct() -> QVariant;
51 #[doc(hidden)]
52 #[rust_name = "qvariant_clone"]
53 fn construct(variant: &QVariant) -> QVariant;
54 #[doc(hidden)]
55 #[rust_name = "qvariant_eq"]
56 fn operatorEq(a: &QVariant, b: &QVariant) -> bool;
57 #[doc(hidden)]
58 #[rust_name = "qvariant_to_debug_qstring"]
59 fn toDebugQString(variant: &QVariant) -> QString;
60 }
61
62 #[namespace = "rust::cxxqtlib1::qvariant"]
63 unsafe extern "C++" {
64 #[doc(hidden)]
65 #[rust_name = "qvariant_type_name"]
66 fn qvariantTypeName(variant: &QVariant) -> &[u8];
67 }
68}
69
70#[repr(C)]
74pub struct QVariant {
75 _data: MaybeUninit<f64>,
80
81 #[cfg(cxxqt_qt_version_major = "5")]
82 _space: MaybeUninit<u32>,
83 #[cfg(cxxqt_qt_version_major = "6")]
84 _space: MaybeUninit<[usize; 3]>,
85}
86
87impl Clone for QVariant {
88 fn clone(&self) -> Self {
90 ffi::qvariant_clone(self)
91 }
92}
93
94impl Default for QVariant {
95 fn default() -> Self {
97 ffi::qvariant_default()
98 }
99}
100
101impl Drop for QVariant {
102 fn drop(&mut self) {
104 ffi::qvariant_drop(self)
105 }
106}
107
108impl<T> From<&T> for QVariant
109where
110 T: QVariantValue,
111{
112 fn from(value: &T) -> Self {
114 T::construct(value)
115 }
116}
117
118impl QVariant {
124 pub fn type_id(&self) -> QMetaTypeType {
126 self.user_type().into()
127 }
128
129 pub fn type_name(&self) -> &str {
134 let slice = ffi::qvariant_type_name(self);
136 std::str::from_utf8(slice).expect("QVariant type name is not valid UTF-8")
137 }
138
139 pub fn value<T: QVariantValue>(&self) -> Option<T> {
143 if T::can_convert(self) {
144 Some(T::value_or_default(self))
145 } else {
146 None
147 }
148 }
149
150 pub fn value_or_default<T: QVariantValue>(&self) -> T {
157 T::value_or_default(self)
158 }
159}
160
161impl std::cmp::PartialEq for QVariant {
162 fn eq(&self, other: &Self) -> bool {
174 ffi::qvariant_eq(self, other)
175 }
176}
177
178impl fmt::Debug for QVariant {
179 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
180 ffi::qvariant_to_debug_qstring(self).fmt(f)
181 }
182}
183
184pub trait QVariantValue {
186 fn can_convert(variant: &QVariant) -> bool;
187 fn construct(value: &Self) -> QVariant;
188 fn value_or_default(variant: &QVariant) -> Self;
189}
190
191macro_rules! impl_qvariant_value {
192 ( $typeName:ty, $module:ident ) => {
193 mod $module;
194
195 impl QVariantValue for $typeName {
196 fn can_convert(variant: &QVariant) -> bool {
197 $module::can_convert(variant)
198 }
199
200 fn construct(value: &Self) -> QVariant {
201 $module::construct(value)
202 }
203
204 fn value_or_default(variant: &QVariant) -> Self {
205 $module::value_or_default(variant)
206 }
207 }
208 };
209}
210
211impl_qvariant_value!(bool, qvariant_bool);
212impl_qvariant_value!(f32, qvariant_f32);
213impl_qvariant_value!(f64, qvariant_f64);
214impl_qvariant_value!(i8, qvariant_i8);
215impl_qvariant_value!(i16, qvariant_i16);
216impl_qvariant_value!(i32, qvariant_i32);
217impl_qvariant_value!(i64, qvariant_i64);
218impl_qvariant_value!(crate::QByteArray, qvariant_qbytearray);
219impl_qvariant_value!(crate::QDate, qvariant_qdate);
220#[cfg(not(target_os = "emscripten"))]
221impl_qvariant_value!(crate::QDateTime, qvariant_qdatetime);
222impl_qvariant_value!(crate::QJsonArray, qvariant_qjsonarray);
223impl_qvariant_value!(crate::QJsonObject, qvariant_qjsonobject);
224impl_qvariant_value!(crate::QJsonValue, qvariant_qjsonvalue);
225impl_qvariant_value!(crate::QLine, qvariant_qline);
226impl_qvariant_value!(crate::QLineF, qvariant_qlinef);
227impl_qvariant_value!(crate::QModelIndex, qvariant_qmodelindex);
228impl_qvariant_value!(crate::QObjectMutPtr, qvariant_qobjectmutptr);
229impl_qvariant_value!(crate::QPersistentModelIndex, qvariant_qpersistentmodelindex);
230impl_qvariant_value!(crate::QPoint, qvariant_qpoint);
231impl_qvariant_value!(crate::QPointF, qvariant_qpointf);
232impl_qvariant_value!(crate::QRect, qvariant_qrect);
233impl_qvariant_value!(crate::QRectF, qvariant_qrectf);
234impl_qvariant_value!(crate::QSize, qvariant_qsize);
235impl_qvariant_value!(crate::QSizeF, qvariant_qsizef);
236impl_qvariant_value!(crate::QString, qvariant_qstring);
237impl_qvariant_value!(crate::QStringList, qvariant_qstringlist);
238impl_qvariant_value!(crate::QTime, qvariant_qtime);
239impl_qvariant_value!(crate::QUrl, qvariant_qurl);
240impl_qvariant_value!(crate::QUuid, qvariant_quuid);
241impl_qvariant_value!(
242 crate::QHash<crate::QHashPair_QString_QVariant>,
243 qvariant_qvarianthash
244);
245impl_qvariant_value!(crate::QList<bool>, qvariant_qlist_bool);
246impl_qvariant_value!(crate::QList<f32>, qvariant_qlist_f32);
247impl_qvariant_value!(crate::QList<f64>, qvariant_qlist_f64);
248impl_qvariant_value!(crate::QList<i8>, qvariant_qlist_i8);
249impl_qvariant_value!(crate::QList<i16>, qvariant_qlist_i16);
250impl_qvariant_value!(crate::QList<i32>, qvariant_qlist_i32);
251impl_qvariant_value!(crate::QList<i64>, qvariant_qlist_i64);
252impl_qvariant_value!(crate::QList<u8>, qvariant_qlist_u8);
253impl_qvariant_value!(crate::QList<u16>, qvariant_qlist_u16);
254impl_qvariant_value!(crate::QList<u32>, qvariant_qlist_u32);
255impl_qvariant_value!(crate::QList<u64>, qvariant_qlist_u64);
256impl_qvariant_value!(crate::QList<QObjectMutPtr>, qvariant_qlist_qobjectmutptr);
257impl_qvariant_value!(crate::QList<crate::QString>, qvariant_qlist_qstring);
260impl_qvariant_value!(crate::QList<QVariant>, qvariant_qvariantlist);
261impl_qvariant_value!(
262 crate::QMap<crate::QMapPair_QString_QVariant>,
263 qvariant_qvariantmap
264);
265impl_qvariant_value!(u8, qvariant_u8);
266impl_qvariant_value!(u16, qvariant_u16);
267impl_qvariant_value!(u32, qvariant_u32);
268impl_qvariant_value!(u64, qvariant_u64);
269
270#[cfg(feature = "qt_gui")]
271impl_qvariant_value!(crate::QColor, qvariant_qcolor);
272#[cfg(feature = "qt_gui")]
273impl_qvariant_value!(crate::QFont, qvariant_qfont);
274#[cfg(feature = "qt_gui")]
275impl_qvariant_value!(crate::QImage, qvariant_qimage);
276#[cfg(feature = "qt_gui")]
277impl_qvariant_value!(crate::QPen, qvariant_qpen);
278#[cfg(feature = "qt_gui")]
279impl_qvariant_value!(crate::QPolygon, qvariant_qpolygon);
280#[cfg(feature = "qt_gui")]
281impl_qvariant_value!(crate::QPolygonF, qvariant_qpolygonf);
282#[cfg(feature = "qt_gui")]
283impl_qvariant_value!(crate::QQuaternion, qvariant_qquaternion);
284#[cfg(feature = "qt_gui")]
285impl_qvariant_value!(crate::QRegion, qvariant_qregion);
286#[cfg(feature = "qt_gui")]
287impl_qvariant_value!(crate::QVector2D, qvariant_qvector2d);
288#[cfg(feature = "qt_gui")]
289impl_qvariant_value!(crate::QVector3D, qvariant_qvector3d);
290#[cfg(feature = "qt_gui")]
291impl_qvariant_value!(crate::QVector4D, qvariant_qvector4d);
292
293unsafe impl ExternType for QVariant {
297 type Id = type_id!("QVariant");
298 type Kind = cxx::kind::Trivial;
299}
300
301#[cfg(test)]
302mod tests {
303 use super::*;
304 use crate::{QList, QString};
305
306 #[test]
307 fn test_type_name() {
308 let variant = QVariant::from(&true);
309 assert_eq!(variant.type_name(), "bool");
310
311 let variant = QVariant::from(&123_i32);
312 assert_eq!(variant.type_name(), "int");
313
314 let variant = QVariant::from(&0.25f32);
315 assert_eq!(variant.type_name(), "float");
316
317 let variant = QVariant::from(&0.75f64);
318 assert_eq!(variant.type_name(), "double");
319
320 let variant = QVariant::from(&QList::<i32>::from_iter(&[1, 2, 3]));
321 assert_eq!(variant.type_name(), "QList<int>");
322
323 let variant = QVariant::from(&QString::from("ABC"));
324 assert_eq!(variant.type_name(), "QString");
325 }
326
327 #[test]
328 fn qvariant_type_name_invalid() {
329 let variant = QVariant::default();
330 assert!(!variant.is_valid());
331 assert_eq!(variant.type_name(), "");
332 }
333}