Skip to main content

slint_interpreter/
value_model.rs

1// Copyright © SixtyFPS GmbH <info@slint.dev>
2// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
3
4use crate::api::Value;
5use i_slint_core::model::{Model, ModelRc, ModelTracker};
6
7/// A number used as a model (`for i in 42`): `n` rows whose data is the row
8/// index. The type-erased equivalent of core's `impl Model for usize`; the
9/// count is baked in — a change to the number re-evaluates the model binding
10/// and produces a new `IntModel`, so the tracker has nothing to track.
11pub struct IntModel(pub usize);
12
13impl Model for IntModel {
14    type Data = Value;
15
16    fn row_count(&self) -> usize {
17        self.0
18    }
19
20    fn row_data(&self, row: usize) -> Option<Self::Data> {
21        (row < self.0).then(|| Value::Number(row as f64))
22    }
23
24    fn model_tracker(&self) -> &dyn ModelTracker {
25        &()
26    }
27
28    fn as_any(&self) -> &dyn core::any::Any {
29        self
30    }
31}
32
33// A map model that wraps a Model
34pub struct ValueMapModel<T>(pub ModelRc<T>);
35
36impl<T: TryFrom<Value> + Into<Value> + 'static> Model for ValueMapModel<T> {
37    type Data = Value;
38
39    fn row_count(&self) -> usize {
40        self.0.row_count()
41    }
42
43    fn row_data(&self, row: usize) -> Option<Self::Data> {
44        self.0.row_data(row).map(|x| x.into())
45    }
46
47    fn model_tracker(&self) -> &dyn ModelTracker {
48        self.0.model_tracker()
49    }
50
51    fn as_any(&self) -> &dyn core::any::Any {
52        self
53    }
54
55    fn set_row_data(&self, row: usize, data: Self::Data) {
56        if let Ok(data) = data.try_into() {
57            self.0.set_row_data(row, data)
58        }
59    }
60
61    fn push_row(&self, data: Self::Data) {
62        if let Ok(data) = data.try_into() {
63            self.0.push_row(data)
64        }
65    }
66
67    fn remove_row(&self, row: isize) {
68        if row >= 0 && row < self.0.row_count() as isize {
69            self.0.remove_row(row);
70        }
71    }
72
73    fn insert_row(&self, row: isize, data: Self::Data) {
74        if row < 0 || row > self.0.row_count() as isize {
75            return;
76        }
77        if let Ok(data) = data.try_into() {
78            self.0.insert_row(row, data);
79        }
80    }
81}