qtbridge_runtime/
qmodelitem.rs

1// Copyright (C) 2026 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only
3
4use std::collections::HashMap;
5
6use qtbridge_type_lib::QVariant;
7
8#[doc(hidden)]
9pub trait QVariantConvertible : Sized {
10    fn to_qvariant(&self) -> QVariant;
11    fn from_qvariant(value: &QVariant) -> Result<Self, ()>;
12}
13
14impl<T> QVariantConvertible for T
15where
16    for<'a> QVariant: From<&'a T>,
17    for<'a> T: TryFrom<&'a QVariant, Error = ()>,
18{
19    fn to_qvariant(&self) -> QVariant {
20        QVariant::from(self)
21    }
22
23    fn from_qvariant(value: &QVariant) -> Result<Self, ()> {
24        <T>::try_from(value)
25    }
26}
27
28fn option_to_qvariant<T: QVariantConvertible>(value: Option<&T>) -> QVariant
29{
30    value.map(<T>::to_qvariant)
31            .unwrap_or_default()
32}
33
34
35
36
37/// Trait representing a single item in a Qt item model.
38///
39/// This trait is implemented automatically by `#[derive(QModelItem)]`
40/// for structs and tuple structs and an implementation for primitive types
41/// and tuples is provided. It allows QtBridge to use the type in item models.
42///
43/// # Typical usage
44/// Normally, you should **not implement this manually**. Use
45/// `#[derive(QModelItem)]` on your struct:
46///
47/// ```rust, ignore
48/// #[derive(QModelItem)]
49/// struct Person {
50///     name: String,
51///     age: u32,
52/// }
53/// ```
54///
55/// # Manual Implementation
56/// If your struct contains fields that **cannot be converted to `QVariant`**,
57/// you need to implement `QModelItem` manually. Only include fields that
58/// are known to QtBridge in the `getN` and `setN` methods, and adjust
59/// `role_names()` accordingly.
60///
61/// Example:
62///
63/// ```rust
64///
65/// use std::collections::HashMap;
66/// use qtbridge::QModelItem;
67///
68/// struct CustomType {
69///     data: Vec<u8>, // cannot be directly converted to QVariant
70///     name: String,
71/// }
72///
73/// impl QModelItem for CustomType {
74///     type T0 = String;
75///     type T1 = ();
76///     type T2 = ();
77///     type T3 = ();
78///     type T4 = ();
79///     type T5 = ();
80///     type T6 = ();
81///     type T7 = ();
82///     type T8 = ();
83///     type T9 = ();
84///     type T10 = ();
85///     type T11 = ();
86///     type T12 = ();
87///     type T13 = ();
88///     type T14 = ();
89///
90///     fn get0(&self) -> Option<&String> {
91///         Some(&self.name)
92///     }
93///
94///     fn set0(&mut self, value: String) {
95///         self.name = value;
96///     }
97///
98///     fn role_names() -> HashMap<i32, String> {
99///         let roles = [(0x0, "name".into())];
100///         roles.into()
101///     }
102/// }
103/// ```
104pub trait QModelItem {
105    // TODO: When associated type defaults become stable, set () as default type.
106    // https://github.com/rust-lang/rust/issues/29661
107    type T0 : QVariantConvertible;
108    type T1 : QVariantConvertible;
109    type T2 : QVariantConvertible;
110    type T3 : QVariantConvertible;
111    type T4 : QVariantConvertible;
112    type T5 : QVariantConvertible;
113    type T6 : QVariantConvertible;
114    type T7 : QVariantConvertible;
115    type T8 : QVariantConvertible;
116    type T9 : QVariantConvertible;
117    type T10 : QVariantConvertible;
118    type T11 : QVariantConvertible;
119    type T12 : QVariantConvertible;
120    type T13 : QVariantConvertible;
121    type T14 : QVariantConvertible;
122
123    fn get0(&self) -> Option<&Self::T0> { None }
124    fn get1(&self) -> Option<&Self::T1> { None }
125    fn get2(&self) -> Option<&Self::T2> { None }
126    fn get3(&self) -> Option<&Self::T3> { None }
127    fn get4(&self) -> Option<&Self::T4> { None }
128    fn get5(&self) -> Option<&Self::T5> { None }
129    fn get6(&self) -> Option<&Self::T6> { None }
130    fn get7(&self) -> Option<&Self::T7> { None }
131    fn get8(&self) -> Option<&Self::T8> { None }
132    fn get9(&self) -> Option<&Self::T9> { None }
133    fn get10(&self) -> Option<&Self::T10> { None }
134    fn get11(&self) -> Option<&Self::T11> { None }
135    fn get12(&self) -> Option<&Self::T12> { None }
136    fn get13(&self) -> Option<&Self::T13> { None }
137    fn get14(&self) -> Option<&Self::T14> { None }
138
139    fn set0(&mut self, _value: Self::T0) {}
140    fn set1(&mut self, _value: Self::T1) {}
141    fn set2(&mut self, _value: Self::T2) {}
142    fn set3(&mut self, _value: Self::T3) {}
143    fn set4(&mut self, _value: Self::T4) {}
144    fn set5(&mut self, _value: Self::T5) {}
145    fn set6(&mut self, _value: Self::T6) {}
146    fn set7(&mut self, _value: Self::T7) {}
147    fn set8(&mut self, _value: Self::T8) {}
148    fn set9(&mut self, _value: Self::T9) {}
149    fn set10(&mut self, _value: Self::T10) {}
150    fn set11(&mut self, _value: Self::T11) {}
151    fn set12(&mut self, _value: Self::T12) {}
152    fn set13(&mut self, _value: Self::T13) {}
153    fn set14(&mut self, _value: Self::T14) {}
154
155    #[doc(hidden)]
156    fn get_role(&self, id: i32) -> QVariant
157    {
158        match id {
159            0 => option_to_qvariant(self.get0()),
160            1 => option_to_qvariant(self.get1()),
161            2 => option_to_qvariant(self.get2()),
162            3 => option_to_qvariant(self.get3()),
163            4 => option_to_qvariant(self.get4()),
164            5 => option_to_qvariant(self.get5()),
165            6 => option_to_qvariant(self.get6()),
166            7 => option_to_qvariant(self.get7()),
167            8 => option_to_qvariant(self.get8()),
168            9 => option_to_qvariant(self.get9()),
169            10 => option_to_qvariant(self.get10()),
170            11 => option_to_qvariant(self.get11()),
171            12 => option_to_qvariant(self.get12()),
172            13 => option_to_qvariant(self.get13()),
173            14 => option_to_qvariant(self.get14()),
174            _ => QVariant::default(),
175        }
176    }
177
178    #[doc(hidden)]
179    fn set_role(&mut self, id: i32, value: &QVariant) -> bool
180    {
181        match id {
182            0 => <Self::T0>::from_qvariant(value).map(|val| self.set0(val)),
183            1 => <Self::T1>::from_qvariant(value).map(|val| self.set1(val)),
184            2 => <Self::T2>::from_qvariant(value).map(|val| self.set2(val)),
185            3 => <Self::T3>::from_qvariant(value).map(|val| self.set3(val)),
186            4 => <Self::T4>::from_qvariant(value).map(|val| self.set4(val)),
187            5 => <Self::T5>::from_qvariant(value).map(|val| self.set5(val)),
188            6 => <Self::T6>::from_qvariant(value).map(|val| self.set6(val)),
189            7 => <Self::T7>::from_qvariant(value).map(|val| self.set7(val)),
190            8 => <Self::T8>::from_qvariant(value).map(|val| self.set8(val)),
191            9 => <Self::T9>::from_qvariant(value).map(|val| self.set9(val)),
192            10 => <Self::T10>::from_qvariant(value).map(|val| self.set10(val)),
193            11 => <Self::T11>::from_qvariant(value).map(|val| self.set11(val)),
194            12 => <Self::T12>::from_qvariant(value).map(|val| self.set12(val)),
195            13 => <Self::T13>::from_qvariant(value).map(|val| self.set13(val)),
196            14 => <Self::T14>::from_qvariant(value).map(|val| self.set14(val)),
197            _ =>  return false,
198        }.is_ok()
199    }
200
201    fn role_names() -> HashMap<i32, String>;
202}
203
204macro_rules! impl_qmodel_item_for_primitive {
205    ($t:ty) => {
206        impl QModelItem for $t {
207            type T0 = $t;
208            type T1 = ();
209            type T2 = ();
210            type T3 = ();
211            type T4 = ();
212            type T5 = ();
213            type T6 = ();
214            type T7 = ();
215            type T8 = ();
216            type T9 = ();
217            type T10 = ();
218            type T11 = ();
219            type T12 = ();
220            type T13 = ();
221            type T14 = ();
222
223            fn get0(&self) -> Option<&Self::T0> {
224                Some(self)
225            }
226
227            fn set0(&mut self, value: Self::T0) {
228                *self = value;
229            }
230            fn role_names() -> HashMap<i32, String> {
231                let roles = [(0x0, "value".into())];
232                roles.into()
233            }
234        }
235    };
236}
237
238impl_qmodel_item_for_primitive!(i8);
239impl_qmodel_item_for_primitive!(i16);
240impl_qmodel_item_for_primitive!(i32);
241impl_qmodel_item_for_primitive!(i64);
242impl_qmodel_item_for_primitive!(u8);
243impl_qmodel_item_for_primitive!(u16);
244impl_qmodel_item_for_primitive!(u32);
245impl_qmodel_item_for_primitive!(u64);
246impl_qmodel_item_for_primitive!(f32);
247impl_qmodel_item_for_primitive!(f64);
248impl_qmodel_item_for_primitive!(bool);
249impl_qmodel_item_for_primitive!(String);
250
251impl<T0, T1> QModelItem for (T0, T1)
252where
253    T0: QVariantConvertible,
254    T1: QVariantConvertible
255{
256    type T0 = T0;
257    type T1 = T1;
258    type T2 = ();
259    type T3 = ();
260    type T4 = ();
261    type T5 = ();
262    type T6 = ();
263    type T7 = ();
264    type T8 = ();
265    type T9 = ();
266    type T10 = ();
267    type T11 = ();
268    type T12 = ();
269    type T13 = ();
270    type T14 = ();
271
272    fn get0(&self) -> Option<&Self::T0> { Some(&self.0) }
273    fn get1(&self) -> Option<&Self::T1> { Some(&self.1) }
274    fn set0(&mut self, value: Self::T0) { self.0 = value; }
275    fn set1(&mut self, value: Self::T1) { self.1 = value; }
276
277    fn role_names() -> HashMap<i32, String> {
278        let roles= [
279            (0x0, "_0".into()),
280            (0x1, "_1".into()),
281        ];
282        roles.into()
283    }
284}
285
286impl<T0, T1, T2> QModelItem for (T0, T1, T2)
287where
288    T0: QVariantConvertible,
289    T1: QVariantConvertible,
290    T2: QVariantConvertible
291{
292    type T0 = T0;
293    type T1 = T1;
294    type T2 = T2;
295    type T3 = ();
296    type T4 = ();
297    type T5 = ();
298    type T6 = ();
299    type T7 = ();
300    type T8 = ();
301    type T9 = ();
302    type T10 = ();
303    type T11 = ();
304    type T12 = ();
305    type T13 = ();
306    type T14 = ();
307
308    fn get0(&self) -> Option<&Self::T0> { Some(&self.0) }
309    fn get1(&self) -> Option<&Self::T1> { Some(&self.1) }
310    fn get2(&self) -> Option<&Self::T2> { Some(&self.2) }
311    fn set0(&mut self, value: Self::T0) { self.0 = value; }
312    fn set1(&mut self, value: Self::T1) { self.1 = value; }
313    fn set2(&mut self, value: Self::T2) { self.2 = value; }
314
315    fn role_names() -> HashMap<i32, String> {
316        let roles= [
317            (0x0, "_0".into()),
318            (0x1, "_1".into()),
319            (0x2, "_2".into()),
320        ];
321        roles.into()
322    }
323}
324
325impl<T0, T1, T2, T3> QModelItem for (T0, T1, T2, T3)
326where
327    T0: QVariantConvertible,
328    T1: QVariantConvertible,
329    T2: QVariantConvertible,
330    T3: QVariantConvertible
331{
332    type T0 = T0;
333    type T1 = T1;
334    type T2 = T2;
335    type T3 = T3;
336    type T4 = ();
337    type T5 = ();
338    type T6 = ();
339    type T7 = ();
340    type T8 = ();
341    type T9 = ();
342    type T10 = ();
343    type T11 = ();
344    type T12 = ();
345    type T13 = ();
346    type T14 = ();
347
348    fn get0(&self) -> Option<&Self::T0> { Some(&self.0) }
349    fn get1(&self) -> Option<&Self::T1> { Some(&self.1) }
350    fn get2(&self) -> Option<&Self::T2> { Some(&self.2) }
351    fn get3(&self) -> Option<&Self::T3> { Some(&self.3) }
352    fn set0(&mut self, value: Self::T0) { self.0 = value; }
353    fn set1(&mut self, value: Self::T1) { self.1 = value; }
354    fn set2(&mut self, value: Self::T2) { self.2 = value; }
355    fn set3(&mut self, value: Self::T3) { self.3 = value; }
356
357    fn role_names() -> HashMap<i32, String> {
358        let roles= [
359            (0x0, "_0".into()),
360            (0x1, "_1".into()),
361            (0x2, "_2".into()),
362            (0x3, "_3".into()),
363        ];
364        roles.into()
365    }
366}
367
368impl<T0, T1, T2, T3, T4> QModelItem for (T0, T1, T2, T3, T4)
369where
370    T0: QVariantConvertible,
371    T1: QVariantConvertible,
372    T2: QVariantConvertible,
373    T3: QVariantConvertible,
374    T4: QVariantConvertible
375{
376    type T0 = T0;
377    type T1 = T1;
378    type T2 = T2;
379    type T3 = T3;
380    type T4 = T4;
381    type T5 = ();
382    type T6 = ();
383    type T7 = ();
384    type T8 = ();
385    type T9 = ();
386    type T10 = ();
387    type T11 = ();
388    type T12 = ();
389    type T13 = ();
390    type T14 = ();
391
392    fn get0(&self) -> Option<&Self::T0> { Some(&self.0) }
393    fn get1(&self) -> Option<&Self::T1> { Some(&self.1) }
394    fn get2(&self) -> Option<&Self::T2> { Some(&self.2) }
395    fn get3(&self) -> Option<&Self::T3> { Some(&self.3) }
396    fn get4(&self) -> Option<&Self::T4> { Some(&self.4) }
397    fn set0(&mut self, value: Self::T0) { self.0 = value; }
398    fn set1(&mut self, value: Self::T1) { self.1 = value; }
399    fn set2(&mut self, value: Self::T2) { self.2 = value; }
400    fn set3(&mut self, value: Self::T3) { self.3 = value; }
401    fn set4(&mut self, value: Self::T4) { self.4 = value; }
402
403    fn role_names() -> HashMap<i32, String> {
404        let roles= [
405            (0x0, "_0".into()),
406            (0x1, "_1".into()),
407            (0x2, "_2".into()),
408            (0x3, "_3".into()),
409            (0x4, "_4".into()),
410        ];
411        roles.into()
412    }
413}
414
415impl<T0, T1, T2, T3, T4, T5> QModelItem for (T0, T1, T2, T3, T4, T5)
416where
417    T0: QVariantConvertible,
418    T1: QVariantConvertible,
419    T2: QVariantConvertible,
420    T3: QVariantConvertible,
421    T4: QVariantConvertible,
422    T5: QVariantConvertible
423{
424    type T0 = T0;
425    type T1 = T1;
426    type T2 = T2;
427    type T3 = T3;
428    type T4 = T4;
429    type T5 = T5;
430    type T6 = ();
431    type T7 = ();
432    type T8 = ();
433    type T9 = ();
434    type T10 = ();
435    type T11 = ();
436    type T12 = ();
437    type T13 = ();
438    type T14 = ();
439
440    fn get0(&self) -> Option<&Self::T0> { Some(&self.0) }
441    fn get1(&self) -> Option<&Self::T1> { Some(&self.1) }
442    fn get2(&self) -> Option<&Self::T2> { Some(&self.2) }
443    fn get3(&self) -> Option<&Self::T3> { Some(&self.3) }
444    fn get4(&self) -> Option<&Self::T4> { Some(&self.4) }
445    fn get5(&self) -> Option<&Self::T5> { Some(&self.5) }
446    fn set0(&mut self, value: Self::T0) { self.0 = value; }
447    fn set1(&mut self, value: Self::T1) { self.1 = value; }
448    fn set2(&mut self, value: Self::T2) { self.2 = value; }
449    fn set3(&mut self, value: Self::T3) { self.3 = value; }
450    fn set4(&mut self, value: Self::T4) { self.4 = value; }
451    fn set5(&mut self, value: Self::T5) { self.5 = value; }
452
453    fn role_names() -> HashMap<i32, String> {
454        let roles= [
455            (0x0, "_0".into()),
456            (0x1, "_1".into()),
457            (0x2, "_2".into()),
458            (0x3, "_3".into()),
459            (0x4, "_4".into()),
460            (0x5, "_5".into()),
461        ];
462        roles.into()
463    }
464}
465
466#[cfg(test)]
467macro_rules! test_tuple_index {
468    ($tuple:expr, $set:ident, $get:ident, $field:tt, $value:expr) => {{
469        $tuple.$set($value);
470        assert_eq!(*$tuple.$get().unwrap(), $value);
471        assert_eq!(*$tuple.$get().unwrap(), $tuple.$field);
472    }};
473}
474
475#[cfg(test)]
476macro_rules! assert_role_name {
477    ($type:ty, $idx:expr, $expected:expr) => {
478        assert_eq!(
479            <$type>::role_names().get(&$idx).unwrap(),
480            $expected
481        );
482    };
483}
484
485#[test]
486fn test_tuple_implementation() {
487    let mut tuple2: (i32, i32) = (1, 1);
488    assert_eq!(<(i32, i32)>::role_names().len(), 2);
489    assert_role_name!((i32, i32), 0, "_0");
490    assert_role_name!((i32, i32), 1, "_1");
491    test_tuple_index!(tuple2, set0, get0, 0, 42);
492    test_tuple_index!(tuple2, set1, get1, 1, 43);
493
494    let mut tuple3: (i32, i32, i32) = (1, 1, 1);
495    assert_eq!(<(i32, i32, i32)>::role_names().len(), 3);
496    assert_role_name!((i32, i32, i32), 0, "_0");
497    assert_role_name!((i32, i32, i32), 1, "_1");
498    assert_role_name!((i32, i32, i32), 2, "_2");
499    test_tuple_index!(tuple3, set0, get0, 0, 42);
500    test_tuple_index!(tuple3, set1, get1, 1, 43);
501    test_tuple_index!(tuple3, set2, get2, 2, 44);
502
503    let mut tuple4: (i32, i32, i32, i32) = (1, 1, 1, 1);
504    assert_eq!(<(i32, i32, i32, i32)>::role_names().len(), 4);
505    assert_role_name!((i32, i32, i32, i32), 0, "_0");
506    assert_role_name!((i32, i32, i32, i32), 1, "_1");
507    assert_role_name!((i32, i32, i32, i32), 2, "_2");
508    assert_role_name!((i32, i32, i32, i32), 3, "_3");
509    test_tuple_index!(tuple4, set0, get0, 0, 42);
510    test_tuple_index!(tuple4, set1, get1, 1, 43);
511    test_tuple_index!(tuple4, set2, get2, 2, 44);
512    test_tuple_index!(tuple4, set3, get3, 3, 45);
513
514    let mut tuple5: (i32, i32, i32, i32, i32) = (1, 1, 1, 1, 1);
515    assert_eq!(<(i32, i32, i32, i32, i32)>::role_names().len(), 5);
516    assert_role_name!((i32, i32, i32, i32, i32), 0, "_0");
517    assert_role_name!((i32, i32, i32, i32, i32), 1, "_1");
518    assert_role_name!((i32, i32, i32, i32, i32), 2, "_2");
519    assert_role_name!((i32, i32, i32, i32, i32), 3, "_3");
520    assert_role_name!((i32, i32, i32, i32, i32), 4, "_4");
521    test_tuple_index!(tuple5, set0, get0, 0, 42);
522    test_tuple_index!(tuple5, set1, get1, 1, 43);
523    test_tuple_index!(tuple5, set2, get2, 2, 44);
524    test_tuple_index!(tuple5, set3, get3, 3, 45);
525    test_tuple_index!(tuple5, set4, get4, 4, 46);
526
527    let mut tuple6: (i32, i32, i32, i32, i32, i32) = (1, 1, 1, 1, 1, 1);
528    assert_eq!(<(i32, i32, i32, i32, i32, i32)>::role_names().len(), 6);
529    assert_role_name!((i32, i32, i32, i32, i32, i32), 0, "_0");
530    assert_role_name!((i32, i32, i32, i32, i32, i32), 1, "_1");
531    assert_role_name!((i32, i32, i32, i32, i32, i32), 2, "_2");
532    assert_role_name!((i32, i32, i32, i32, i32, i32), 3, "_3");
533    assert_role_name!((i32, i32, i32, i32, i32, i32), 4, "_4");
534    assert_role_name!((i32, i32, i32, i32, i32, i32), 5, "_5");
535    test_tuple_index!(tuple6, set0, get0, 0, 42);
536    test_tuple_index!(tuple6, set1, get1, 1, 43);
537    test_tuple_index!(tuple6, set2, get2, 2, 44);
538    test_tuple_index!(tuple6, set3, get3, 3, 45);
539    test_tuple_index!(tuple6, set4, get4, 4, 46);
540    test_tuple_index!(tuple6, set5, get5, 5, 47);
541}