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, ModelError, 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) -> Result<(), ModelError> {
62        match data.try_into() {
63            Ok(data) => self.0.push_row(data),
64            Err(_) => Err(ModelError::unsupported(self)),
65        }
66    }
67
68    fn remove_row(&self, row: usize) -> Result<(), ModelError> {
69        self.0.remove_row(row)
70    }
71
72    fn insert_row(&self, row: usize, data: Self::Data) -> Result<(), ModelError> {
73        match data.try_into() {
74            Ok(data) => self.0.insert_row(row, data),
75            Err(_) => Err(ModelError::unsupported(self)),
76        }
77    }
78}