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 doesnt downcasted modeliter modelrc
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, ListViewProperties, RepeatedItemTree, Repeater, RepeaterTracker};
27
28/// Error returned by the row mutation functions of [`Model`] when the modification
29/// was not applied.
30#[derive(Debug, Clone, Eq, PartialEq, derive_more::Error, derive_more::Display)]
31pub struct ModelError(#[error(not(source))] ErrorImpl);
32
33#[derive(Debug, Clone, Eq, PartialEq, derive_more::Display)]
34enum ErrorImpl {
35    #[display("the row index is out of bounds (the model has {_0} rows)")]
36    OutOfBounds(usize),
37    #[display("the model {_0} does not support this modification")]
38    Unsupported(alloc::borrow::Cow<'static, str>),
39}
40
41impl ModelError {
42    /// The row index is out of the model's bounds. `row_count` is the model's number of rows.
43    pub fn out_of_bounds(row_count: usize) -> Self {
44        Self(ErrorImpl::OutOfBounds(row_count))
45    }
46
47    /// The model does not support this modification.
48    pub fn unsupported(model: &(impl Model + ?Sized)) -> Self {
49        Self(ErrorImpl::Unsupported(core::any::type_name_of_val(model).into()))
50    }
51
52    /// The model with the given type name does not support this modification.
53    ///
54    /// Not part of the public API: for the bridges to models implemented in
55    /// another language, where the type name of the [`Model`] implementation
56    /// would name the wrapper instead of the model.
57    #[doc(hidden)]
58    pub fn unsupported_by_name(
59        model_type_name: impl Into<alloc::borrow::Cow<'static, str>>,
60        _: crate::InternalToken,
61    ) -> Self {
62        Self(ErrorImpl::Unsupported(model_type_name.into()))
63    }
64}
65
66/// This trait defines the interface that users of a model can use to track changes
67/// to a model. It is supplied via [`Model::model_tracker`] and implementation usually
68/// return a reference to its field of [`ModelNotify`].
69pub trait ModelTracker {
70    /// Attach one peer. The peer will be notified when the model changes
71    fn attach_peer(&self, peer: ModelPeer);
72    /// Register the model as a dependency to the current binding being evaluated, so
73    /// that it will be notified when the model changes its size.
74    fn track_row_count_changes(&self);
75    /// Register a row as a dependency to the current binding being evaluated, so that
76    /// it will be notified when the value of that row changes.
77    fn track_row_data_changes(&self, row: usize);
78
79    /// Register the whole model as a dependency to the current binding being evaluated,
80    /// so that it will be notified of any change to the model: the row count as well as
81    /// the data of any of the `row_count` rows.
82    ///
83    /// This is equivalent to calling [`Self::track_row_count_changes`] and then
84    /// [`Self::track_row_data_changes`] for every row, which is what the default
85    /// implementation does, but implementations such as [`ModelNotify`] register a
86    /// single dependency whose cost is independent of the number of rows.
87    ///
88    /// Not part of the public API: the `row_count` parameter only exists for the
89    /// default implementation and may change.
90    #[doc(hidden)]
91    fn track_any_change(&self, row_count: usize, _: crate::InternalToken) {
92        self.track_row_count_changes();
93        for row in 0..row_count {
94            self.track_row_data_changes(row);
95        }
96    }
97}
98
99impl ModelTracker for () {
100    fn attach_peer(&self, _peer: ModelPeer) {}
101
102    fn track_row_count_changes(&self) {}
103    fn track_row_data_changes(&self, _row: usize) {}
104    fn track_any_change(&self, _row_count: usize, _: crate::InternalToken) {}
105}
106
107/// A Model is providing Data for the repeated elements with `for` in the `.slint` language
108///
109/// If the model can be changed, the type implementing the Model trait should hold
110/// a [`ModelNotify`], and is responsible to call functions on it to let the UI know that
111/// something has changed.
112///
113/// Properties of type array will be mapped to a [`ModelRc<T>`], which wraps a `Rc<Model<Data = T>>.`
114/// The [`ModelRc`] documentation has examples on how to set models to array properties.
115///
116/// It is more efficient to operate on the model and send changes through the `ModelNotify` rather than
117/// resetting the property with a different model.
118///
119/// ## Example
120///
121/// As an example, let's see the implementation of [`VecModel`].
122///
123/// ```
124/// # use i_slint_core::model::{Model, ModelNotify, ModelPeer, ModelTracker};
125/// pub struct VecModel<T> {
126///     // the backing data, stored in a `RefCell` as this model can be modified
127///     array: std::cell::RefCell<Vec<T>>,
128///     // the ModelNotify will allow to notify the UI that the model changes
129///     notify: ModelNotify,
130/// }
131///
132/// impl<T: Clone + 'static> Model for VecModel<T> {
133///     type Data = T;
134///
135///     fn row_count(&self) -> usize {
136///         self.array.borrow().len()
137///     }
138///
139///     fn row_data(&self, row: usize) -> Option<Self::Data> {
140///         self.array.borrow().get(row).cloned()
141///     }
142///
143///     fn set_row_data(&self, row: usize, data: Self::Data) {
144///         self.array.borrow_mut()[row] = data;
145///         // don't forget to call row_changed
146///         self.notify.row_changed(row);
147///     }
148///
149///     fn model_tracker(&self) -> &dyn ModelTracker {
150///         &self.notify
151///     }
152///
153///     fn as_any(&self) -> &dyn core::any::Any {
154///         // a typical implementation just return `self`
155///         self
156///     }
157/// }
158///
159/// // when modifying the model, we call the corresponding function in
160/// // the ModelNotify
161/// impl<T> VecModel<T> {
162///     /// Add a row at the end of the model
163///     pub fn push(&self, value: T) {
164///         self.array.borrow_mut().push(value);
165///         self.notify.row_added(self.array.borrow().len() - 1, 1)
166///     }
167///
168///     /// Remove the row at the given index from the model
169///     pub fn remove(&self, index: usize) {
170///         self.array.borrow_mut().remove(index);
171///         self.notify.row_removed(index, 1)
172///     }
173/// }
174/// ```
175pub trait Model {
176    /// The model data: A model is a set of rows and each row has this data
177    type Data;
178    /// The number of rows in the model
179    fn row_count(&self) -> usize;
180    /// Returns the data for a particular row.
181    ///
182    /// This function should normally be called with `row < row_count()` and should return None otherwise.
183    ///
184    /// This function does not register dependencies on the current binding. For an equivalent
185    /// function that tracks dependencies, see [`ModelExt::row_data_tracked`]
186    fn row_data(&self, row: usize) -> Option<Self::Data>;
187    /// Sets the data for a particular row.
188    ///
189    /// This function should be called with `row < row_count()`, otherwise the implementation can panic.
190    ///
191    /// If the model cannot support data changes, then it is ok to do nothing.
192    /// The default implementation will print a warning to stderr.
193    ///
194    /// If the model can update the data, it should also call [`ModelNotify::row_changed`] on its
195    /// internal [`ModelNotify`].
196    fn set_row_data(&self, _row: usize, _data: Self::Data) {
197        #[cfg(feature = "std")]
198        crate::debug_log!(
199            "Model::set_row_data called on a model of type {} which does not re-implement this method. \
200            This happens when trying to modify a read-only model",
201            core::any::type_name::<Self>(),
202        );
203    }
204
205    /// Add a new row at the end of the model.
206    ///
207    /// The default implementation inserts the row after the last one with
208    /// [`insert_row`](Self::insert_row).
209    fn push_row(&self, data: Self::Data) -> Result<(), ModelError> {
210        self.insert_row(self.row_count(), data)
211    }
212
213    /// Remove the row at the specified index from the model.
214    ///
215    /// This function should be called with `row < row_count()`.
216    ///
217    /// The default implementation returns [`ModelError::unsupported`]; implementations
218    /// should return [`ModelError::out_of_bounds`] when `row` is out of bounds.
219    ///
220    /// If the model can update the data, it should also call [`ModelNotify::row_removed`] on its
221    /// internal [`ModelNotify`].
222    fn remove_row(&self, _row: usize) -> Result<(), ModelError> {
223        Err(ModelError::unsupported(self))
224    }
225
226    /// Insert a new row at the specified index and move the next rows by 1 step to the right.
227    ///
228    /// The default implementation returns [`ModelError::unsupported`]; implementations
229    /// should return [`ModelError::out_of_bounds`] when `row` is out of bounds.
230    ///
231    /// If the model can update the data, it should also call [`ModelNotify::row_added`] on its
232    /// internal [`ModelNotify`].
233    fn insert_row(&self, _row: usize, _data: Self::Data) -> Result<(), ModelError> {
234        Err(ModelError::unsupported(self))
235    }
236
237    /// The implementation should return a reference to its [`ModelNotify`] field.
238    ///
239    /// You can return `&()` if you your `Model` is constant and does not have a ModelNotify field.
240    fn model_tracker(&self) -> &dyn ModelTracker;
241
242    /// Returns an iterator visiting all elements of the model.
243    fn iter(&self) -> ModelIterator<'_, Self::Data>
244    where
245        Self: Sized,
246    {
247        ModelIterator::new(self)
248    }
249
250    /// Return something that can be downcast'ed (typically self).
251    ///
252    /// Use this to retrieve the concrete model from a [`ModelRc`] stored
253    /// in your tree of UI elements.
254    ///
255    /// ```
256    /// # use i_slint_core::model::*;
257    /// # use std::rc::Rc;
258    /// let handle = ModelRc::new(VecModel::from(vec![1i32, 2, 3]));
259    /// // later:
260    /// handle.as_any().downcast_ref::<VecModel<i32>>().unwrap().push(4);
261    /// assert_eq!(handle.row_data(3).unwrap(), 4);
262    /// ```
263    ///
264    /// Note: Custom models must implement this method for the cast to succeed.
265    /// A valid implementation is to return `self`:
266    /// ```ignore
267    ///     fn as_any(&self) -> &dyn core::any::Any { self }
268    /// ```
269    ///
270    /// ## Troubleshooting
271    /// A common reason why the downcast fails at run-time is because of a type-mismatch
272    /// between the model created and the model downcasted. To debug this at compile time,
273    /// try matching the model type used for the downcast explicitly at model creation time.
274    /// In the following example, the downcast fails at run-time:
275    ///
276    /// ```
277    /// # use i_slint_core::model::*;
278    /// # use std::rc::Rc;
279    /// let model = VecModel::from_slice(&[3i32, 2, 1])
280    ///     .filter(Box::new(|v: &i32| *v >= 2) as Box<dyn Fn(&i32) -> bool>);
281    /// let model_rc = ModelRc::new(model);
282    /// assert!(model_rc.as_any()
283    ///     .downcast_ref::<FilterModel<VecModel<i32>, Box<dyn Fn(&i32) -> bool>>>()
284    ///     .is_none());
285    /// ```
286    ///
287    /// To debug this, let's make the type explicit. It fails to compile.
288    ///
289    /// ```compile_fail
290    /// # use i_slint_core::model::*;
291    /// # use std::rc::Rc;
292    /// let model: FilterModel<VecModel<i32>, Box<dyn Fn(&i32) -> bool>>
293    ///     = VecModel::from_slice(&[3i32, 2, 1])
294    ///       .filter(Box::new(|v: &i32| *v >= 2) as Box<dyn Fn(&i32) -> bool>);
295    /// let model_rc = ModelRc::new(model);
296    /// assert!(model_rc.as_any()
297    ///     .downcast_ref::<FilterModel<VecModel<i32>, Box<dyn Fn(&i32) -> bool>>>()
298    ///     .is_none());
299    /// ```
300    ///
301    /// The compiler tells us that the type of model is not `FilterModel<VecModel<..>>`,
302    /// but instead `from_slice()` already returns a `ModelRc`, so the correct type to
303    /// use for the downcast is wrapped in `ModelRc`:
304    ///
305    /// ```
306    /// # use i_slint_core::model::*;
307    /// # use std::rc::Rc;
308    /// let model: FilterModel<ModelRc<i32>, Box<dyn Fn(&i32) -> bool>>
309    ///     = VecModel::from_slice(&[3i32, 2, 1])
310    ///       .filter(Box::new(|v: &i32| *v >= 2) as Box<dyn Fn(&i32) -> bool>);
311    /// let model_rc = ModelRc::new(model);
312    /// assert!(model_rc.as_any()
313    ///     .downcast_ref::<FilterModel<ModelRc<i32>, Box<dyn Fn(&i32) -> bool>>>()
314    ///     .is_some());
315    /// ```
316    fn as_any(&self) -> &dyn core::any::Any {
317        &()
318    }
319}
320
321/// Extension trait with extra methods implemented on types that implement [`Model`]
322pub trait ModelExt: Model {
323    /// Convenience function that calls [`ModelTracker::track_row_data_changes`]
324    /// before returning [`Model::row_data`].
325    ///
326    /// Calling [`row_data(row)`](Model::row_data) does not register the row as a dependency when calling it while
327    /// evaluating a property binding. This function calls [`track_row_data_changes(row)`](ModelTracker::track_row_data_changes)
328    /// on the [`self.model_tracker()`](Model::model_tracker) to enable tracking.
329    fn row_data_tracked(&self, row: usize) -> Option<Self::Data> {
330        self.model_tracker().track_row_data_changes(row);
331        self.row_data(row)
332    }
333
334    /// Returns a new Model where all elements are mapped by the function `map_function`.
335    /// This is a shortcut for [`MapModel::new()`].
336    fn map<F, U>(self, map_function: F) -> MapModel<Self, F>
337    where
338        Self: Sized + 'static,
339        F: Fn(Self::Data) -> U + 'static,
340    {
341        MapModel::new(self, map_function)
342    }
343
344    /// Returns a new Model where the elements are filtered by the function `filter_function`.
345    /// This is a shortcut for [`FilterModel::new()`].
346    fn filter<F>(self, filter_function: F) -> FilterModel<Self, F>
347    where
348        Self: Sized + 'static,
349        F: Fn(&Self::Data) -> bool + 'static,
350    {
351        FilterModel::new(self, filter_function)
352    }
353
354    /// Returns a new Model where the elements are sorted ascending.
355    /// This is a shortcut for [`SortModel::new_ascending()`].
356    #[must_use]
357    fn sort(self) -> SortModel<Self, adapters::AscendingSortHelper>
358    where
359        Self: Sized + 'static,
360        Self::Data: core::cmp::Ord,
361    {
362        SortModel::new_ascending(self)
363    }
364
365    /// Returns a new Model where the elements are sorted by the function `sort_function`.
366    /// This is a shortcut for [`SortModel::new()`].
367    fn sort_by<F>(self, sort_function: F) -> SortModel<Self, F>
368    where
369        Self: Sized + 'static,
370        F: FnMut(&Self::Data, &Self::Data) -> core::cmp::Ordering + 'static,
371    {
372        SortModel::new(self, sort_function)
373    }
374
375    /// Returns a new Model where the elements are reversed.
376    /// This is a shortcut for [`ReverseModel::new()`].
377    fn reverse(self) -> ReverseModel<Self>
378    where
379        Self: Sized + 'static,
380    {
381        ReverseModel::new(self)
382    }
383}
384
385impl<T: Model> ModelExt for T {}
386
387/// Reports the error of a rejected model modification as a log message.
388///
389/// Called with the result of the `.slint` array functions by the generated code
390/// and the interpreter, which otherwise ignore the error.
391#[doc(hidden)]
392pub fn report_model_error(
393    function: &str,
394    location: Option<crate::debug_log::LogMessageLocation<'_>>,
395    result: Result<(), ModelError>,
396) {
397    if let Err(err) = result {
398        crate::debug_log::log_message(crate::debug_log::LogMessage::new(
399            crate::debug_log::LogMessageSource::SlintCode,
400            location,
401            format_args!("array.{function}(): {err}"),
402        ));
403    }
404}
405
406pub fn model_any<T>(model: &dyn Model<Data = T>, mut predicate: impl FnMut(T) -> bool) -> bool {
407    let row_count = model.row_count();
408    model.model_tracker().track_any_change(row_count, crate::InternalToken);
409    (0..row_count).any(|index| model.row_data(index).is_some_and(&mut predicate))
410}
411
412pub fn model_all<T>(model: &dyn Model<Data = T>, mut predicate: impl FnMut(T) -> bool) -> bool {
413    let row_count = model.row_count();
414    model.model_tracker().track_any_change(row_count, crate::InternalToken);
415    // `is_none_or`, not `is_some_and`: a row without data is skipped, as it is by
416    // model_any and model_find_index, rather than failing the whole model.
417    (0..row_count).all(|index| model.row_data(index).is_none_or(&mut predicate))
418}
419
420/// Returns the index of the first row for which `predicate` returns `true`, or `-1`
421/// if no row matches.
422pub fn model_find_index<T>(
423    model: &dyn Model<Data = T>,
424    mut predicate: impl FnMut(T) -> bool,
425) -> i32 {
426    let row_count = model.row_count();
427    model.model_tracker().track_any_change(row_count, crate::InternalToken);
428    (0..row_count)
429        .find(|index| model.row_data(*index).is_some_and(&mut predicate))
430        .map_or(-1, |index| index as i32)
431}
432
433/// An iterator over the elements of a model.
434/// This struct is created by the [`Model::iter()`] trait function.
435pub struct ModelIterator<'a, T> {
436    model: &'a dyn Model<Data = T>,
437    row: usize,
438}
439
440impl<'a, T> ModelIterator<'a, T> {
441    /// Creates a new model iterator for a model reference.
442    /// This is the same as calling [`model.iter()`](Model::iter)
443    pub fn new(model: &'a dyn Model<Data = T>) -> Self {
444        Self { model, row: 0 }
445    }
446}
447
448impl<T> Iterator for ModelIterator<'_, T> {
449    type Item = T;
450
451    fn next(&mut self) -> Option<Self::Item> {
452        if self.row >= self.model.row_count() {
453            return None;
454        }
455        let row = self.row;
456        self.row += 1;
457        self.model.row_data(row)
458    }
459
460    fn size_hint(&self) -> (usize, Option<usize>) {
461        let len = self.model.row_count();
462        (len, Some(len))
463    }
464
465    fn nth(&mut self, n: usize) -> Option<Self::Item> {
466        self.row = self.row.checked_add(n)?;
467        self.next()
468    }
469}
470
471impl<T> ExactSizeIterator for ModelIterator<'_, T> {}
472
473impl<M: Model> Model for Rc<M> {
474    type Data = M::Data;
475
476    fn row_count(&self) -> usize {
477        (**self).row_count()
478    }
479
480    fn row_data(&self, row: usize) -> Option<Self::Data> {
481        (**self).row_data(row)
482    }
483
484    fn model_tracker(&self) -> &dyn ModelTracker {
485        (**self).model_tracker()
486    }
487
488    fn as_any(&self) -> &dyn core::any::Any {
489        (**self).as_any()
490    }
491    fn set_row_data(&self, row: usize, data: Self::Data) {
492        (**self).set_row_data(row, data)
493    }
494    fn push_row(&self, data: Self::Data) -> Result<(), ModelError> {
495        (**self).push_row(data)
496    }
497    fn remove_row(&self, row: usize) -> Result<(), ModelError> {
498        (**self).remove_row(row)
499    }
500    fn insert_row(&self, row: usize, data: Self::Data) -> Result<(), ModelError> {
501        (**self).insert_row(row, data)
502    }
503}
504
505/// A [`Model`] backed by a `Vec<T>`, using interior mutability.
506pub struct VecModel<T> {
507    array: RefCell<Vec<T>>,
508    notify: ModelNotify,
509}
510
511impl<T> Default for VecModel<T> {
512    fn default() -> Self {
513        Self { array: Default::default(), notify: Default::default() }
514    }
515}
516
517impl<T: 'static> VecModel<T> {
518    /// Allocate a new model from a slice
519    pub fn from_slice(slice: &[T]) -> ModelRc<T>
520    where
521        T: Clone,
522    {
523        ModelRc::new(Self::from(slice.to_vec()))
524    }
525
526    /// Add a row at the end of the model
527    pub fn push(&self, value: T) {
528        self.array.borrow_mut().push(value);
529        self.notify.row_added(self.array.borrow().len() - 1, 1)
530    }
531
532    /// Inserts a row at position index. All rows after that are shifted.
533    /// This function panics if index is > row_count().
534    pub fn insert(&self, index: usize, value: T) {
535        self.array.borrow_mut().insert(index, value);
536        self.notify.row_added(index, 1)
537    }
538
539    /// Remove the row at the given index from the model
540    ///
541    /// Returns the removed row
542    pub fn remove(&self, index: usize) -> T {
543        let r = self.array.borrow_mut().remove(index);
544        self.notify.row_removed(index, 1);
545        r
546    }
547
548    /// Replace inner Vec with new data
549    pub fn set_vec(&self, new: impl Into<Vec<T>>) {
550        *self.array.borrow_mut() = new.into();
551        self.notify.reset();
552    }
553
554    /// Extend the model with the content of the iterator
555    ///
556    /// Similar to [`Vec::extend`]
557    pub fn extend<I: IntoIterator<Item = T>>(&self, iter: I) {
558        let mut array = self.array.borrow_mut();
559        let old_idx = array.len();
560        array.extend(iter);
561        let count = array.len() - old_idx;
562        drop(array);
563        self.notify.row_added(old_idx, count);
564    }
565
566    /// Clears the model, removing all values
567    ///
568    /// Similar to [`Vec::clear`]
569    pub fn clear(&self) {
570        self.array.borrow_mut().clear();
571        self.notify.reset();
572    }
573
574    /// Swaps two elements in the model.
575    pub fn swap(&self, a: usize, b: usize) {
576        if a == b {
577            return;
578        }
579
580        self.array.borrow_mut().swap(a, b);
581        self.notify.row_changed(a);
582        self.notify.row_changed(b);
583    }
584}
585
586impl<T: Clone + 'static> VecModel<T> {
587    /// Appends all the elements in the slice to the model
588    ///
589    /// Similar to [`Vec::extend_from_slice`]
590    pub fn extend_from_slice(&self, src: &[T]) {
591        let mut array = self.array.borrow_mut();
592        let old_idx = array.len();
593
594        array.extend_from_slice(src);
595        drop(array);
596        self.notify.row_added(old_idx, src.len());
597    }
598}
599
600impl<T> From<Vec<T>> for VecModel<T> {
601    fn from(array: Vec<T>) -> Self {
602        VecModel { array: RefCell::new(array), notify: Default::default() }
603    }
604}
605
606impl<T> FromIterator<T> for VecModel<T> {
607    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
608        VecModel::from(Vec::from_iter(iter))
609    }
610}
611
612impl<T: Clone + 'static> Model for VecModel<T> {
613    type Data = T;
614
615    fn row_count(&self) -> usize {
616        self.array.borrow().len()
617    }
618
619    fn row_data(&self, row: usize) -> Option<Self::Data> {
620        self.array.borrow().get(row).cloned()
621    }
622
623    fn set_row_data(&self, row: usize, data: Self::Data) {
624        if row < self.row_count() {
625            self.array.borrow_mut()[row] = data;
626            self.notify.row_changed(row);
627        }
628    }
629
630    fn remove_row(&self, row: usize) -> Result<(), ModelError> {
631        if row >= self.row_count() {
632            return Err(ModelError::out_of_bounds(self.row_count()));
633        }
634        self.remove(row);
635        Ok(())
636    }
637
638    fn insert_row(&self, row: usize, data: Self::Data) -> Result<(), ModelError> {
639        if row > self.row_count() {
640            return Err(ModelError::out_of_bounds(self.row_count()));
641        }
642        self.insert(row, data);
643        Ok(())
644    }
645
646    fn model_tracker(&self) -> &dyn ModelTracker {
647        &self.notify
648    }
649
650    fn as_any(&self) -> &dyn core::any::Any {
651        self
652    }
653}
654
655/// A model backed by a `SharedVector<T>`
656#[derive(Default)]
657pub struct SharedVectorModel<T> {
658    array: RefCell<SharedVector<T>>,
659    notify: ModelNotify,
660}
661
662impl<T: Clone + 'static> SharedVectorModel<T> {
663    /// Add a row at the end of the model
664    pub fn push(&self, value: T) {
665        self.array.borrow_mut().push(value);
666        self.notify.row_added(self.array.borrow().len() - 1, 1)
667    }
668}
669
670impl<T> SharedVectorModel<T> {
671    /// Returns a clone of the model's backing shared vector.
672    pub fn shared_vector(&self) -> SharedVector<T> {
673        self.array.borrow_mut().clone()
674    }
675}
676
677impl<T> From<SharedVector<T>> for SharedVectorModel<T> {
678    fn from(array: SharedVector<T>) -> Self {
679        SharedVectorModel { array: RefCell::new(array), notify: Default::default() }
680    }
681}
682
683impl<T: Clone + 'static> Model for SharedVectorModel<T> {
684    type Data = T;
685
686    fn row_count(&self) -> usize {
687        self.array.borrow().len()
688    }
689
690    fn row_data(&self, row: usize) -> Option<Self::Data> {
691        self.array.borrow().get(row).cloned()
692    }
693
694    fn set_row_data(&self, row: usize, data: Self::Data) {
695        self.array.borrow_mut().make_mut_slice()[row] = data;
696        self.notify.row_changed(row);
697    }
698
699    fn remove_row(&self, row: usize) -> Result<(), ModelError> {
700        if row >= self.row_count() {
701            return Err(ModelError::out_of_bounds(self.row_count()));
702        }
703        self.array.borrow_mut().remove(row);
704        self.notify.row_removed(row, 1);
705        Ok(())
706    }
707
708    fn insert_row(&self, row: usize, data: Self::Data) -> Result<(), ModelError> {
709        if row > self.row_count() {
710            return Err(ModelError::out_of_bounds(self.row_count()));
711        }
712        self.array.borrow_mut().insert(row, data);
713        self.notify.row_added(row, 1);
714        Ok(())
715    }
716
717    fn model_tracker(&self) -> &dyn ModelTracker {
718        &self.notify
719    }
720
721    fn as_any(&self) -> &dyn core::any::Any {
722        self
723    }
724}
725
726impl Model for usize {
727    type Data = i32;
728
729    fn row_count(&self) -> usize {
730        *self
731    }
732
733    fn row_data(&self, row: usize) -> Option<Self::Data> {
734        (row < self.row_count()).then_some(row as i32)
735    }
736
737    fn as_any(&self) -> &dyn core::any::Any {
738        self
739    }
740
741    fn model_tracker(&self) -> &dyn ModelTracker {
742        &()
743    }
744}
745
746impl Model for bool {
747    type Data = ();
748
749    fn row_count(&self) -> usize {
750        if *self { 1 } else { 0 }
751    }
752
753    fn row_data(&self, row: usize) -> Option<Self::Data> {
754        (row < self.row_count()).then_some(())
755    }
756
757    fn as_any(&self) -> &dyn core::any::Any {
758        self
759    }
760
761    fn model_tracker(&self) -> &dyn ModelTracker {
762        &()
763    }
764}
765
766/// ModelRc is a type wrapper for a reference counted implementation of the [`Model`] trait.
767///
768/// Models are used to represent sequences of the same data type. In `.slint` code those
769/// are represented using the `[T]` array syntax and typically used in `for` expressions,
770/// array properties, and array struct fields.
771///
772/// For example, a `property <[string]> foo` will be of type `ModelRc<SharedString>`
773/// and, behind the scenes, wraps a `Rc<dyn Model<Data = SharedString>>.`
774///
775/// An array struct field will also be of type `ModelRc`:
776///
777/// ```slint,no-preview
778/// export struct AddressBook {
779///     names: [string]
780/// }
781/// ```
782///
783/// When accessing `AddressBook` from Rust, the `names` field will be of type `ModelRc<SharedString>`.
784///
785/// There are several ways of constructing a ModelRc in Rust:
786///
787/// * An empty ModelRc can be constructed with [`ModelRc::default()`].
788/// * A `ModelRc` can be constructed from a slice or an array using the [`From`] trait.
789///   This allocates a [`VecModel`].
790/// * Use [`ModelRc::new()`] to construct a `ModelRc` from a type that implements the
791///   [`Model`] trait, such as [`VecModel`] or your own implementation.
792/// * If you have your model already in an `Rc`, then you can use the [`From`] trait
793///   to convert from `Rc<dyn Model<Data = T>>` to `ModelRc`.
794///
795/// ## Example
796///
797/// ```rust
798/// # i_slint_backend_testing::init_no_event_loop();
799/// use slint::{slint, SharedString, ModelRc, Model, VecModel};
800/// use std::rc::Rc;
801/// slint!{
802///     import { Button } from "std-widgets.slint";
803///     export component Example {
804///         callback add_item <=> btn.clicked;
805///         in property <[string]> the_model;
806///         HorizontalLayout {
807///             for it in the_model : Text { text: it; }
808///             btn := Button { text: "Add"; }
809///         }
810///     }
811/// }
812/// let ui = Example::new().unwrap();
813/// // Create a VecModel and put it in an Rc.
814/// let the_model : Rc<VecModel<SharedString>> =
815///         Rc::new(VecModel::from(vec!["Hello".into(), "World".into()]));
816/// // Convert it to a ModelRc.
817/// let the_model_rc = ModelRc::from(the_model.clone());
818/// // Pass the model to the ui: The generated set_the_model setter from the
819/// // the_model property takes a ModelRc.
820/// ui.set_the_model(the_model_rc);
821///
822/// // We have kept a strong reference to the_model, to modify it in a callback.
823/// ui.on_add_item(move || {
824///     // Use VecModel API: VecModel uses the Model notification mechanism to let Slint
825///     // know it needs to refresh the UI.
826///     the_model.push("SomeValue".into());
827/// });
828///
829/// // Alternative: we can re-use a getter.
830/// let ui_weak = ui.as_weak();
831/// ui.on_add_item(move || {
832///     let ui = ui_weak.unwrap();
833///     let the_model_rc = ui.get_the_model();
834///     let the_model = the_model_rc.as_any().downcast_ref::<VecModel<SharedString>>()
835///         .expect("We know we set a VecModel earlier");
836///     the_model.push("An Item".into());
837/// });
838/// ```
839///
840/// ### Updating the Model from a Thread
841///
842/// `ModelRc` is not `Send` and can only be used in the main thread.
843/// 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
844/// using [`invoke_from_event_loop`](crate::api::invoke_from_event_loop) or
845/// [`Weak::upgrade_in_event_loop`](crate::api::Weak::upgrade_in_event_loop).
846///
847/// ```rust
848/// # i_slint_backend_testing::init_integration_test_with_mock_time();
849/// use slint::Model;
850/// slint::slint!{
851///     export component TestCase inherits Window {
852///         in property <[string]> the_model;
853///         //...
854///     }
855/// }
856/// let ui = TestCase::new().unwrap();
857/// // set a model (a VecModel)
858/// let model = std::rc::Rc::new(slint::VecModel::<slint::SharedString>::default());
859/// ui.set_the_model(model.clone().into());
860///
861/// // do some work in a thread
862/// let ui_weak = ui.as_weak();
863/// let thread = std::thread::spawn(move || {
864///     // do some work
865///     let new_strings = vec!["foo".into(), "bar".into()];
866///     // send the data back to the main thread
867///     ui_weak.upgrade_in_event_loop(move |ui| {
868///         let model = ui.get_the_model();
869///         let model = model.as_any().downcast_ref::<slint::VecModel<slint::SharedString>>()
870///             .expect("We know we set a VecModel earlier");
871///         model.set_vec(new_strings);
872/// #       slint::quit_event_loop().unwrap();
873///     });
874/// });
875/// ui.run().unwrap();
876/// ```
877pub struct ModelRc<T>(Option<Rc<dyn Model<Data = T>>>);
878
879impl<T> core::fmt::Debug for ModelRc<T> {
880    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
881        write!(f, "ModelRc(dyn Model)")
882    }
883}
884
885impl<T> Clone for ModelRc<T> {
886    fn clone(&self) -> Self {
887        Self(self.0.clone())
888    }
889}
890
891impl<T> Default for ModelRc<T> {
892    /// Construct an empty model
893    fn default() -> Self {
894        Self(None)
895    }
896}
897
898impl<T> core::cmp::PartialEq for ModelRc<T> {
899    fn eq(&self, other: &Self) -> bool {
900        match (&self.0, &other.0) {
901            (None, None) => true,
902            (Some(a), Some(b)) => core::ptr::eq(
903                (&**a) as *const dyn Model<Data = T> as *const u8,
904                (&**b) as *const dyn Model<Data = T> as *const u8,
905            ),
906            _ => false,
907        }
908    }
909}
910
911#[cfg(feature = "serde")]
912use serde::ser::SerializeSeq;
913#[cfg(feature = "serde")]
914impl<T> serde::Serialize for ModelRc<T>
915where
916    T: serde::Serialize,
917{
918    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
919    where
920        S: serde::Serializer,
921    {
922        let mut seq = serializer.serialize_seq(Some(self.row_count()))?;
923        for item in self.iter() {
924            seq.serialize_element(&item)?;
925        }
926        seq.end()
927    }
928}
929
930#[cfg(feature = "serde")]
931impl<'de, T> serde::Deserialize<'de> for ModelRc<T>
932where
933    T: serde::Deserialize<'de> + Clone + 'static,
934{
935    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
936    where
937        D: serde::Deserializer<'de>,
938    {
939        let vec = Vec::<T>::deserialize(deserializer)?;
940        if vec.is_empty() {
941            return Ok(ModelRc::default());
942        }
943        Ok(ModelRc::new(VecModel::from(vec)))
944    }
945}
946
947impl<T> ModelRc<T> {
948    pub fn new(model: impl Model<Data = T> + 'static) -> Self {
949        Self(Some(Rc::new(model)))
950    }
951}
952
953impl<T, M: Model<Data = T> + 'static> From<Rc<M>> for ModelRc<T> {
954    fn from(model: Rc<M>) -> Self {
955        Self(Some(model))
956    }
957}
958
959impl<T> From<Rc<dyn Model<Data = T> + 'static>> for ModelRc<T> {
960    fn from(model: Rc<dyn Model<Data = T> + 'static>) -> Self {
961        Self(Some(model))
962    }
963}
964
965impl<T: Clone + 'static> From<&[T]> for ModelRc<T> {
966    fn from(slice: &[T]) -> Self {
967        VecModel::from_slice(slice)
968    }
969}
970
971impl<T: Clone + 'static, const N: usize> From<[T; N]> for ModelRc<T> {
972    fn from(array: [T; N]) -> Self {
973        VecModel::from_slice(&array)
974    }
975}
976
977impl<T> TryInto<Rc<dyn Model<Data = T>>> for ModelRc<T> {
978    type Error = ();
979
980    fn try_into(self) -> Result<Rc<dyn Model<Data = T>>, Self::Error> {
981        self.0.ok_or(())
982    }
983}
984
985impl<T> Model for ModelRc<T> {
986    type Data = T;
987
988    fn row_count(&self) -> usize {
989        self.0.as_ref().map_or(0, |model| model.row_count())
990    }
991
992    fn row_data(&self, row: usize) -> Option<Self::Data> {
993        self.0.as_ref().and_then(|model| model.row_data(row))
994    }
995
996    fn set_row_data(&self, row: usize, data: Self::Data) {
997        if let Some(model) = self.0.as_ref() {
998            model.set_row_data(row, data);
999        }
1000    }
1001
1002    fn push_row(&self, data: Self::Data) -> Result<(), ModelError> {
1003        match self.0.as_ref() {
1004            Some(model) => model.push_row(data),
1005            None => Err(ModelError::unsupported(self)),
1006        }
1007    }
1008
1009    fn remove_row(&self, row: usize) -> Result<(), ModelError> {
1010        match self.0.as_ref() {
1011            Some(model) => model.remove_row(row),
1012            None => Err(ModelError::unsupported(self)),
1013        }
1014    }
1015
1016    fn insert_row(&self, row: usize, data: Self::Data) -> Result<(), ModelError> {
1017        match self.0.as_ref() {
1018            Some(model) => model.insert_row(row, data),
1019            None => Err(ModelError::unsupported(self)),
1020        }
1021    }
1022
1023    fn model_tracker(&self) -> &dyn ModelTracker {
1024        self.0.as_ref().map_or(&(), |model| model.model_tracker())
1025    }
1026
1027    fn as_any(&self) -> &dyn core::any::Any {
1028        self.0.as_ref().map_or(&(), |model| model.as_any())
1029    }
1030}
1031
1032impl From<SharedString> for StandardListViewItem {
1033    fn from(value: SharedString) -> Self {
1034        StandardListViewItem { text: value }
1035    }
1036}
1037
1038impl From<&str> for StandardListViewItem {
1039    fn from(value: &str) -> Self {
1040        StandardListViewItem { text: value.into() }
1041    }
1042}
1043
1044#[cfg(test)]
1045mod tests {
1046    use super::*;
1047    use std::vec;
1048
1049    #[cfg(feature = "serde")]
1050    #[test]
1051    fn test_serialize_deserialize_modelrc() {
1052        let model_rc = ModelRc::new(VecModel::from(vec![1, 2, 3]));
1053        let serialized = serde_json::to_string(&model_rc).unwrap();
1054        let deserialized: ModelRc<i32> = serde_json::from_str(&serialized).unwrap();
1055        assert_eq!(deserialized.row_count(), 3);
1056        assert_eq!(deserialized.row_data(0), Some(1));
1057        assert_eq!(deserialized.row_data(1), Some(2));
1058        assert_eq!(deserialized.row_data(2), Some(3));
1059    }
1060
1061    #[test]
1062    fn test_tracking_model_handle() {
1063        let model: Rc<VecModel<u8>> = Rc::new(Default::default());
1064        let handle = ModelRc::from(model.clone() as Rc<dyn Model<Data = u8>>);
1065        let tracker = Box::pin(<crate::properties::PropertyTracker>::default());
1066        assert_eq!(
1067            tracker.as_ref().evaluate(|| {
1068                handle.model_tracker().track_row_count_changes();
1069                handle.row_count()
1070            }),
1071            0
1072        );
1073        assert!(!tracker.is_dirty());
1074        model.push(42);
1075        model.push(100);
1076        assert!(tracker.is_dirty());
1077        assert_eq!(
1078            tracker.as_ref().evaluate(|| {
1079                handle.model_tracker().track_row_count_changes();
1080                handle.row_count()
1081            }),
1082            2
1083        );
1084        assert!(!tracker.is_dirty());
1085        model.set_row_data(0, 41);
1086        assert!(!tracker.is_dirty());
1087        model.remove(0);
1088        assert!(tracker.is_dirty());
1089        assert_eq!(
1090            tracker.as_ref().evaluate(|| {
1091                handle.model_tracker().track_row_count_changes();
1092                handle.row_count()
1093            }),
1094            1
1095        );
1096        assert!(!tracker.is_dirty());
1097        model.set_vec(vec![1, 2, 3]);
1098        assert!(tracker.is_dirty());
1099    }
1100
1101    #[test]
1102    fn test_shared_vector_model_bounds() {
1103        let model: Rc<SharedVectorModel<i32>> =
1104            Rc::new(SharedVectorModel::from(SharedVector::from_slice(&[1, 2, 3])));
1105        let handle = ModelRc::from(model.clone());
1106        let tracker = Box::pin(<crate::properties::PropertyTracker>::default());
1107        let count = || {
1108            tracker.as_ref().evaluate(|| {
1109                handle.model_tracker().track_row_count_changes();
1110                handle.row_count()
1111            })
1112        };
1113        assert_eq!(count(), 3);
1114        assert!(!tracker.is_dirty());
1115
1116        // Out-of-range operations return an error, do nothing, and must not notify the views.
1117        assert!(model.remove_row(3).is_err());
1118        assert!(model.insert_row(4, 42).is_err());
1119        assert!(!tracker.is_dirty());
1120        assert_eq!(model.row_count(), 3);
1121        assert_eq!(model.row_data(2), Some(3));
1122
1123        // In-range operations change the data and notify.
1124        model.insert_row(3, 4).unwrap();
1125        assert!(tracker.is_dirty());
1126        assert_eq!(count(), 4);
1127        model.remove_row(0).unwrap();
1128        assert_eq!(model.row_count(), 3);
1129        assert_eq!(model.row_data(0), Some(2));
1130    }
1131
1132    #[test]
1133    fn test_data_tracking() {
1134        let model: Rc<VecModel<u8>> = Rc::new(VecModel::from(vec![0, 1, 2, 3, 4]));
1135        let handle = ModelRc::from(model.clone());
1136        let tracker = Box::pin(<crate::properties::PropertyTracker>::default());
1137        assert_eq!(
1138            tracker.as_ref().evaluate(|| {
1139                handle.model_tracker().track_row_data_changes(1);
1140                handle.row_data(1).unwrap()
1141            }),
1142            1
1143        );
1144        assert!(!tracker.is_dirty());
1145
1146        model.set_row_data(2, 42);
1147        assert!(!tracker.is_dirty());
1148        model.set_row_data(1, 100);
1149        assert!(tracker.is_dirty());
1150
1151        assert_eq!(
1152            tracker.as_ref().evaluate(|| {
1153                handle.model_tracker().track_row_data_changes(1);
1154                handle.row_data(1).unwrap()
1155            }),
1156            100
1157        );
1158        assert!(!tracker.is_dirty());
1159
1160        // Any changes to rows (even if after tracked rows) for now also marks watched rows as dirty, to
1161        // keep the logic simple.
1162        model.push(200);
1163        assert!(tracker.is_dirty());
1164
1165        assert_eq!(tracker.as_ref().evaluate(|| { handle.row_data_tracked(1).unwrap() }), 100);
1166        assert!(!tracker.is_dirty());
1167
1168        model.insert(0, 255);
1169        assert!(tracker.is_dirty());
1170
1171        model.set_vec(Vec::new());
1172        assert!(tracker.is_dirty());
1173    }
1174
1175    #[test]
1176    fn test_data_tracking_outside_a_binding() {
1177        let model: Rc<VecModel<u8>> = Rc::new(VecModel::from(vec![0, 1, 2, 3, 4]));
1178        let handle = ModelRc::from(model.clone());
1179        let tracker = Box::pin(<crate::properties::PropertyTracker>::default());
1180        assert_eq!(
1181            tracker.as_ref().evaluate(|| {
1182                handle.model_tracker().track_row_data_changes(1);
1183                handle.row_data(1).unwrap()
1184            }),
1185            1
1186        );
1187        assert!(!tracker.is_dirty());
1188
1189        // Tracking a row while no binding is being evaluated registers no dependency, so it
1190        // must not make later changes to that row dirty bindings that never asked for it.
1191        handle.model_tracker().track_row_data_changes(0);
1192        model.set_row_data(0, 100);
1193        assert!(!tracker.is_dirty());
1194
1195        // The row the tracker did ask for still works.
1196        model.set_row_data(1, 100);
1197        assert!(tracker.is_dirty());
1198    }
1199
1200    #[test]
1201    fn test_any_change_tracking() {
1202        let model: Rc<VecModel<u8>> = Rc::new(VecModel::from(vec![0, 1, 2, 3, 4]));
1203        let handle = ModelRc::from(model.clone());
1204        let tracker = Box::pin(<crate::properties::PropertyTracker>::default());
1205        let find_two = || tracker.as_ref().evaluate(|| model_find_index(&handle, |x| x == 2));
1206        assert_eq!(find_two(), 2);
1207        assert!(!tracker.is_dirty());
1208
1209        // Any row change dirties the binding, including rows past the match,
1210        // as track_any_change() tracks all rows regardless of short-circuiting.
1211        model.set_row_data(4, 42);
1212        assert!(tracker.is_dirty());
1213        assert_eq!(find_two(), 2);
1214        assert!(!tracker.is_dirty());
1215
1216        model.set_row_data(2, 22);
1217        assert!(tracker.is_dirty());
1218        assert_eq!(find_two(), -1);
1219        assert!(!tracker.is_dirty());
1220
1221        model.push(2);
1222        assert!(tracker.is_dirty());
1223        assert_eq!(find_two(), 5);
1224        assert!(!tracker.is_dirty());
1225
1226        model.remove(0);
1227        assert!(tracker.is_dirty());
1228        assert_eq!(find_two(), 4);
1229        assert!(!tracker.is_dirty());
1230
1231        // A row change right after add/remove cleared the tracking state still
1232        // dirties the binding, because the re-evaluation re-tracked the model.
1233        model.set_row_data(0, 7);
1234        assert!(tracker.is_dirty());
1235        assert_eq!(find_two(), 4);
1236        assert!(!tracker.is_dirty());
1237
1238        model.set_vec(Vec::new());
1239        assert!(tracker.is_dirty());
1240        assert_eq!(find_two(), -1);
1241        assert!(!tracker.is_dirty());
1242    }
1243
1244    #[test]
1245    fn test_track_any_change_default_impl() {
1246        // A tracker that doesn't override track_any_change(), to exercise
1247        // ModelTracker's default implementation, which must be equivalent to
1248        // calling track_row_count_changes() and then track_row_data_changes()
1249        // for every row.
1250        #[derive(Default)]
1251        struct RecordingTracker {
1252            row_count_calls: Cell<usize>,
1253            row_data_calls: RefCell<Vec<usize>>,
1254        }
1255
1256        impl ModelTracker for RecordingTracker {
1257            fn attach_peer(&self, _peer: ModelPeer) {}
1258            fn track_row_count_changes(&self) {
1259                self.row_count_calls.set(self.row_count_calls.get() + 1);
1260            }
1261            fn track_row_data_changes(&self, row: usize) {
1262                self.row_data_calls.borrow_mut().push(row);
1263            }
1264        }
1265
1266        let tracker = RecordingTracker::default();
1267        tracker.track_any_change(3, crate::InternalToken);
1268        assert_eq!(tracker.row_count_calls.get(), 1);
1269        assert_eq!(*tracker.row_data_calls.borrow(), vec![0, 1, 2]);
1270
1271        tracker.track_any_change(0, crate::InternalToken);
1272        assert_eq!(tracker.row_count_calls.get(), 2);
1273        assert_eq!(*tracker.row_data_calls.borrow(), vec![0, 1, 2]);
1274    }
1275
1276    /// A model whose middle row has no data, to pin down how the array predicates
1277    /// treat a row that is in range but unreadable.
1278    struct AbsentRowModel;
1279
1280    impl Model for AbsentRowModel {
1281        type Data = i32;
1282        fn row_count(&self) -> usize {
1283            3
1284        }
1285        fn row_data(&self, row: usize) -> Option<i32> {
1286            match row {
1287                0 => Some(1),
1288                1 => None,
1289                _ => Some(3),
1290            }
1291        }
1292        fn model_tracker(&self) -> &dyn ModelTracker {
1293            &()
1294        }
1295    }
1296
1297    #[test]
1298    fn test_predicates_skip_absent_rows() {
1299        // All three predicates skip the absent row, rather than failing the whole
1300        // model or feeding the predicate a default value in its place.
1301        assert!(model_all(&AbsentRowModel, |x| x > 0));
1302        assert!(!model_any(&AbsentRowModel, |x| x == 0));
1303        assert_eq!(model_find_index(&AbsentRowModel, |x| x == 3), 2);
1304    }
1305
1306    #[test]
1307    fn test_any_change_subsumes_row_tracking() {
1308        let model: Rc<VecModel<u8>> = Rc::new(VecModel::from(vec![0, 1, 2, 3, 4]));
1309        let handle = ModelRc::from(model.clone());
1310
1311        // Track the whole model, so that every row is now implicitly tracked.
1312        let any_tracker = Box::pin(<crate::properties::PropertyTracker>::default());
1313        any_tracker.as_ref().evaluate(|| model_find_index(&handle, |x| x == 2));
1314        assert!(!any_tracker.is_dirty());
1315
1316        // track_row_data_changes() no longer records the row individually while that
1317        // is the case, but a binding tracking a single row must still be notified.
1318        let row_tracker = Box::pin(<crate::properties::PropertyTracker>::default());
1319        row_tracker.as_ref().evaluate(|| handle.model_tracker().track_row_data_changes(0));
1320        assert!(!row_tracker.is_dirty());
1321
1322        model.set_row_data(0, 9);
1323        assert!(row_tracker.is_dirty());
1324        assert!(any_tracker.is_dirty());
1325    }
1326
1327    #[derive(Default)]
1328    struct TestView {
1329        // Track the parameters reported by the model (row counts, indices, etc.).
1330        // The last field in the tuple is the row size the model reports at the time
1331        // of callback
1332        changed_rows: RefCell<Vec<(usize, usize)>>,
1333        added_rows: RefCell<Vec<(usize, usize, usize)>>,
1334        removed_rows: RefCell<Vec<(usize, usize, usize)>>,
1335        reset: RefCell<usize>,
1336        model: RefCell<Option<std::rc::Weak<dyn Model<Data = i32>>>>,
1337    }
1338    impl TestView {
1339        fn clear(&self) {
1340            self.changed_rows.borrow_mut().clear();
1341            self.added_rows.borrow_mut().clear();
1342            self.removed_rows.borrow_mut().clear();
1343            *self.reset.borrow_mut() = 0;
1344        }
1345        fn row_count(&self) -> usize {
1346            self.model
1347                .borrow()
1348                .as_ref()
1349                .and_then(|model| model.upgrade())
1350                .map_or(0, |model| model.row_count())
1351        }
1352    }
1353    impl ModelChangeListener for TestView {
1354        fn row_changed(self: Pin<&Self>, row: usize) {
1355            self.changed_rows.borrow_mut().push((row, self.row_count()));
1356        }
1357
1358        fn row_added(self: Pin<&Self>, index: usize, count: usize) {
1359            self.added_rows.borrow_mut().push((index, count, self.row_count()));
1360        }
1361
1362        fn row_removed(self: Pin<&Self>, index: usize, count: usize) {
1363            self.removed_rows.borrow_mut().push((index, count, self.row_count()));
1364        }
1365        fn reset(self: Pin<&Self>) {
1366            *self.reset.borrow_mut() += 1;
1367        }
1368    }
1369
1370    #[test]
1371    fn test_vecmodel_set_vec() {
1372        let view = Box::pin(ModelChangeListenerContainer::<TestView>::default());
1373
1374        let model = Rc::new(VecModel::from(vec![1i32, 2, 3, 4]));
1375        model.model_tracker().attach_peer(Pin::as_ref(&view).model_peer());
1376        *view.model.borrow_mut() =
1377            Some(std::rc::Rc::downgrade(&(model.clone() as Rc<dyn Model<Data = i32>>)));
1378
1379        model.push(5);
1380        assert!(view.changed_rows.borrow().is_empty());
1381        assert_eq!(&*view.added_rows.borrow(), &[(4, 1, 5)]);
1382        assert!(view.removed_rows.borrow().is_empty());
1383        assert_eq!(*view.reset.borrow(), 0);
1384        view.clear();
1385
1386        model.set_vec(vec![6, 7, 8]);
1387        assert!(view.changed_rows.borrow().is_empty());
1388        assert!(view.added_rows.borrow().is_empty());
1389        assert!(view.removed_rows.borrow().is_empty());
1390        assert_eq!(*view.reset.borrow(), 1);
1391        view.clear();
1392
1393        model.extend_from_slice(&[9, 10, 11]);
1394        assert!(view.changed_rows.borrow().is_empty());
1395        assert_eq!(&*view.added_rows.borrow(), &[(3, 3, 6)]);
1396        assert!(view.removed_rows.borrow().is_empty());
1397        assert_eq!(*view.reset.borrow(), 0);
1398        view.clear();
1399
1400        model.extend([12, 13]);
1401        assert!(view.changed_rows.borrow().is_empty());
1402        assert_eq!(&*view.added_rows.borrow(), &[(6, 2, 8)]);
1403        assert!(view.removed_rows.borrow().is_empty());
1404        assert_eq!(*view.reset.borrow(), 0);
1405        view.clear();
1406
1407        assert_eq!(model.iter().collect::<Vec<_>>(), vec![6, 7, 8, 9, 10, 11, 12, 13]);
1408
1409        model.swap(1, 1);
1410        assert!(view.changed_rows.borrow().is_empty());
1411        assert!(view.added_rows.borrow().is_empty());
1412        assert!(view.removed_rows.borrow().is_empty());
1413        assert_eq!(*view.reset.borrow(), 0);
1414        view.clear();
1415
1416        model.swap(1, 2);
1417        assert_eq!(&*view.changed_rows.borrow(), &[(1, 8), (2, 8)]);
1418        assert!(view.added_rows.borrow().is_empty());
1419        assert!(view.removed_rows.borrow().is_empty());
1420        assert_eq!(*view.reset.borrow(), 0);
1421        view.clear();
1422
1423        assert_eq!(model.iter().collect::<Vec<_>>(), vec![6, 8, 7, 9, 10, 11, 12, 13]);
1424    }
1425
1426    #[test]
1427    fn test_vecmodel_clear() {
1428        let view = Box::pin(ModelChangeListenerContainer::<TestView>::default());
1429
1430        let model = Rc::new(VecModel::from(vec![1, 2, 3, 4]));
1431        model.model_tracker().attach_peer(Pin::as_ref(&view).model_peer());
1432        *view.model.borrow_mut() =
1433            Some(std::rc::Rc::downgrade(&(model.clone() as Rc<dyn Model<Data = i32>>)));
1434
1435        model.clear();
1436        assert_eq!(*view.reset.borrow(), 1);
1437        assert_eq!(model.row_count(), 0);
1438    }
1439
1440    #[test]
1441    fn test_vecmodel_swap() {
1442        let view = Box::pin(ModelChangeListenerContainer::<TestView>::default());
1443
1444        let model = Rc::new(VecModel::from(vec![1, 2, 3, 4]));
1445        model.model_tracker().attach_peer(Pin::as_ref(&view).model_peer());
1446        *view.model.borrow_mut() =
1447            Some(std::rc::Rc::downgrade(&(model.clone() as Rc<dyn Model<Data = i32>>)));
1448
1449        model.swap(1, 1);
1450        assert!(view.changed_rows.borrow().is_empty());
1451        assert!(view.added_rows.borrow().is_empty());
1452        assert!(view.removed_rows.borrow().is_empty());
1453        assert_eq!(*view.reset.borrow(), 0);
1454        view.clear();
1455
1456        model.swap(1, 2);
1457        assert_eq!(&*view.changed_rows.borrow(), &[(1, 4), (2, 4)]);
1458        assert!(view.added_rows.borrow().is_empty());
1459        assert!(view.removed_rows.borrow().is_empty());
1460        assert_eq!(*view.reset.borrow(), 0);
1461        view.clear();
1462    }
1463
1464    #[test]
1465    fn modeliter_in_bounds() {
1466        struct TestModel {
1467            length: usize,
1468            max_requested_row: Cell<usize>,
1469            notify: ModelNotify,
1470        }
1471
1472        impl Model for TestModel {
1473            type Data = usize;
1474
1475            fn row_count(&self) -> usize {
1476                self.length
1477            }
1478
1479            fn row_data(&self, row: usize) -> Option<usize> {
1480                self.max_requested_row.set(self.max_requested_row.get().max(row));
1481                (row < self.length).then_some(row)
1482            }
1483
1484            fn model_tracker(&self) -> &dyn ModelTracker {
1485                &self.notify
1486            }
1487        }
1488
1489        let model = Rc::new(TestModel {
1490            length: 10,
1491            max_requested_row: Cell::new(0),
1492            notify: Default::default(),
1493        });
1494
1495        assert_eq!(model.iter().max().unwrap(), 9);
1496        assert_eq!(model.max_requested_row.get(), 9);
1497    }
1498
1499    #[test]
1500    fn vecmodel_doesnt_require_default() {
1501        #[derive(Clone)]
1502        struct MyNoDefaultType {
1503            _foo: bool,
1504        }
1505        let model = VecModel::<MyNoDefaultType>::default();
1506        assert_eq!(model.row_count(), 0);
1507        model.push(MyNoDefaultType { _foo: true });
1508    }
1509}