Skip to main content

i_slint_core/
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
4// cSpell: ignore vecmodel
5
6//! Model and Repeater
7
8use crate::items::StandardListViewItem;
9use crate::{Property, SharedString, SharedVector};
10pub use adapters::{FilterModel, MapModel, ReverseModel, SortModel};
11use alloc::boxed::Box;
12use alloc::rc::Rc;
13use alloc::vec::Vec;
14use core::cell::{Cell, RefCell};
15use core::pin::Pin;
16#[allow(unused)]
17use euclid::num::{Ceil, Floor};
18pub use model_peer::*;
19use once_cell::unsync::OnceCell;
20use pin_project::pin_project;
21
22mod adapters;
23mod model_peer;
24mod repeater;
25
26pub use repeater::{Conditional, RepeatedItemTree, Repeater, RepeaterTracker};
27
28/// This trait defines the interface that users of a model can use to track changes
29/// to a model. It is supplied via [`Model::model_tracker`] and implementation usually
30/// return a reference to its field of [`ModelNotify`].
31pub trait ModelTracker {
32    /// Attach one peer. The peer will be notified when the model changes
33    fn attach_peer(&self, peer: ModelPeer);
34    /// Register the model as a dependency to the current binding being evaluated, so
35    /// that it will be notified when the model changes its size.
36    fn track_row_count_changes(&self);
37    /// Register a row as a dependency to the current binding being evaluated, so that
38    /// it will be notified when the value of that row changes.
39    fn track_row_data_changes(&self, row: usize);
40}
41
42impl ModelTracker for () {
43    fn attach_peer(&self, _peer: ModelPeer) {}
44
45    fn track_row_count_changes(&self) {}
46    fn track_row_data_changes(&self, _row: usize) {}
47}
48
49/// A Model is providing Data for the repeated elements with `for` in the `.slint` language
50///
51/// If the model can be changed, the type implementing the Model trait should hold
52/// a [`ModelNotify`], and is responsible to call functions on it to let the UI know that
53/// something has changed.
54///
55/// Properties of type array will be mapped to a [`ModelRc<T>`], which wraps a `Rc<Model<Data = T>>.`
56/// The [`ModelRc`] documentation has examples on how to set models to array properties.
57///
58/// It is more efficient to operate on the model and send changes through the `ModelNotify` rather than
59/// resetting the property with a different model.
60///
61/// ## Example
62///
63/// As an example, let's see the implementation of [`VecModel`].
64///
65/// ```
66/// # use i_slint_core::model::{Model, ModelNotify, ModelPeer, ModelTracker};
67/// pub struct VecModel<T> {
68///     // the backing data, stored in a `RefCell` as this model can be modified
69///     array: std::cell::RefCell<Vec<T>>,
70///     // the ModelNotify will allow to notify the UI that the model changes
71///     notify: ModelNotify,
72/// }
73///
74/// impl<T: Clone + 'static> Model for VecModel<T> {
75///     type Data = T;
76///
77///     fn row_count(&self) -> usize {
78///         self.array.borrow().len()
79///     }
80///
81///     fn row_data(&self, row: usize) -> Option<Self::Data> {
82///         self.array.borrow().get(row).cloned()
83///     }
84///
85///     fn set_row_data(&self, row: usize, data: Self::Data) {
86///         self.array.borrow_mut()[row] = data;
87///         // don't forget to call row_changed
88///         self.notify.row_changed(row);
89///     }
90///
91///     fn model_tracker(&self) -> &dyn ModelTracker {
92///         &self.notify
93///     }
94///
95///     fn as_any(&self) -> &dyn core::any::Any {
96///         // a typical implementation just return `self`
97///         self
98///     }
99/// }
100///
101/// // when modifying the model, we call the corresponding function in
102/// // the ModelNotify
103/// impl<T> VecModel<T> {
104///     /// Add a row at the end of the model
105///     pub fn push(&self, value: T) {
106///         self.array.borrow_mut().push(value);
107///         self.notify.row_added(self.array.borrow().len() - 1, 1)
108///     }
109///
110///     /// Remove the row at the given index from the model
111///     pub fn remove(&self, index: usize) {
112///         self.array.borrow_mut().remove(index);
113///         self.notify.row_removed(index, 1)
114///     }
115/// }
116/// ```
117pub trait Model {
118    /// The model data: A model is a set of rows and each row has this data
119    type Data;
120    /// The number of rows in the model
121    fn row_count(&self) -> usize;
122    /// Returns the data for a particular row.
123    ///
124    /// This function should normally be called with `row < row_count()` and should return None otherwise.
125    ///
126    /// This function does not register dependencies on the current binding. For an equivalent
127    /// function that tracks dependencies, see [`ModelExt::row_data_tracked`]
128    fn row_data(&self, row: usize) -> Option<Self::Data>;
129    /// Sets the data for a particular row.
130    ///
131    /// This function should be called with `row < row_count()`, otherwise the implementation can panic.
132    ///
133    /// If the model cannot support data changes, then it is ok to do nothing.
134    /// The default implementation will print a warning to stderr.
135    ///
136    /// If the model can update the data, it should also call [`ModelNotify::row_changed`] on its
137    /// internal [`ModelNotify`].
138    fn set_row_data(&self, _row: usize, _data: Self::Data) {
139        #[cfg(feature = "std")]
140        crate::debug_log!(
141            "Model::set_row_data called on a model of type {} which does not re-implement this method. \
142            This happens when trying to modify a read-only model",
143            core::any::type_name::<Self>(),
144        );
145    }
146
147    /// The implementation should return a reference to its [`ModelNotify`] field.
148    ///
149    /// You can return `&()` if you your `Model` is constant and does not have a ModelNotify field.
150    fn model_tracker(&self) -> &dyn ModelTracker;
151
152    /// Returns an iterator visiting all elements of the model.
153    fn iter(&self) -> ModelIterator<'_, Self::Data>
154    where
155        Self: Sized,
156    {
157        ModelIterator::new(self)
158    }
159
160    /// Return something that can be downcast'ed (typically self).
161    ///
162    /// Use this to retrieve the concrete model from a [`ModelRc`] stored
163    /// in your tree of UI elements.
164    ///
165    /// ```
166    /// # use i_slint_core::model::*;
167    /// # use std::rc::Rc;
168    /// let handle = ModelRc::new(VecModel::from(vec![1i32, 2, 3]));
169    /// // later:
170    /// handle.as_any().downcast_ref::<VecModel<i32>>().unwrap().push(4);
171    /// assert_eq!(handle.row_data(3).unwrap(), 4);
172    /// ```
173    ///
174    /// Note: Custom models must implement this method for the cast to succeed.
175    /// A valid implementation is to return `self`:
176    /// ```ignore
177    ///     fn as_any(&self) -> &dyn core::any::Any { self }
178    /// ```
179    ///
180    /// ## Troubleshooting
181    /// A common reason why the dowcast fails at run-time is because of a type-mismatch
182    /// between the model created and the model downcasted. To debug this at compile time,
183    /// try matching the model type used for the downcast explicitly at model creation time.
184    /// In the following example, the downcast fails at run-time:
185    ///
186    /// ```
187    /// # use i_slint_core::model::*;
188    /// # use std::rc::Rc;
189    /// let model = VecModel::from_slice(&[3i32, 2, 1])
190    ///     .filter(Box::new(|v: &i32| *v >= 2) as Box<dyn Fn(&i32) -> bool>);
191    /// let model_rc = ModelRc::new(model);
192    /// assert!(model_rc.as_any()
193    ///     .downcast_ref::<FilterModel<VecModel<i32>, Box<dyn Fn(&i32) -> bool>>>()
194    ///     .is_none());
195    /// ```
196    ///
197    /// To debug this, let's make the type explicit. It fails to compile.
198    ///
199    /// ```compile_fail
200    /// # use i_slint_core::model::*;
201    /// # use std::rc::Rc;
202    /// let model: FilterModel<VecModel<i32>, Box<dyn Fn(&i32) -> bool>>
203    ///     = VecModel::from_slice(&[3i32, 2, 1])
204    ///       .filter(Box::new(|v: &i32| *v >= 2) as Box<dyn Fn(&i32) -> bool>);
205    /// let model_rc = ModelRc::new(model);
206    /// assert!(model_rc.as_any()
207    ///     .downcast_ref::<FilterModel<VecModel<i32>, Box<dyn Fn(&i32) -> bool>>>()
208    ///     .is_none());
209    /// ```
210    ///
211    /// The compiler tells us that the type of model is not `FilterModel<VecModel<..>>`,
212    /// but instead `from_slice()` already returns a `ModelRc`, so the correct type to
213    /// use for the downcast is wrapped in `ModelRc`:
214    ///
215    /// ```
216    /// # use i_slint_core::model::*;
217    /// # use std::rc::Rc;
218    /// let model: FilterModel<ModelRc<i32>, Box<dyn Fn(&i32) -> bool>>
219    ///     = VecModel::from_slice(&[3i32, 2, 1])
220    ///       .filter(Box::new(|v: &i32| *v >= 2) as Box<dyn Fn(&i32) -> bool>);
221    /// let model_rc = ModelRc::new(model);
222    /// assert!(model_rc.as_any()
223    ///     .downcast_ref::<FilterModel<ModelRc<i32>, Box<dyn Fn(&i32) -> bool>>>()
224    ///     .is_some());
225    /// ```
226    fn as_any(&self) -> &dyn core::any::Any {
227        &()
228    }
229}
230
231/// Extension trait with extra methods implemented on types that implement [`Model`]
232pub trait ModelExt: Model {
233    /// Convenience function that calls [`ModelTracker::track_row_data_changes`]
234    /// before returning [`Model::row_data`].
235    ///
236    /// Calling [`row_data(row)`](Model::row_data) does not register the row as a dependency when calling it while
237    /// evaluating a property binding. This function calls [`track_row_data_changes(row)`](ModelTracker::track_row_data_changes)
238    /// on the [`self.model_tracker()`](Model::model_tracker) to enable tracking.
239    fn row_data_tracked(&self, row: usize) -> Option<Self::Data> {
240        self.model_tracker().track_row_data_changes(row);
241        self.row_data(row)
242    }
243
244    /// Returns a new Model where all elements are mapped by the function `map_function`.
245    /// This is a shortcut for [`MapModel::new()`].
246    fn map<F, U>(self, map_function: F) -> MapModel<Self, F>
247    where
248        Self: Sized + 'static,
249        F: Fn(Self::Data) -> U + 'static,
250    {
251        MapModel::new(self, map_function)
252    }
253
254    /// Returns a new Model where the elements are filtered by the function `filter_function`.
255    /// This is a shortcut for [`FilterModel::new()`].
256    fn filter<F>(self, filter_function: F) -> FilterModel<Self, F>
257    where
258        Self: Sized + 'static,
259        F: Fn(&Self::Data) -> bool + 'static,
260    {
261        FilterModel::new(self, filter_function)
262    }
263
264    /// Returns a new Model where the elements are sorted ascending.
265    /// This is a shortcut for [`SortModel::new_ascending()`].
266    #[must_use]
267    fn sort(self) -> SortModel<Self, adapters::AscendingSortHelper>
268    where
269        Self: Sized + 'static,
270        Self::Data: core::cmp::Ord,
271    {
272        SortModel::new_ascending(self)
273    }
274
275    /// Returns a new Model where the elements are sorted by the function `sort_function`.
276    /// This is a shortcut for [`SortModel::new()`].
277    fn sort_by<F>(self, sort_function: F) -> SortModel<Self, F>
278    where
279        Self: Sized + 'static,
280        F: FnMut(&Self::Data, &Self::Data) -> core::cmp::Ordering + 'static,
281    {
282        SortModel::new(self, sort_function)
283    }
284
285    /// Returns a new Model where the elements are reversed.
286    /// This is a shortcut for [`ReverseModel::new()`].
287    fn reverse(self) -> ReverseModel<Self>
288    where
289        Self: Sized + 'static,
290    {
291        ReverseModel::new(self)
292    }
293}
294
295impl<T: Model> ModelExt for T {}
296
297/// An iterator over the elements of a model.
298/// This struct is created by the [`Model::iter()`] trait function.
299pub struct ModelIterator<'a, T> {
300    model: &'a dyn Model<Data = T>,
301    row: usize,
302}
303
304impl<'a, T> ModelIterator<'a, T> {
305    /// Creates a new model iterator for a model reference.
306    /// This is the same as calling [`model.iter()`](Model::iter)
307    pub fn new(model: &'a dyn Model<Data = T>) -> Self {
308        Self { model, row: 0 }
309    }
310}
311
312impl<T> Iterator for ModelIterator<'_, T> {
313    type Item = T;
314
315    fn next(&mut self) -> Option<Self::Item> {
316        if self.row >= self.model.row_count() {
317            return None;
318        }
319        let row = self.row;
320        self.row += 1;
321        self.model.row_data(row)
322    }
323
324    fn size_hint(&self) -> (usize, Option<usize>) {
325        let len = self.model.row_count();
326        (len, Some(len))
327    }
328
329    fn nth(&mut self, n: usize) -> Option<Self::Item> {
330        self.row = self.row.checked_add(n)?;
331        self.next()
332    }
333}
334
335impl<T> ExactSizeIterator for ModelIterator<'_, T> {}
336
337impl<M: Model> Model for Rc<M> {
338    type Data = M::Data;
339
340    fn row_count(&self) -> usize {
341        (**self).row_count()
342    }
343
344    fn row_data(&self, row: usize) -> Option<Self::Data> {
345        (**self).row_data(row)
346    }
347
348    fn model_tracker(&self) -> &dyn ModelTracker {
349        (**self).model_tracker()
350    }
351
352    fn as_any(&self) -> &dyn core::any::Any {
353        (**self).as_any()
354    }
355    fn set_row_data(&self, row: usize, data: Self::Data) {
356        (**self).set_row_data(row, data)
357    }
358}
359
360/// A [`Model`] backed by a `Vec<T>`, using interior mutability.
361pub struct VecModel<T> {
362    array: RefCell<Vec<T>>,
363    notify: ModelNotify,
364}
365
366impl<T> Default for VecModel<T> {
367    fn default() -> Self {
368        Self { array: Default::default(), notify: Default::default() }
369    }
370}
371
372impl<T: 'static> VecModel<T> {
373    /// Allocate a new model from a slice
374    pub fn from_slice(slice: &[T]) -> ModelRc<T>
375    where
376        T: Clone,
377    {
378        ModelRc::new(Self::from(slice.to_vec()))
379    }
380
381    /// Add a row at the end of the model
382    pub fn push(&self, value: T) {
383        self.array.borrow_mut().push(value);
384        self.notify.row_added(self.array.borrow().len() - 1, 1)
385    }
386
387    /// Inserts a row at position index. All rows after that are shifted.
388    /// This function panics if index is > row_count().
389    pub fn insert(&self, index: usize, value: T) {
390        self.array.borrow_mut().insert(index, value);
391        self.notify.row_added(index, 1)
392    }
393
394    /// Remove the row at the given index from the model
395    ///
396    /// Returns the removed row
397    pub fn remove(&self, index: usize) -> T {
398        let r = self.array.borrow_mut().remove(index);
399        self.notify.row_removed(index, 1);
400        r
401    }
402
403    /// Replace inner Vec with new data
404    pub fn set_vec(&self, new: impl Into<Vec<T>>) {
405        *self.array.borrow_mut() = new.into();
406        self.notify.reset();
407    }
408
409    /// Extend the model with the content of the iterator
410    ///
411    /// Similar to [`Vec::extend`]
412    pub fn extend<I: IntoIterator<Item = T>>(&self, iter: I) {
413        let mut array = self.array.borrow_mut();
414        let old_idx = array.len();
415        array.extend(iter);
416        let count = array.len() - old_idx;
417        drop(array);
418        self.notify.row_added(old_idx, count);
419    }
420
421    /// Clears the model, removing all values
422    ///
423    /// Similar to [`Vec::clear`]
424    pub fn clear(&self) {
425        self.array.borrow_mut().clear();
426        self.notify.reset();
427    }
428
429    /// Swaps two elements in the model.
430    pub fn swap(&self, a: usize, b: usize) {
431        if a == b {
432            return;
433        }
434
435        self.array.borrow_mut().swap(a, b);
436        self.notify.row_changed(a);
437        self.notify.row_changed(b);
438    }
439}
440
441impl<T: Clone + 'static> VecModel<T> {
442    /// Appends all the elements in the slice to the model
443    ///
444    /// Similar to [`Vec::extend_from_slice`]
445    pub fn extend_from_slice(&self, src: &[T]) {
446        let mut array = self.array.borrow_mut();
447        let old_idx = array.len();
448
449        array.extend_from_slice(src);
450        drop(array);
451        self.notify.row_added(old_idx, src.len());
452    }
453}
454
455impl<T> From<Vec<T>> for VecModel<T> {
456    fn from(array: Vec<T>) -> Self {
457        VecModel { array: RefCell::new(array), notify: Default::default() }
458    }
459}
460
461impl<T> FromIterator<T> for VecModel<T> {
462    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
463        VecModel::from(Vec::from_iter(iter))
464    }
465}
466
467impl<T: Clone + 'static> Model for VecModel<T> {
468    type Data = T;
469
470    fn row_count(&self) -> usize {
471        self.array.borrow().len()
472    }
473
474    fn row_data(&self, row: usize) -> Option<Self::Data> {
475        self.array.borrow().get(row).cloned()
476    }
477
478    fn set_row_data(&self, row: usize, data: Self::Data) {
479        if row < self.row_count() {
480            self.array.borrow_mut()[row] = data;
481            self.notify.row_changed(row);
482        }
483    }
484
485    fn model_tracker(&self) -> &dyn ModelTracker {
486        &self.notify
487    }
488
489    fn as_any(&self) -> &dyn core::any::Any {
490        self
491    }
492}
493
494/// A model backed by a `SharedVector<T>`
495#[derive(Default)]
496pub struct SharedVectorModel<T> {
497    array: RefCell<SharedVector<T>>,
498    notify: ModelNotify,
499}
500
501impl<T: Clone + 'static> SharedVectorModel<T> {
502    /// Add a row at the end of the model
503    pub fn push(&self, value: T) {
504        self.array.borrow_mut().push(value);
505        self.notify.row_added(self.array.borrow().len() - 1, 1)
506    }
507}
508
509impl<T> SharedVectorModel<T> {
510    /// Returns a clone of the model's backing shared vector.
511    pub fn shared_vector(&self) -> SharedVector<T> {
512        self.array.borrow_mut().clone()
513    }
514}
515
516impl<T> From<SharedVector<T>> for SharedVectorModel<T> {
517    fn from(array: SharedVector<T>) -> Self {
518        SharedVectorModel { array: RefCell::new(array), notify: Default::default() }
519    }
520}
521
522impl<T: Clone + 'static> Model for SharedVectorModel<T> {
523    type Data = T;
524
525    fn row_count(&self) -> usize {
526        self.array.borrow().len()
527    }
528
529    fn row_data(&self, row: usize) -> Option<Self::Data> {
530        self.array.borrow().get(row).cloned()
531    }
532
533    fn set_row_data(&self, row: usize, data: Self::Data) {
534        self.array.borrow_mut().make_mut_slice()[row] = data;
535        self.notify.row_changed(row);
536    }
537
538    fn model_tracker(&self) -> &dyn ModelTracker {
539        &self.notify
540    }
541
542    fn as_any(&self) -> &dyn core::any::Any {
543        self
544    }
545}
546
547impl Model for usize {
548    type Data = i32;
549
550    fn row_count(&self) -> usize {
551        *self
552    }
553
554    fn row_data(&self, row: usize) -> Option<Self::Data> {
555        (row < self.row_count()).then_some(row as i32)
556    }
557
558    fn as_any(&self) -> &dyn core::any::Any {
559        self
560    }
561
562    fn model_tracker(&self) -> &dyn ModelTracker {
563        &()
564    }
565}
566
567impl Model for bool {
568    type Data = ();
569
570    fn row_count(&self) -> usize {
571        if *self { 1 } else { 0 }
572    }
573
574    fn row_data(&self, row: usize) -> Option<Self::Data> {
575        (row < self.row_count()).then_some(())
576    }
577
578    fn as_any(&self) -> &dyn core::any::Any {
579        self
580    }
581
582    fn model_tracker(&self) -> &dyn ModelTracker {
583        &()
584    }
585}
586
587/// ModelRc is a type wrapper for a reference counted implementation of the [`Model`] trait.
588///
589/// Models are used to represent sequences of the same data type. In `.slint` code those
590/// are represented using the `[T]` array syntax and typically used in `for` expressions,
591/// array properties, and array struct fields.
592///
593/// For example, a `property <[string]> foo` will be of type `ModelRc<SharedString>`
594/// and, behind the scenes, wraps a `Rc<dyn Model<Data = SharedString>>.`
595///
596/// An array struct field will also be of type `ModelRc`:
597///
598/// ```slint,no-preview
599/// export struct AddressBook {
600///     names: [string]
601/// }
602/// ```
603///
604/// When accessing `AddressBook` from Rust, the `names` field will be of type `ModelRc<SharedString>`.
605///
606/// There are several ways of constructing a ModelRc in Rust:
607///
608/// * An empty ModelRc can be constructed with [`ModelRc::default()`].
609/// * A `ModelRc` can be constructed from a slice or an array using the [`From`] trait.
610///   This allocates a [`VecModel`].
611/// * Use [`ModelRc::new()`] to construct a `ModelRc` from a type that implements the
612///   [`Model`] trait, such as [`VecModel`] or your own implementation.
613/// * If you have your model already in an `Rc`, then you can use the [`From`] trait
614///   to convert from `Rc<dyn Model<Data = T>>` to `ModelRc`.
615///
616/// ## Example
617///
618/// ```rust
619/// # i_slint_backend_testing::init_no_event_loop();
620/// use slint::{slint, SharedString, ModelRc, Model, VecModel};
621/// use std::rc::Rc;
622/// slint!{
623///     import { Button } from "std-widgets.slint";
624///     export component Example {
625///         callback add_item <=> btn.clicked;
626///         in property <[string]> the_model;
627///         HorizontalLayout {
628///             for it in the_model : Text { text: it; }
629///             btn := Button { text: "Add"; }
630///         }
631///     }
632/// }
633/// let ui = Example::new().unwrap();
634/// // Create a VecModel and put it in an Rc.
635/// let the_model : Rc<VecModel<SharedString>> =
636///         Rc::new(VecModel::from(vec!["Hello".into(), "World".into()]));
637/// // Convert it to a ModelRc.
638/// let the_model_rc = ModelRc::from(the_model.clone());
639/// // Pass the model to the ui: The generated set_the_model setter from the
640/// // the_model property takes a ModelRc.
641/// ui.set_the_model(the_model_rc);
642///
643/// // We have kept a strong reference to the_model, to modify it in a callback.
644/// ui.on_add_item(move || {
645///     // Use VecModel API: VecModel uses the Model notification mechanism to let Slint
646///     // know it needs to refresh the UI.
647///     the_model.push("SomeValue".into());
648/// });
649///
650/// // Alternative: we can re-use a getter.
651/// let ui_weak = ui.as_weak();
652/// ui.on_add_item(move || {
653///     let ui = ui_weak.unwrap();
654///     let the_model_rc = ui.get_the_model();
655///     let the_model = the_model_rc.as_any().downcast_ref::<VecModel<SharedString>>()
656///         .expect("We know we set a VecModel earlier");
657///     the_model.push("An Item".into());
658/// });
659/// ```
660///
661/// ### Updating the Model from a Thread
662///
663/// `ModelRc` is not `Send` and can only be used in the main thread.
664/// If you want to update the model based on data coming from another thread, you need to send back the data to the main thread
665/// using [`invoke_from_event_loop`](crate::api::invoke_from_event_loop) or
666/// [`Weak::upgrade_in_event_loop`](crate::api::Weak::upgrade_in_event_loop).
667///
668/// ```rust
669/// # i_slint_backend_testing::init_integration_test_with_mock_time();
670/// use slint::Model;
671/// slint::slint!{
672///     export component TestCase inherits Window {
673///         in property <[string]> the_model;
674///         //...
675///     }
676/// }
677/// let ui = TestCase::new().unwrap();
678/// // set a model (a VecModel)
679/// let model = std::rc::Rc::new(slint::VecModel::<slint::SharedString>::default());
680/// ui.set_the_model(model.clone().into());
681///
682/// // do some work in a thread
683/// let ui_weak = ui.as_weak();
684/// let thread = std::thread::spawn(move || {
685///     // do some work
686///     let new_strings = vec!["foo".into(), "bar".into()];
687///     // send the data back to the main thread
688///     ui_weak.upgrade_in_event_loop(move |ui| {
689///         let model = ui.get_the_model();
690///         let model = model.as_any().downcast_ref::<slint::VecModel<slint::SharedString>>()
691///             .expect("We know we set a VecModel earlier");
692///         model.set_vec(new_strings);
693/// #       slint::quit_event_loop().unwrap();
694///     });
695/// });
696/// ui.run().unwrap();
697/// ```
698pub struct ModelRc<T>(Option<Rc<dyn Model<Data = T>>>);
699
700impl<T> core::fmt::Debug for ModelRc<T> {
701    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
702        write!(f, "ModelRc(dyn Model)")
703    }
704}
705
706impl<T> Clone for ModelRc<T> {
707    fn clone(&self) -> Self {
708        Self(self.0.clone())
709    }
710}
711
712impl<T> Default for ModelRc<T> {
713    /// Construct an empty model
714    fn default() -> Self {
715        Self(None)
716    }
717}
718
719impl<T> core::cmp::PartialEq for ModelRc<T> {
720    fn eq(&self, other: &Self) -> bool {
721        match (&self.0, &other.0) {
722            (None, None) => true,
723            (Some(a), Some(b)) => core::ptr::eq(
724                (&**a) as *const dyn Model<Data = T> as *const u8,
725                (&**b) as *const dyn Model<Data = T> as *const u8,
726            ),
727            _ => false,
728        }
729    }
730}
731
732#[cfg(feature = "serde")]
733use serde::ser::SerializeSeq;
734#[cfg(feature = "serde")]
735impl<T> serde::Serialize for ModelRc<T>
736where
737    T: serde::Serialize,
738{
739    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
740    where
741        S: serde::Serializer,
742    {
743        let mut seq = serializer.serialize_seq(Some(self.row_count()))?;
744        for item in self.iter() {
745            seq.serialize_element(&item)?;
746        }
747        seq.end()
748    }
749}
750
751#[cfg(feature = "serde")]
752impl<'de, T> serde::Deserialize<'de> for ModelRc<T>
753where
754    T: serde::Deserialize<'de> + Clone + 'static,
755{
756    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
757    where
758        D: serde::Deserializer<'de>,
759    {
760        let vec = Vec::<T>::deserialize(deserializer)?;
761        if vec.is_empty() {
762            return Ok(ModelRc::default());
763        }
764        Ok(ModelRc::new(VecModel::from(vec)))
765    }
766}
767
768impl<T> ModelRc<T> {
769    pub fn new(model: impl Model<Data = T> + 'static) -> Self {
770        Self(Some(Rc::new(model)))
771    }
772}
773
774impl<T, M: Model<Data = T> + 'static> From<Rc<M>> for ModelRc<T> {
775    fn from(model: Rc<M>) -> Self {
776        Self(Some(model))
777    }
778}
779
780impl<T> From<Rc<dyn Model<Data = T> + 'static>> for ModelRc<T> {
781    fn from(model: Rc<dyn Model<Data = T> + 'static>) -> Self {
782        Self(Some(model))
783    }
784}
785
786impl<T: Clone + 'static> From<&[T]> for ModelRc<T> {
787    fn from(slice: &[T]) -> Self {
788        VecModel::from_slice(slice)
789    }
790}
791
792impl<T: Clone + 'static, const N: usize> From<[T; N]> for ModelRc<T> {
793    fn from(array: [T; N]) -> Self {
794        VecModel::from_slice(&array)
795    }
796}
797
798impl<T> TryInto<Rc<dyn Model<Data = T>>> for ModelRc<T> {
799    type Error = ();
800
801    fn try_into(self) -> Result<Rc<dyn Model<Data = T>>, Self::Error> {
802        self.0.ok_or(())
803    }
804}
805
806impl<T> Model for ModelRc<T> {
807    type Data = T;
808
809    fn row_count(&self) -> usize {
810        self.0.as_ref().map_or(0, |model| model.row_count())
811    }
812
813    fn row_data(&self, row: usize) -> Option<Self::Data> {
814        self.0.as_ref().and_then(|model| model.row_data(row))
815    }
816
817    fn set_row_data(&self, row: usize, data: Self::Data) {
818        if let Some(model) = self.0.as_ref() {
819            model.set_row_data(row, data);
820        }
821    }
822
823    fn model_tracker(&self) -> &dyn ModelTracker {
824        self.0.as_ref().map_or(&(), |model| model.model_tracker())
825    }
826
827    fn as_any(&self) -> &dyn core::any::Any {
828        self.0.as_ref().map_or(&(), |model| model.as_any())
829    }
830}
831
832impl From<SharedString> for StandardListViewItem {
833    fn from(value: SharedString) -> Self {
834        StandardListViewItem { text: value }
835    }
836}
837
838impl From<&str> for StandardListViewItem {
839    fn from(value: &str) -> Self {
840        StandardListViewItem { text: value.into() }
841    }
842}
843
844#[cfg(test)]
845mod tests {
846    use super::*;
847    use std::vec;
848
849    #[cfg(feature = "serde")]
850    #[test]
851    fn test_serialize_deserialize_modelrc() {
852        let model_rc = ModelRc::new(VecModel::from(vec![1, 2, 3]));
853        let serialized = serde_json::to_string(&model_rc).unwrap();
854        let deserialized: ModelRc<i32> = serde_json::from_str(&serialized).unwrap();
855        assert_eq!(deserialized.row_count(), 3);
856        assert_eq!(deserialized.row_data(0), Some(1));
857        assert_eq!(deserialized.row_data(1), Some(2));
858        assert_eq!(deserialized.row_data(2), Some(3));
859    }
860
861    #[test]
862    fn test_tracking_model_handle() {
863        let model: Rc<VecModel<u8>> = Rc::new(Default::default());
864        let handle = ModelRc::from(model.clone() as Rc<dyn Model<Data = u8>>);
865        let tracker = Box::pin(<crate::properties::PropertyTracker>::default());
866        assert_eq!(
867            tracker.as_ref().evaluate(|| {
868                handle.model_tracker().track_row_count_changes();
869                handle.row_count()
870            }),
871            0
872        );
873        assert!(!tracker.is_dirty());
874        model.push(42);
875        model.push(100);
876        assert!(tracker.is_dirty());
877        assert_eq!(
878            tracker.as_ref().evaluate(|| {
879                handle.model_tracker().track_row_count_changes();
880                handle.row_count()
881            }),
882            2
883        );
884        assert!(!tracker.is_dirty());
885        model.set_row_data(0, 41);
886        assert!(!tracker.is_dirty());
887        model.remove(0);
888        assert!(tracker.is_dirty());
889        assert_eq!(
890            tracker.as_ref().evaluate(|| {
891                handle.model_tracker().track_row_count_changes();
892                handle.row_count()
893            }),
894            1
895        );
896        assert!(!tracker.is_dirty());
897        model.set_vec(vec![1, 2, 3]);
898        assert!(tracker.is_dirty());
899    }
900
901    #[test]
902    fn test_data_tracking() {
903        let model: Rc<VecModel<u8>> = Rc::new(VecModel::from(vec![0, 1, 2, 3, 4]));
904        let handle = ModelRc::from(model.clone());
905        let tracker = Box::pin(<crate::properties::PropertyTracker>::default());
906        assert_eq!(
907            tracker.as_ref().evaluate(|| {
908                handle.model_tracker().track_row_data_changes(1);
909                handle.row_data(1).unwrap()
910            }),
911            1
912        );
913        assert!(!tracker.is_dirty());
914
915        model.set_row_data(2, 42);
916        assert!(!tracker.is_dirty());
917        model.set_row_data(1, 100);
918        assert!(tracker.is_dirty());
919
920        assert_eq!(
921            tracker.as_ref().evaluate(|| {
922                handle.model_tracker().track_row_data_changes(1);
923                handle.row_data(1).unwrap()
924            }),
925            100
926        );
927        assert!(!tracker.is_dirty());
928
929        // Any changes to rows (even if after tracked rows) for now also marks watched rows as dirty, to
930        // keep the logic simple.
931        model.push(200);
932        assert!(tracker.is_dirty());
933
934        assert_eq!(tracker.as_ref().evaluate(|| { handle.row_data_tracked(1).unwrap() }), 100);
935        assert!(!tracker.is_dirty());
936
937        model.insert(0, 255);
938        assert!(tracker.is_dirty());
939
940        model.set_vec(Vec::new());
941        assert!(tracker.is_dirty());
942    }
943
944    #[derive(Default)]
945    struct TestView {
946        // Track the parameters reported by the model (row counts, indices, etc.).
947        // The last field in the tuple is the row size the model reports at the time
948        // of callback
949        changed_rows: RefCell<Vec<(usize, usize)>>,
950        added_rows: RefCell<Vec<(usize, usize, usize)>>,
951        removed_rows: RefCell<Vec<(usize, usize, usize)>>,
952        reset: RefCell<usize>,
953        model: RefCell<Option<std::rc::Weak<dyn Model<Data = i32>>>>,
954    }
955    impl TestView {
956        fn clear(&self) {
957            self.changed_rows.borrow_mut().clear();
958            self.added_rows.borrow_mut().clear();
959            self.removed_rows.borrow_mut().clear();
960            *self.reset.borrow_mut() = 0;
961        }
962        fn row_count(&self) -> usize {
963            self.model
964                .borrow()
965                .as_ref()
966                .and_then(|model| model.upgrade())
967                .map_or(0, |model| model.row_count())
968        }
969    }
970    impl ModelChangeListener for TestView {
971        fn row_changed(self: Pin<&Self>, row: usize) {
972            self.changed_rows.borrow_mut().push((row, self.row_count()));
973        }
974
975        fn row_added(self: Pin<&Self>, index: usize, count: usize) {
976            self.added_rows.borrow_mut().push((index, count, self.row_count()));
977        }
978
979        fn row_removed(self: Pin<&Self>, index: usize, count: usize) {
980            self.removed_rows.borrow_mut().push((index, count, self.row_count()));
981        }
982        fn reset(self: Pin<&Self>) {
983            *self.reset.borrow_mut() += 1;
984        }
985    }
986
987    #[test]
988    fn test_vecmodel_set_vec() {
989        let view = Box::pin(ModelChangeListenerContainer::<TestView>::default());
990
991        let model = Rc::new(VecModel::from(vec![1i32, 2, 3, 4]));
992        model.model_tracker().attach_peer(Pin::as_ref(&view).model_peer());
993        *view.model.borrow_mut() =
994            Some(std::rc::Rc::downgrade(&(model.clone() as Rc<dyn Model<Data = i32>>)));
995
996        model.push(5);
997        assert!(view.changed_rows.borrow().is_empty());
998        assert_eq!(&*view.added_rows.borrow(), &[(4, 1, 5)]);
999        assert!(view.removed_rows.borrow().is_empty());
1000        assert_eq!(*view.reset.borrow(), 0);
1001        view.clear();
1002
1003        model.set_vec(vec![6, 7, 8]);
1004        assert!(view.changed_rows.borrow().is_empty());
1005        assert!(view.added_rows.borrow().is_empty());
1006        assert!(view.removed_rows.borrow().is_empty());
1007        assert_eq!(*view.reset.borrow(), 1);
1008        view.clear();
1009
1010        model.extend_from_slice(&[9, 10, 11]);
1011        assert!(view.changed_rows.borrow().is_empty());
1012        assert_eq!(&*view.added_rows.borrow(), &[(3, 3, 6)]);
1013        assert!(view.removed_rows.borrow().is_empty());
1014        assert_eq!(*view.reset.borrow(), 0);
1015        view.clear();
1016
1017        model.extend([12, 13]);
1018        assert!(view.changed_rows.borrow().is_empty());
1019        assert_eq!(&*view.added_rows.borrow(), &[(6, 2, 8)]);
1020        assert!(view.removed_rows.borrow().is_empty());
1021        assert_eq!(*view.reset.borrow(), 0);
1022        view.clear();
1023
1024        assert_eq!(model.iter().collect::<Vec<_>>(), vec![6, 7, 8, 9, 10, 11, 12, 13]);
1025
1026        model.swap(1, 1);
1027        assert!(view.changed_rows.borrow().is_empty());
1028        assert!(view.added_rows.borrow().is_empty());
1029        assert!(view.removed_rows.borrow().is_empty());
1030        assert_eq!(*view.reset.borrow(), 0);
1031        view.clear();
1032
1033        model.swap(1, 2);
1034        assert_eq!(&*view.changed_rows.borrow(), &[(1, 8), (2, 8)]);
1035        assert!(view.added_rows.borrow().is_empty());
1036        assert!(view.removed_rows.borrow().is_empty());
1037        assert_eq!(*view.reset.borrow(), 0);
1038        view.clear();
1039
1040        assert_eq!(model.iter().collect::<Vec<_>>(), vec![6, 8, 7, 9, 10, 11, 12, 13]);
1041    }
1042
1043    #[test]
1044    fn test_vecmodel_clear() {
1045        let view = Box::pin(ModelChangeListenerContainer::<TestView>::default());
1046
1047        let model = Rc::new(VecModel::from(vec![1, 2, 3, 4]));
1048        model.model_tracker().attach_peer(Pin::as_ref(&view).model_peer());
1049        *view.model.borrow_mut() =
1050            Some(std::rc::Rc::downgrade(&(model.clone() as Rc<dyn Model<Data = i32>>)));
1051
1052        model.clear();
1053        assert_eq!(*view.reset.borrow(), 1);
1054        assert_eq!(model.row_count(), 0);
1055    }
1056
1057    #[test]
1058    fn test_vecmodel_swap() {
1059        let view = Box::pin(ModelChangeListenerContainer::<TestView>::default());
1060
1061        let model = Rc::new(VecModel::from(vec![1, 2, 3, 4]));
1062        model.model_tracker().attach_peer(Pin::as_ref(&view).model_peer());
1063        *view.model.borrow_mut() =
1064            Some(std::rc::Rc::downgrade(&(model.clone() as Rc<dyn Model<Data = i32>>)));
1065
1066        model.swap(1, 1);
1067        assert!(view.changed_rows.borrow().is_empty());
1068        assert!(view.added_rows.borrow().is_empty());
1069        assert!(view.removed_rows.borrow().is_empty());
1070        assert_eq!(*view.reset.borrow(), 0);
1071        view.clear();
1072
1073        model.swap(1, 2);
1074        assert_eq!(&*view.changed_rows.borrow(), &[(1, 4), (2, 4)]);
1075        assert!(view.added_rows.borrow().is_empty());
1076        assert!(view.removed_rows.borrow().is_empty());
1077        assert_eq!(*view.reset.borrow(), 0);
1078        view.clear();
1079    }
1080
1081    #[test]
1082    fn modeliter_in_bounds() {
1083        struct TestModel {
1084            length: usize,
1085            max_requested_row: Cell<usize>,
1086            notify: ModelNotify,
1087        }
1088
1089        impl Model for TestModel {
1090            type Data = usize;
1091
1092            fn row_count(&self) -> usize {
1093                self.length
1094            }
1095
1096            fn row_data(&self, row: usize) -> Option<usize> {
1097                self.max_requested_row.set(self.max_requested_row.get().max(row));
1098                (row < self.length).then_some(row)
1099            }
1100
1101            fn model_tracker(&self) -> &dyn ModelTracker {
1102                &self.notify
1103            }
1104        }
1105
1106        let model = Rc::new(TestModel {
1107            length: 10,
1108            max_requested_row: Cell::new(0),
1109            notify: Default::default(),
1110        });
1111
1112        assert_eq!(model.iter().max().unwrap(), 9);
1113        assert_eq!(model.max_requested_row.get(), 9);
1114    }
1115
1116    #[test]
1117    fn vecmodel_doesnt_require_default() {
1118        #[derive(Clone)]
1119        struct MyNoDefaultType {
1120            _foo: bool,
1121        }
1122        let model = VecModel::<MyNoDefaultType>::default();
1123        assert_eq!(model.row_count(), 0);
1124        model.push(MyNoDefaultType { _foo: true });
1125    }
1126}