Skip to main content

i_slint_core/model/
adapters.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//! This module contains adapter models.
5
6use super::*;
7
8#[cfg(test)]
9mod tests_helper {
10    use super::*;
11
12    #[derive(Default)]
13    pub struct TestView {
14        // Track the parameters reported by the model (row counts, indices, etc.).
15        // The last field in the tuple is the row size the model reports at the time
16        // of callback
17        pub changed_rows: RefCell<Vec<usize>>,
18        pub added_rows: RefCell<Vec<(usize, usize)>>,
19        pub removed_rows: RefCell<Vec<(usize, usize)>>,
20        pub reset: RefCell<usize>,
21    }
22
23    impl TestView {
24        pub fn clear(&self) {
25            self.changed_rows.borrow_mut().clear();
26            self.added_rows.borrow_mut().clear();
27            self.removed_rows.borrow_mut().clear();
28        }
29    }
30
31    impl ModelChangeListener for TestView {
32        fn row_changed(self: Pin<&Self>, row: usize) {
33            self.changed_rows.borrow_mut().push(row);
34        }
35
36        fn row_added(self: Pin<&Self>, index: usize, count: usize) {
37            self.added_rows.borrow_mut().push((index, count));
38        }
39
40        fn row_removed(self: Pin<&Self>, index: usize, count: usize) {
41            self.removed_rows.borrow_mut().push((index, count));
42        }
43        fn reset(self: Pin<&Self>) {
44            *self.reset.borrow_mut() += 1;
45        }
46    }
47
48    pub struct ModelChecker<Data: PartialEq + core::fmt::Debug + 'static> {
49        pub model: Rc<dyn Model<Data = Data>>,
50        pub rows_copy: RefCell<Vec<Data>>,
51    }
52
53    impl<Data: PartialEq + core::fmt::Debug + 'static> ModelChangeListener for ModelChecker<Data> {
54        fn row_changed(self: Pin<&Self>, row: usize) {
55            self.rows_copy.borrow_mut()[row] = self.model.row_data(row).unwrap();
56        }
57
58        fn row_added(self: Pin<&Self>, index: usize, count: usize) {
59            let mut copy = self.rows_copy.borrow_mut();
60            for row in index..index + count {
61                copy.insert(row, self.model.row_data(row).unwrap());
62            }
63        }
64
65        fn row_removed(self: Pin<&Self>, index: usize, count: usize) {
66            self.rows_copy.borrow_mut().drain(index..index + count);
67        }
68        fn reset(self: Pin<&Self>) {
69            *self.rows_copy.borrow_mut() = ModelRc::from(self.model.clone()).iter().collect()
70        }
71    }
72
73    impl<Data: PartialEq + core::fmt::Debug + 'static> ModelChecker<Data> {
74        pub fn new(
75            model: Rc<impl Model<Data = Data> + 'static>,
76        ) -> Pin<Box<ModelChangeListenerContainer<Self>>> {
77            let s = Self { rows_copy: RefCell::new(model.iter().collect()), model: model.clone() };
78            let s = Box::pin(ModelChangeListenerContainer::new(s));
79            model.model_tracker().attach_peer(s.as_ref().model_peer());
80            s
81        }
82
83        #[track_caller]
84        pub fn check(&self) {
85            assert_eq!(
86                *self.rows_copy.borrow(),
87                ModelRc::from(self.model.clone()).iter().collect::<Vec<_>>()
88            );
89        }
90    }
91
92    impl<Data: PartialEq + core::fmt::Debug + 'static> Drop for ModelChecker<Data> {
93        fn drop(&mut self) {
94            self.check();
95        }
96    }
97
98    #[derive(Default)]
99    pub struct BrokenModel<T> {
100        pub data: RefCell<Vec<Option<T>>>,
101        pub notify: ModelNotify,
102    }
103
104    #[cfg(test)]
105    impl<T: Clone> Model for BrokenModel<T> {
106        type Data = T;
107
108        fn row_count(&self) -> usize {
109            self.data.borrow().len()
110        }
111
112        fn row_data(&self, row: usize) -> Option<Self::Data> {
113            self.data.borrow().get(row).and_then(|x| x.clone())
114        }
115
116        fn set_row_data(&self, row: usize, data: Self::Data) {
117            self.data.borrow_mut()[row] = Some(data);
118            self.notify.row_changed(row);
119        }
120
121        fn model_tracker(&self) -> &dyn ModelTracker {
122            &self.notify
123        }
124    }
125
126    impl<T> BrokenModel<T> {
127        pub fn new(data: Vec<Option<T>>) -> Rc<Self> {
128            Rc::new(Self { data: RefCell::new(data), notify: Default::default() })
129        }
130    }
131}
132
133/// Provides rows that are generated by a map function based on the rows of another Model
134///
135/// When the other Model is updated, the `MapModel` is updated accordingly.
136///
137/// Generic parameters:
138/// * `M` the type of the wrapped `Model`.
139/// * `F` the map function.
140///
141/// ## Example
142///
143/// Here we have a [`VecModel`] holding rows of a custom type `Name`.
144/// It is then mapped into a `MapModel` of [`SharedString`]s
145///
146/// ```
147/// # use slint::{Model, VecModel, SharedString, MapModel};
148/// #[derive(Clone)]
149/// struct Name {
150///     first: String,
151///     last: String,
152/// }
153///
154/// let model = VecModel::from(vec![
155///     Name { first: "Hans".to_string(), last: "Emil".to_string() },
156///     Name { first: "Max".to_string(), last: "Mustermann".to_string() },
157///     Name { first: "Roman".to_string(), last: "Tisch".to_string() },
158/// ]);
159///
160/// let mapped_model = MapModel::new(model, |n|
161///     slint::format!("{}, {}", n.last, n.first)
162/// );
163///
164/// assert_eq!(mapped_model.row_data(0).unwrap(), SharedString::from("Emil, Hans"));
165/// assert_eq!(mapped_model.row_data(1).unwrap(), SharedString::from("Mustermann, Max"));
166/// assert_eq!(mapped_model.row_data(2).unwrap(), SharedString::from("Tisch, Roman"));
167///
168/// ```
169///
170/// Alternatively you can use the shortcut [`ModelExt::map`].
171/// ```
172/// # use slint::{Model, ModelExt, VecModel, SharedString, MapModel};
173/// # #[derive(Clone)]
174/// # struct Name {
175/// #     first: String,
176/// #     last: String,
177/// # }
178/// let mapped_model = VecModel::from(vec![
179///     Name { first: "Hans".to_string(), last: "Emil".to_string() },
180///     Name { first: "Max".to_string(), last: "Mustermann".to_string() },
181///     Name { first: "Roman".to_string(), last: "Tisch".to_string() },
182/// ])
183/// .map(|n| slint::format!("{}, {}", n.last, n.first));
184/// # assert_eq!(mapped_model.row_data(0).unwrap(), SharedString::from("Emil, Hans"));
185/// # assert_eq!(mapped_model.row_data(1).unwrap(), SharedString::from("Mustermann, Max"));
186/// # assert_eq!(mapped_model.row_data(2).unwrap(), SharedString::from("Tisch, Roman"));
187/// ```
188///
189/// If you want to modify the underlying [`VecModel`] you can give it a [`Rc`] of the MapModel:
190/// ```
191/// # use std::rc::Rc;
192/// # use slint::{Model, VecModel, SharedString, MapModel};
193/// # #[derive(Clone)]
194/// # struct Name {
195/// #     first: String,
196/// #     last: String,
197/// # }
198/// let model = Rc::new(VecModel::from(vec![
199///     Name { first: "Hans".to_string(), last: "Emil".to_string() },
200///     Name { first: "Max".to_string(), last: "Mustermann".to_string() },
201///     Name { first: "Roman".to_string(), last: "Tisch".to_string() },
202/// ]));
203///
204/// let mapped_model = MapModel::new(model.clone(), |n|
205///     slint::format!("{}, {}", n.last, n.first)
206/// );
207///
208/// model.set_row_data(1, Name { first: "Minnie".to_string(), last: "Musterfrau".to_string() });
209///
210/// assert_eq!(mapped_model.row_data(0).unwrap(), SharedString::from("Emil, Hans"));
211/// assert_eq!(mapped_model.row_data(1).unwrap(), SharedString::from("Musterfrau, Minnie"));
212/// assert_eq!(mapped_model.row_data(2).unwrap(), SharedString::from("Tisch, Roman"));
213///
214/// ```
215pub struct MapModel<M, F> {
216    wrapped_model: M,
217    map_function: F,
218}
219
220impl<M, F, T, U> Model for MapModel<M, F>
221where
222    M: 'static,
223    F: 'static,
224    F: Fn(T) -> U,
225    M: Model<Data = T>,
226{
227    type Data = U;
228
229    fn row_count(&self) -> usize {
230        self.wrapped_model.row_count()
231    }
232
233    fn row_data(&self, row: usize) -> Option<Self::Data> {
234        self.wrapped_model.row_data(row).map(|x| (self.map_function)(x))
235    }
236
237    fn model_tracker(&self) -> &dyn ModelTracker {
238        self.wrapped_model.model_tracker()
239    }
240
241    fn as_any(&self) -> &dyn core::any::Any {
242        self
243    }
244}
245
246impl<M, F, T, U> MapModel<M, F>
247where
248    M: 'static,
249    F: 'static,
250    F: Fn(T) -> U,
251    M: Model<Data = T>,
252{
253    /// Creates a new MapModel based on the given `wrapped_model` and `map_function`.
254    /// Alternatively you can use [`ModelExt::map`] on your Model.
255    pub fn new(wrapped_model: M, map_function: F) -> Self {
256        Self { wrapped_model, map_function }
257    }
258
259    /// Returns a reference to the inner model
260    pub fn source_model(&self) -> &M {
261        &self.wrapped_model
262    }
263}
264
265#[test]
266fn test_map_model() {
267    use alloc::string::ToString;
268    let wrapped_rc = Rc::new(VecModel::from(std::vec![1, 2, 3]));
269    let map = MapModel::new(wrapped_rc.clone(), |x| x.to_string());
270
271    wrapped_rc.set_row_data(2, 42);
272    wrapped_rc.push(4);
273
274    assert_eq!(map.row_data(2).unwrap(), "42");
275    assert_eq!(map.row_data(3).unwrap(), "4");
276    assert_eq!(map.row_data(1).unwrap(), "2");
277}
278
279struct FilterModelInner<M, F>
280where
281    M: Model + 'static,
282    F: Fn(&M::Data) -> bool + 'static,
283{
284    wrapped_model: M,
285    filter_function: F,
286    // This vector saves the indices of the elements that are not filtered out
287    mapping: RefCell<Vec<usize>>,
288    notify: ModelNotify,
289}
290
291impl<M, F> FilterModelInner<M, F>
292where
293    M: Model + 'static,
294    F: Fn(&M::Data) -> bool + 'static,
295{
296    fn build_mapping_vec(&self) {
297        let mut mapping = self.mapping.borrow_mut();
298        *mapping = (0..self.wrapped_model.row_count())
299            .filter_map(|i| {
300                self.wrapped_model.row_data(i).and_then(|e| (self.filter_function)(&e).then_some(i))
301            })
302            .collect();
303    }
304}
305
306impl<M, F> ModelChangeListener for FilterModelInner<M, F>
307where
308    M: Model + 'static,
309    F: Fn(&M::Data) -> bool + 'static,
310{
311    fn row_changed(self: Pin<&Self>, row: usize) {
312        let mut mapping = self.mapping.borrow_mut();
313
314        let (index, is_contained) = match mapping.binary_search(&row) {
315            Ok(index) => (index, true),
316            Err(index) => (index, false),
317        };
318
319        let should_be_contained =
320            self.wrapped_model.row_data(row).is_some_and(|data| (self.filter_function)(&data));
321
322        if is_contained && should_be_contained {
323            drop(mapping);
324            self.notify.row_changed(index);
325        } else if !is_contained && should_be_contained {
326            mapping.insert(index, row);
327            drop(mapping);
328            self.notify.row_added(index, 1);
329        } else if is_contained && !should_be_contained {
330            mapping.remove(index);
331            drop(mapping);
332            self.notify.row_removed(index, 1);
333        }
334    }
335
336    fn row_added(self: Pin<&Self>, index: usize, count: usize) {
337        if count == 0 {
338            return;
339        }
340
341        let insertion: Vec<usize> = self
342            .wrapped_model
343            .iter()
344            .enumerate()
345            .skip(index)
346            .take(count)
347            .filter_map(|(i, e)| (self.filter_function)(&e).then_some(i))
348            .collect();
349
350        let mut mapping = self.mapping.borrow_mut();
351        let insertion_point = mapping.binary_search(&index).unwrap_or_else(|ip| ip);
352        mapping[insertion_point..].iter_mut().for_each(|i| *i += count);
353
354        if !insertion.is_empty() {
355            let insertion_len = insertion.len();
356            mapping.splice(insertion_point..insertion_point, insertion);
357
358            drop(mapping);
359            self.notify.row_added(insertion_point, insertion_len);
360        }
361    }
362
363    fn row_removed(self: Pin<&Self>, index: usize, count: usize) {
364        if count == 0 {
365            return;
366        }
367        let mut mapping = self.mapping.borrow_mut();
368
369        let start = mapping.binary_search(&index).unwrap_or_else(|s| s);
370        let end = mapping.binary_search(&(index + count)).unwrap_or_else(|e| e);
371        let range = start..end;
372
373        mapping[end..].iter_mut().for_each(|i| *i -= count);
374
375        if !range.is_empty() {
376            mapping.drain(range.clone());
377            drop(mapping);
378            self.notify.row_removed(start, range.len());
379        }
380    }
381
382    fn reset(self: Pin<&Self>) {
383        self.build_mapping_vec();
384        self.notify.reset();
385    }
386}
387
388/// Provides a filtered subset of rows by another [`Model`].
389///
390/// When the other Model is updated, the `FilterModel` is updated accordingly.
391///
392/// Generic parameters:
393/// * `M` the type of the wrapped `Model`.
394/// * `F` the filter function.
395///
396/// ## Example
397///
398/// Here we have a [`VecModel`] holding [`crate::SharedString`]s.
399/// It is then filtered into a `FilterModel`.
400///
401/// ```
402/// # use slint::{Model, VecModel, SharedString, FilterModel};
403/// let model = VecModel::from(vec![
404///     SharedString::from("Lorem"),
405///     SharedString::from("ipsum"),
406///     SharedString::from("dolor"),
407/// ]);
408///
409/// let filtered_model = FilterModel::new(model, |s| s.contains('o'));
410///
411/// assert_eq!(filtered_model.row_data(0).unwrap(), SharedString::from("Lorem"));
412/// assert_eq!(filtered_model.row_data(1).unwrap(), SharedString::from("dolor"));
413/// ```
414///
415/// Alternatively you can use the shortcut [`ModelExt::filter`].
416/// ```
417/// # use slint::{Model, ModelExt, VecModel, SharedString, FilterModel};
418/// let filtered_model = VecModel::from(vec![
419///     SharedString::from("Lorem"),
420///     SharedString::from("ipsum"),
421///     SharedString::from("dolor"),
422/// ]).filter(|s| s.contains('o'));
423/// # assert_eq!(filtered_model.row_data(0).unwrap(), SharedString::from("Lorem"));
424/// # assert_eq!(filtered_model.row_data(1).unwrap(), SharedString::from("dolor"));
425/// ```
426///
427/// If you want to modify the underlying [`VecModel`] you can give it a [`Rc`] of the FilterModel:
428/// ```
429/// # use std::rc::Rc;
430/// # use slint::{Model, VecModel, SharedString, FilterModel};
431/// let model = Rc::new(VecModel::from(vec![
432///     SharedString::from("Lorem"),
433///     SharedString::from("ipsum"),
434///     SharedString::from("dolor"),
435/// ]));
436///
437/// let filtered_model = FilterModel::new(model.clone(), |s| s.contains('o'));
438///
439/// assert_eq!(filtered_model.row_data(0).unwrap(), SharedString::from("Lorem"));
440/// assert_eq!(filtered_model.row_data(1).unwrap(), SharedString::from("dolor"));
441///
442/// model.set_row_data(1, SharedString::from("opsom"));
443///
444/// assert_eq!(filtered_model.row_data(0).unwrap(), SharedString::from("Lorem"));
445/// assert_eq!(filtered_model.row_data(1).unwrap(), SharedString::from("opsom"));
446/// assert_eq!(filtered_model.row_data(2).unwrap(), SharedString::from("dolor"));
447/// ```
448pub struct FilterModel<M, F>(Pin<Box<ModelChangeListenerContainer<FilterModelInner<M, F>>>>)
449where
450    M: Model + 'static,
451    F: Fn(&M::Data) -> bool + 'static;
452
453impl<M, F> FilterModel<M, F>
454where
455    M: Model + 'static,
456    F: Fn(&M::Data) -> bool + 'static,
457{
458    /// Creates a new FilterModel based on the given `wrapped_model` and filtered by `filter_function`.
459    /// Alternatively you can use [`ModelExt::filter`] on your Model.
460    pub fn new(wrapped_model: M, filter_function: F) -> Self {
461        let filter_model_inner = FilterModelInner {
462            wrapped_model,
463            filter_function,
464            mapping: RefCell::new(Vec::new()),
465            notify: Default::default(),
466        };
467
468        filter_model_inner.build_mapping_vec();
469
470        let container = Box::pin(ModelChangeListenerContainer::new(filter_model_inner));
471
472        container.wrapped_model.model_tracker().attach_peer(container.as_ref().model_peer());
473
474        Self(container)
475    }
476
477    /// Manually reapply the filter. You need to run this e.g. if the filtering function depends on
478    /// mutable state and it has changed.
479    pub fn reset(&self) {
480        self.0.as_ref().get().reset();
481    }
482
483    /// Gets the row index of the underlying unfiltered model for a given filtered row index.
484    pub fn unfiltered_row(&self, filtered_row: usize) -> usize {
485        self.0.mapping.borrow()[filtered_row]
486    }
487
488    /// Returns a reference to the inner model
489    pub fn source_model(&self) -> &M {
490        &self.0.as_ref().get().get_ref().wrapped_model
491    }
492}
493
494impl<M, F> Model for FilterModel<M, F>
495where
496    M: Model + 'static,
497    F: Fn(&M::Data) -> bool + 'static,
498{
499    type Data = M::Data;
500
501    fn row_count(&self) -> usize {
502        self.0.mapping.borrow().len()
503    }
504
505    fn row_data(&self, row: usize) -> Option<Self::Data> {
506        self.0
507            .mapping
508            .borrow()
509            .get(row)
510            .and_then(|&wrapped_row| self.0.wrapped_model.row_data(wrapped_row))
511    }
512
513    fn set_row_data(&self, row: usize, data: Self::Data) {
514        let wrapped_row = self.0.mapping.borrow()[row];
515        self.0.wrapped_model.set_row_data(wrapped_row, data);
516    }
517
518    fn model_tracker(&self) -> &dyn ModelTracker {
519        &self.0.notify
520    }
521
522    fn as_any(&self) -> &dyn core::any::Any {
523        self
524    }
525}
526
527#[test]
528fn test_filter_model() {
529    use tests_helper::*;
530    let wrapped_rc = Rc::new(VecModel::from(std::vec![1, 2, 3, 4, 5, 6]));
531    let filter = Rc::new(FilterModel::new(wrapped_rc.clone(), |x| x % 2 == 0));
532
533    let _checker = ModelChecker::new(filter.clone());
534
535    assert_eq!(filter.row_data(0).unwrap(), 2);
536    assert_eq!(filter.row_data(1).unwrap(), 4);
537    assert_eq!(filter.row_data(2).unwrap(), 6);
538    assert_eq!(filter.row_count(), 3);
539
540    wrapped_rc.remove(1);
541    assert_eq!(filter.row_data(0).unwrap(), 4);
542    assert_eq!(filter.row_data(1).unwrap(), 6);
543    assert_eq!(filter.row_count(), 2);
544
545    wrapped_rc.push(8);
546    wrapped_rc.push(7);
547    assert_eq!(filter.row_data(0).unwrap(), 4);
548    assert_eq!(filter.row_data(1).unwrap(), 6);
549    assert_eq!(filter.row_data(2).unwrap(), 8);
550    assert_eq!(filter.row_count(), 3);
551
552    wrapped_rc.set_row_data(1, 2);
553    assert_eq!(filter.row_data(0).unwrap(), 2);
554    assert_eq!(filter.row_data(1).unwrap(), 4);
555    assert_eq!(filter.row_data(2).unwrap(), 6);
556    assert_eq!(filter.row_data(3).unwrap(), 8);
557    assert_eq!(filter.row_count(), 4);
558
559    wrapped_rc.insert(2, 12);
560    assert_eq!(filter.row_data(0).unwrap(), 2);
561    assert_eq!(filter.row_data(1).unwrap(), 12);
562    assert_eq!(filter.row_data(2).unwrap(), 4);
563    assert_eq!(filter.row_data(3).unwrap(), 6);
564    assert_eq!(filter.row_data(4).unwrap(), 8);
565    assert_eq!(filter.row_count(), 5);
566}
567
568#[test]
569fn test_filter_model_source_model() {
570    use tests_helper::*;
571    let wrapped_rc = Rc::new(VecModel::from(std::vec![1, 2, 3, 4]));
572    let model = Rc::new(FilterModel::new(wrapped_rc.clone(), |x| x % 2 == 0));
573
574    let observer = Box::pin(ModelChangeListenerContainer::<TestView>::default());
575    model.model_tracker().attach_peer(Pin::as_ref(&observer).model_peer());
576
577    let _checker = ModelChecker::new(model.clone());
578
579    model.source_model().push(5);
580    model.source_model().push(6);
581
582    let expected = &[2, 4, 6];
583    assert_eq!(model.row_count(), expected.len());
584    for (i, v) in expected.iter().enumerate() {
585        assert_eq!(model.row_data(i), Some(*v), "Expected {v} at index {i}");
586    }
587}
588
589#[test]
590fn test_filter_model_broken_model() {
591    use tests_helper::*;
592    let wrapped_rc = BrokenModel::new(std::vec![Some(1), Some(2), None, Some(3), None, Some(4)]);
593    let model = Rc::new(FilterModel::new(wrapped_rc.clone(), |x| x % 2 == 0));
594
595    assert_eq!(model.row_count(), 2);
596    assert_eq!(model.row_data(0), Some(2));
597    assert_eq!(model.row_data(1), Some(4));
598
599    wrapped_rc.notify.row_removed(1, 2);
600    wrapped_rc.notify.row_added(1, 2);
601    wrapped_rc.data.borrow_mut()[1] = None;
602    wrapped_rc.data.borrow_mut()[2] = Some(8);
603    wrapped_rc.notify.row_changed(1);
604    wrapped_rc.notify.row_changed(2);
605
606    assert_eq!(model.row_count(), 2);
607    assert_eq!(model.row_data(0), Some(8));
608    assert_eq!(model.row_data(1), Some(4));
609}
610
611pub trait SortHelper<D> {
612    fn cmp(&mut self, lhs: &D, rhs: &D) -> core::cmp::Ordering;
613}
614
615pub struct AscendingSortHelper;
616
617impl<D> SortHelper<D> for AscendingSortHelper
618where
619    D: core::cmp::Ord,
620{
621    fn cmp(&mut self, lhs: &D, rhs: &D) -> core::cmp::Ordering {
622        lhs.cmp(rhs)
623    }
624}
625
626impl<F, D> SortHelper<D> for F
627where
628    F: FnMut(&D, &D) -> core::cmp::Ordering + 'static,
629{
630    fn cmp(&mut self, lhs: &D, rhs: &D) -> core::cmp::Ordering {
631        (self)(lhs, rhs)
632    }
633}
634
635struct SortModelInner<M, S>
636where
637    M: Model + 'static,
638    S: SortHelper<M::Data> + 'static,
639{
640    wrapped_model: M,
641    sort_helper: RefCell<S>,
642    // This vector saves the indices of the elements in sorted order.
643    mapping: RefCell<Vec<usize>>,
644    notify: ModelNotify,
645    sorted_rows_dirty: Cell<bool>,
646}
647
648impl<M, S> SortModelInner<M, S>
649where
650    M: Model + 'static,
651    S: SortHelper<M::Data>,
652{
653    fn build_mapping_vec(&self) {
654        if !self.sorted_rows_dirty.get() {
655            return;
656        }
657
658        let mut mapping = self.mapping.borrow_mut();
659
660        mapping.clear();
661        mapping.extend(0..self.wrapped_model.row_count());
662        mapping.sort_by(|lhs, rhs| {
663            let Some(lhs) = self.wrapped_model.row_data(*lhs) else {
664                return core::cmp::Ordering::Greater;
665            };
666            let Some(rhs) = self.wrapped_model.row_data(*rhs) else {
667                return core::cmp::Ordering::Less;
668            };
669            self.sort_helper.borrow_mut().cmp(&lhs, &rhs)
670        });
671
672        self.sorted_rows_dirty.set(false);
673    }
674}
675
676impl<M, S> ModelChangeListener for SortModelInner<M, S>
677where
678    M: Model + 'static,
679    S: SortHelper<M::Data> + 'static,
680{
681    fn row_changed(self: Pin<&Self>, row: usize) {
682        if self.sorted_rows_dirty.get() {
683            self.reset();
684            return;
685        }
686
687        let mut mapping = self.mapping.borrow_mut();
688        let removed_index = mapping.iter().position(|r| *r == row).unwrap();
689        mapping.remove(removed_index);
690
691        let insertion_index = if let Some(changed_data) = self.wrapped_model.row_data(row) {
692            mapping.partition_point(|existing_row| {
693                self.wrapped_model.row_data(*existing_row).is_some_and(|existing| {
694                    self.sort_helper.borrow_mut().cmp(&existing, &changed_data)
695                        == core::cmp::Ordering::Less
696                })
697            })
698        } else {
699            mapping.len()
700        };
701
702        mapping.insert(insertion_index, row);
703
704        drop(mapping);
705
706        if insertion_index == removed_index {
707            self.notify.row_changed(removed_index);
708        } else {
709            self.notify.row_removed(removed_index, 1);
710            self.notify.row_added(insertion_index, 1);
711        }
712    }
713
714    fn row_added(self: Pin<&Self>, index: usize, count: usize) {
715        if count == 0 {
716            return;
717        }
718
719        if self.sorted_rows_dirty.get() {
720            self.reset();
721            return;
722        }
723
724        // Adjust the existing sorted row indices to match the updated source model
725        for row in self.mapping.borrow_mut().iter_mut() {
726            if *row >= index {
727                *row += count;
728            }
729        }
730
731        for row in index..(index + count) {
732            let insertion_index = if let Some(added_data) = self.wrapped_model.row_data(row) {
733                self.mapping.borrow().partition_point(|existing_row| {
734                    self.wrapped_model.row_data(*existing_row).is_some_and(|existing| {
735                        self.sort_helper.borrow_mut().cmp(&existing, &added_data)
736                            == core::cmp::Ordering::Less
737                    })
738                })
739            } else {
740                self.mapping.borrow().len()
741            };
742            self.mapping.borrow_mut().insert(insertion_index, row);
743            self.notify.row_added(insertion_index, 1)
744        }
745    }
746
747    fn row_removed(self: Pin<&Self>, index: usize, count: usize) {
748        if count == 0 {
749            return;
750        }
751
752        if self.sorted_rows_dirty.get() {
753            self.reset();
754            return;
755        }
756
757        let mut removed_rows = Vec::new();
758
759        let mut i = 0;
760
761        loop {
762            if i >= self.mapping.borrow().len() {
763                break;
764            }
765
766            let sort_index = self.mapping.borrow()[i];
767
768            if sort_index >= index {
769                if sort_index < index + count {
770                    removed_rows.push(i);
771                    self.mapping.borrow_mut().remove(i);
772                    continue;
773                } else {
774                    self.mapping.borrow_mut()[i] -= count;
775                }
776            }
777
778            i += 1;
779        }
780
781        for removed_row in removed_rows {
782            self.notify.row_removed(removed_row, 1);
783        }
784    }
785
786    fn reset(self: Pin<&Self>) {
787        self.sorted_rows_dirty.set(true);
788        self.notify.reset();
789    }
790}
791
792/// Provides a sorted view of rows by another [`Model`].
793///
794/// When the other Model is updated, the `Sorted` is updated accordingly.
795///
796/// Generic parameters:
797/// * `M` the type of the wrapped `Model`.
798/// * `F` a type that provides an order to model rows. It is constrained by the internal trait `SortHelper`, which is used to sort the model in ascending order if the model data supports it, or by a given sort function.
799///
800/// ## Example
801///
802/// Here we have a [`VecModel`] holding [`crate::SharedString`]s.
803/// It is then sorted into a `SortModel`.
804///
805/// ```
806/// # use slint::{Model, VecModel, SharedString, SortModel};
807/// let model = VecModel::from(vec![
808///     SharedString::from("Lorem"),
809///     SharedString::from("ipsum"),
810///     SharedString::from("dolor"),
811/// ]);
812///
813/// let sorted_model = SortModel::new(model, |lhs, rhs| lhs.to_lowercase().cmp(&rhs.to_lowercase()));
814///
815/// assert_eq!(sorted_model.row_data(0).unwrap(), SharedString::from("dolor"));
816/// assert_eq!(sorted_model.row_data(1).unwrap(), SharedString::from("ipsum"));
817/// assert_eq!(sorted_model.row_data(2).unwrap(), SharedString::from("Lorem"));
818/// ```
819///
820/// Alternatively you can use the shortcut [`ModelExt::sort_by`].
821/// ```
822/// # use slint::{Model, ModelExt, VecModel, SharedString, SortModel};
823/// let sorted_model = VecModel::from(vec![
824///     SharedString::from("Lorem"),
825///     SharedString::from("ipsum"),
826///     SharedString::from("dolor"),
827/// ]).sort_by(|lhs, rhs| lhs.to_lowercase().cmp(&rhs.to_lowercase()));
828/// # assert_eq!(sorted_model.row_data(0).unwrap(), SharedString::from("dolor"));
829/// # assert_eq!(sorted_model.row_data(1).unwrap(), SharedString::from("ipsum"));
830/// # assert_eq!(sorted_model.row_data(2).unwrap(), SharedString::from("Lorem"));
831/// ```
832///
833/// It is also possible to get a ascending sorted  `SortModel` order for `core::cmp::Ord` type items.
834///
835/// ```
836/// # use slint::{Model, VecModel, SortModel};
837/// let model = VecModel::from(vec![
838///     5,
839///     1,
840///     3,
841/// ]);
842///
843/// let sorted_model = SortModel::new_ascending(model);
844///
845/// assert_eq!(sorted_model.row_data(0).unwrap(), 1);
846/// assert_eq!(sorted_model.row_data(1).unwrap(), 3);
847/// assert_eq!(sorted_model.row_data(2).unwrap(), 5);
848/// ```
849///
850/// Alternatively you can use the shortcut [`ModelExt::sort`].
851/// ```
852/// # use slint::{Model, ModelExt, VecModel, SharedString, SortModel};
853/// let sorted_model = VecModel::from(vec![
854///     5,
855///     1,
856///     3,
857/// ]).sort();
858/// # assert_eq!(sorted_model.row_data(0).unwrap(), 1);
859/// # assert_eq!(sorted_model.row_data(1).unwrap(), 3);
860/// # assert_eq!(sorted_model.row_data(2).unwrap(), 5);
861/// ```
862///
863/// If you want to modify the underlying [`VecModel`] you can give it a [`Rc`] of the SortModel:
864/// ```
865/// # use std::rc::Rc;
866/// # use slint::{Model, VecModel, SharedString, SortModel};
867/// let model = Rc::new(VecModel::from(vec![
868///     SharedString::from("Lorem"),
869///     SharedString::from("ipsum"),
870///     SharedString::from("dolor"),
871/// ]));
872///
873/// let sorted_model = SortModel::new(model.clone(), |lhs, rhs| lhs.to_lowercase().cmp(&rhs.to_lowercase()));
874///
875/// assert_eq!(sorted_model.row_data(0).unwrap(), SharedString::from("dolor"));
876/// assert_eq!(sorted_model.row_data(1).unwrap(), SharedString::from("ipsum"));
877/// assert_eq!(sorted_model.row_data(2).unwrap(), SharedString::from("Lorem"));
878///
879/// model.set_row_data(1, SharedString::from("opsom"));
880///
881/// assert_eq!(sorted_model.row_data(0).unwrap(), SharedString::from("dolor"));
882/// assert_eq!(sorted_model.row_data(1).unwrap(), SharedString::from("Lorem"));
883/// assert_eq!(sorted_model.row_data(2).unwrap(), SharedString::from("opsom"));
884/// ```
885pub struct SortModel<M, F>(Pin<Box<ModelChangeListenerContainer<SortModelInner<M, F>>>>)
886where
887    M: Model + 'static,
888    F: SortHelper<M::Data> + 'static;
889
890impl<M, F> SortModel<M, F>
891where
892    M: Model + 'static,
893    F: FnMut(&M::Data, &M::Data) -> core::cmp::Ordering + 'static,
894{
895    /// Creates a new SortModel based on the given `wrapped_model` and sorted by `sort_function`.
896    /// Alternatively you can use [`ModelExt::sort_by`] on your Model.
897    pub fn new(wrapped_model: M, sort_function: F) -> Self
898    where
899        F: FnMut(&M::Data, &M::Data) -> core::cmp::Ordering + 'static,
900    {
901        let sorted_model_inner = SortModelInner {
902            wrapped_model,
903            sort_helper: RefCell::new(sort_function),
904            mapping: RefCell::new(Vec::new()),
905            notify: Default::default(),
906            sorted_rows_dirty: Cell::new(true),
907        };
908
909        let container = Box::pin(ModelChangeListenerContainer::new(sorted_model_inner));
910
911        container.wrapped_model.model_tracker().attach_peer(container.as_ref().model_peer());
912
913        Self(container)
914    }
915}
916
917impl<M> SortModel<M, AscendingSortHelper>
918where
919    M: Model + 'static,
920    M::Data: core::cmp::Ord,
921{
922    /// Creates a new SortModel based on the given `wrapped_model` and sorted in ascending order.
923    /// Alternatively you can use [`ModelExt::sort`] on your Model.
924    pub fn new_ascending(wrapped_model: M) -> Self
925    where
926        M::Data: core::cmp::Ord,
927    {
928        let sorted_model_inner = SortModelInner {
929            wrapped_model,
930            sort_helper: RefCell::new(AscendingSortHelper),
931            mapping: RefCell::new(Vec::new()),
932            notify: Default::default(),
933            sorted_rows_dirty: Cell::new(true),
934        };
935
936        let container = Box::pin(ModelChangeListenerContainer::new(sorted_model_inner));
937
938        container.wrapped_model.model_tracker().attach_peer(container.as_ref().model_peer());
939
940        Self(container)
941    }
942}
943
944impl<M, S> SortModel<M, S>
945where
946    M: Model + 'static,
947    S: SortHelper<M::Data>,
948{
949    /// Returns a reference to the inner model
950    pub fn source_model(&self) -> &M {
951        &self.0.as_ref().get().get_ref().wrapped_model
952    }
953
954    /// Manually reapply the sorting. You need to run this e.g. if the sort function depends
955    /// on mutable state and it has changed.
956    pub fn reset(&self) {
957        self.0.as_ref().get().reset();
958    }
959
960    /// Gets the row index of the underlying unsorted model for a given sorted row index.
961    pub fn unsorted_row(&self, sorted_row: usize) -> usize {
962        self.0.build_mapping_vec();
963        self.0.mapping.borrow()[sorted_row]
964    }
965}
966
967impl<M, S> Model for SortModel<M, S>
968where
969    M: Model + 'static,
970    S: SortHelper<M::Data>,
971{
972    type Data = M::Data;
973
974    fn row_count(&self) -> usize {
975        self.0.wrapped_model.row_count()
976    }
977
978    fn row_data(&self, row: usize) -> Option<Self::Data> {
979        self.0.build_mapping_vec();
980
981        self.0
982            .mapping
983            .borrow()
984            .get(row)
985            .and_then(|&wrapped_row| self.0.wrapped_model.row_data(wrapped_row))
986    }
987
988    fn set_row_data(&self, row: usize, data: Self::Data) {
989        let wrapped_row = self.0.mapping.borrow()[row];
990        self.0.wrapped_model.set_row_data(wrapped_row, data);
991    }
992
993    fn model_tracker(&self) -> &dyn ModelTracker {
994        &self.0.notify
995    }
996
997    fn as_any(&self) -> &dyn core::any::Any {
998        self
999    }
1000}
1001
1002#[cfg(test)]
1003mod sort_tests {
1004    use super::*;
1005    use std::vec;
1006    use tests_helper::*;
1007
1008    #[test]
1009    fn test_sorted_model_insert() {
1010        let wrapped_rc = Rc::new(VecModel::from(std::vec![3, 4, 1, 2]));
1011        let sorted_model = Rc::new(SortModel::new(wrapped_rc.clone(), |lhs, rhs| lhs.cmp(rhs)));
1012
1013        let _checker = ModelChecker::new(sorted_model.clone());
1014
1015        let observer = Box::pin(ModelChangeListenerContainer::<TestView>::default());
1016        sorted_model.model_tracker().attach_peer(Pin::as_ref(&observer).model_peer());
1017
1018        assert_eq!(sorted_model.row_count(), 4);
1019        assert_eq!(sorted_model.row_data(0).unwrap(), 1);
1020        assert_eq!(sorted_model.row_data(1).unwrap(), 2);
1021        assert_eq!(sorted_model.row_data(2).unwrap(), 3);
1022        assert_eq!(sorted_model.row_data(3).unwrap(), 4);
1023
1024        wrapped_rc.insert(0, 10);
1025
1026        assert_eq!(observer.added_rows.borrow().len(), 1);
1027        assert!(observer.added_rows.borrow().eq(&[(4, 1)]));
1028        assert!(observer.changed_rows.borrow().is_empty());
1029        assert!(observer.removed_rows.borrow().is_empty());
1030        assert_eq!(*observer.reset.borrow(), 0);
1031        observer.clear();
1032
1033        assert_eq!(sorted_model.row_count(), 5);
1034        assert_eq!(sorted_model.row_data(0).unwrap(), 1);
1035        assert_eq!(sorted_model.row_data(1).unwrap(), 2);
1036        assert_eq!(sorted_model.row_data(2).unwrap(), 3);
1037        assert_eq!(sorted_model.row_data(3).unwrap(), 4);
1038        assert_eq!(sorted_model.row_data(4).unwrap(), 10);
1039    }
1040
1041    #[test]
1042    fn test_sorted_model_remove() {
1043        let wrapped_rc = Rc::new(VecModel::from(vec![3, 4, 1, 2]));
1044        let sorted_model = Rc::new(SortModel::new(wrapped_rc.clone(), |lhs, rhs| lhs.cmp(rhs)));
1045
1046        let _checker = ModelChecker::new(sorted_model.clone());
1047
1048        let observer = Box::pin(ModelChangeListenerContainer::<TestView>::default());
1049        sorted_model.model_tracker().attach_peer(Pin::as_ref(&observer).model_peer());
1050
1051        assert_eq!(sorted_model.row_count(), 4);
1052        assert_eq!(sorted_model.row_data(0).unwrap(), 1);
1053        assert_eq!(sorted_model.row_data(1).unwrap(), 2);
1054        assert_eq!(sorted_model.row_data(2).unwrap(), 3);
1055        assert_eq!(sorted_model.row_data(3).unwrap(), 4);
1056
1057        // Remove the entry with the value 4
1058        wrapped_rc.remove(1);
1059
1060        assert!(observer.added_rows.borrow().is_empty());
1061        assert!(observer.changed_rows.borrow().is_empty());
1062        assert_eq!(observer.removed_rows.borrow().len(), 1);
1063        assert!(observer.removed_rows.borrow().eq(&[(3, 1)]));
1064        assert_eq!(*observer.reset.borrow(), 0);
1065        observer.clear();
1066
1067        assert_eq!(sorted_model.row_count(), 3);
1068        assert_eq!(sorted_model.row_data(0).unwrap(), 1);
1069        assert_eq!(sorted_model.row_data(1).unwrap(), 2);
1070        assert_eq!(sorted_model.row_data(2).unwrap(), 3);
1071    }
1072
1073    #[test]
1074    fn test_sorted_model_changed() {
1075        let wrapped_rc = Rc::new(VecModel::from(vec![3, 4, 1, 2]));
1076        let sorted_model = Rc::new(SortModel::new(wrapped_rc.clone(), |lhs, rhs| lhs.cmp(rhs)));
1077
1078        let _checker = ModelChecker::new(sorted_model.clone());
1079
1080        let observer = Box::pin(ModelChangeListenerContainer::<TestView>::default());
1081        sorted_model.model_tracker().attach_peer(Pin::as_ref(&observer).model_peer());
1082
1083        assert_eq!(sorted_model.row_count(), 4);
1084        assert_eq!(sorted_model.row_data(0).unwrap(), 1);
1085        assert_eq!(sorted_model.row_data(1).unwrap(), 2);
1086        assert_eq!(sorted_model.row_data(2).unwrap(), 3);
1087        assert_eq!(sorted_model.row_data(3).unwrap(), 4);
1088
1089        // Change the entry with the value 4 to 10 -> maintain order
1090        wrapped_rc.set_row_data(1, 10);
1091
1092        assert!(observer.added_rows.borrow().is_empty());
1093        assert_eq!(observer.changed_rows.borrow().len(), 1);
1094        assert_eq!(*observer.changed_rows.borrow().first().unwrap(), 3);
1095        assert!(observer.removed_rows.borrow().is_empty());
1096        assert_eq!(*observer.reset.borrow(), 0);
1097        observer.clear();
1098
1099        assert_eq!(sorted_model.row_count(), 4);
1100        assert_eq!(sorted_model.row_data(0).unwrap(), 1);
1101        assert_eq!(sorted_model.row_data(1).unwrap(), 2);
1102        assert_eq!(sorted_model.row_data(2).unwrap(), 3);
1103        assert_eq!(sorted_model.row_data(3).unwrap(), 10);
1104
1105        // Change the entry with the value 10 to 0 -> new order with remove and insert
1106        wrapped_rc.set_row_data(1, 0);
1107
1108        assert_eq!(observer.added_rows.borrow().len(), 1);
1109        assert!(observer.added_rows.borrow().first().unwrap().eq(&(0, 1)));
1110        assert!(observer.changed_rows.borrow().is_empty());
1111        assert_eq!(observer.removed_rows.borrow().len(), 1);
1112        assert!(observer.removed_rows.borrow().first().unwrap().eq(&(3, 1)));
1113        assert_eq!(*observer.reset.borrow(), 0);
1114        observer.clear();
1115
1116        assert_eq!(sorted_model.row_count(), 4);
1117        assert_eq!(sorted_model.row_data(0).unwrap(), 0);
1118        assert_eq!(sorted_model.row_data(1).unwrap(), 1);
1119        assert_eq!(sorted_model.row_data(2).unwrap(), 2);
1120        assert_eq!(sorted_model.row_data(3).unwrap(), 3);
1121    }
1122
1123    #[test]
1124    fn test_sorted_model_source_model() {
1125        let wrapped_rc = Rc::new(VecModel::from(vec![3, 4, 1, 2]));
1126        let model = Rc::new(SortModel::new(wrapped_rc.clone(), |lhs, rhs| lhs.cmp(rhs)));
1127        let _checker = ModelChecker::new(model.clone());
1128
1129        let observer = Box::pin(ModelChangeListenerContainer::<TestView>::default());
1130        model.model_tracker().attach_peer(Pin::as_ref(&observer).model_peer());
1131
1132        model.source_model().push(6);
1133        model.source_model().push(5);
1134
1135        let expected = &[1, 2, 3, 4, 5, 6];
1136        assert_eq!(model.row_count(), expected.len());
1137        for (i, v) in expected.iter().enumerate() {
1138            assert_eq!(model.row_data(i), Some(*v), "Expected {v} at index {i}");
1139        }
1140
1141        assert!(Rc::ptr_eq(model.source_model(), &wrapped_rc));
1142        model.reset();
1143        assert_eq!(*observer.reset.borrow(), 1);
1144    }
1145
1146    #[test]
1147    fn test_sorted_broken_model() {
1148        let wrapped_rc = BrokenModel::new(std::vec![
1149            Some("1"),
1150            Some("2"),
1151            None,
1152            Some("4"),
1153            None,
1154            Some("3"),
1155            Some("0"),
1156            Some("5")
1157        ]);
1158        let model = Rc::new(SortModel::new_ascending(wrapped_rc.clone()));
1159
1160        assert_eq!(model.row_count(), 8);
1161        assert_eq!(model.row_data(0), Some("0"));
1162        assert_eq!(model.row_data(1), Some("1"));
1163        assert_eq!(model.row_data(2), Some("2"));
1164        assert_eq!(model.row_data(3), Some("3"));
1165        assert_eq!(model.row_data(4), Some("4"));
1166        assert_eq!(model.row_data(5), Some("5"));
1167        assert_eq!(model.row_data(6), None);
1168        assert_eq!(model.row_data(7), None);
1169
1170        wrapped_rc.notify.row_removed(2, 2);
1171        wrapped_rc.notify.row_added(2, 2);
1172        wrapped_rc.data.borrow_mut()[1] = None;
1173        wrapped_rc.notify.row_changed(1);
1174        wrapped_rc.data.borrow_mut()[2] = Some("a");
1175        wrapped_rc.notify.row_changed(2);
1176
1177        assert_eq!(model.row_count(), 8);
1178        assert_eq!(model.row_data(0), Some("0"));
1179        assert_eq!(model.row_data(1), Some("1"));
1180        assert_eq!(model.row_data(2), Some("3"));
1181        assert_eq!(model.row_data(3), Some("4"));
1182        assert_eq!(model.row_data(4), Some("5"));
1183        assert_eq!(model.row_data(5), Some("a"));
1184        assert_eq!(model.row_data(6), None);
1185        assert_eq!(model.row_data(7), None);
1186
1187        assert!(Rc::ptr_eq(model.source_model(), &wrapped_rc));
1188    }
1189}
1190
1191/// Provides a reversed view of another [`Model`].
1192///
1193/// When the other Model is updated, the `ReverseModel` is updated accordingly.
1194///
1195/// Generic parameters:
1196/// * `M` the type of the wrapped `Model`.
1197///
1198/// ## Example
1199///
1200/// Here we have a [`VecModel`] holding [`crate::SharedString`]s.
1201/// It is then reversed into a `ReverseModel`.
1202///
1203/// ```
1204/// # use slint::{Model, VecModel, SharedString, ReverseModel};
1205/// let model = VecModel::from(vec![
1206///     SharedString::from("Lorem"),
1207///     SharedString::from("ipsum"),
1208///     SharedString::from("dolor"),
1209/// ]);
1210///
1211/// let reverse_model = ReverseModel::new(model);
1212///
1213/// assert_eq!(reverse_model.row_data(0).unwrap(), SharedString::from("dolor"));
1214/// assert_eq!(reverse_model.row_data(1).unwrap(), SharedString::from("ipsum"));
1215/// assert_eq!(reverse_model.row_data(2).unwrap(), SharedString::from("Lorem"));
1216/// ```
1217///
1218/// Alternatively you can use the shortcut [`ModelExt::reverse`].
1219/// ```
1220/// # use slint::{Model, ModelExt, VecModel, SharedString};
1221/// let reverse_model = VecModel::from(vec![
1222///     SharedString::from("Lorem"),
1223///     SharedString::from("ipsum"),
1224///     SharedString::from("dolor"),
1225/// ]).reverse();
1226/// assert_eq!(reverse_model.row_data(0).unwrap(), SharedString::from("dolor"));
1227/// assert_eq!(reverse_model.row_data(1).unwrap(), SharedString::from("ipsum"));
1228/// assert_eq!(reverse_model.row_data(2).unwrap(), SharedString::from("Lorem"));
1229/// ```
1230///
1231/// If you want to modify the underlying [`VecModel`] you can give the ReverseModel a [`Rc`] of it:
1232/// ```
1233/// # use std::rc::Rc;
1234/// # use slint::{Model, VecModel, SharedString, ReverseModel};
1235/// let model = Rc::new(VecModel::from(vec![
1236///     SharedString::from("Lorem"),
1237///     SharedString::from("ipsum"),
1238///     SharedString::from("dolor"),
1239/// ]));
1240///
1241/// let reverse_model = ReverseModel::new(model.clone());
1242///
1243/// assert_eq!(reverse_model.row_data(0).unwrap(), SharedString::from("dolor"));
1244/// assert_eq!(reverse_model.row_data(1).unwrap(), SharedString::from("ipsum"));
1245/// assert_eq!(reverse_model.row_data(2).unwrap(), SharedString::from("Lorem"));
1246///
1247/// model.push(SharedString::from("opsom"));
1248///
1249/// assert_eq!(reverse_model.row_data(0).unwrap(), SharedString::from("opsom"));
1250/// assert_eq!(reverse_model.row_data(1).unwrap(), SharedString::from("dolor"));
1251/// assert_eq!(reverse_model.row_data(2).unwrap(), SharedString::from("ipsum"));
1252/// assert_eq!(reverse_model.row_data(3).unwrap(), SharedString::from("Lorem"));
1253/// ```
1254pub struct ReverseModel<M>(Pin<Box<ModelChangeListenerContainer<ReverseModelInner<M>>>>)
1255where
1256    M: Model + 'static;
1257
1258struct ReverseModelInner<M>
1259where
1260    M: Model + 'static,
1261{
1262    wrapped_model: M,
1263    notify: ModelNotify,
1264}
1265
1266impl<M> ModelChangeListener for ReverseModelInner<M>
1267where
1268    M: Model + 'static,
1269{
1270    fn row_changed(self: Pin<&Self>, row: usize) {
1271        self.notify.row_changed(self.wrapped_model.row_count() - 1 - row);
1272    }
1273
1274    fn row_added(self: Pin<&Self>, index: usize, count: usize) {
1275        let row_count = self.wrapped_model.row_count();
1276        let old_row_count = row_count - count;
1277        let index = old_row_count - index;
1278        self.notify.row_added(index, count);
1279    }
1280
1281    fn row_removed(self: Pin<&Self>, index: usize, count: usize) {
1282        let row_count = self.wrapped_model.row_count();
1283        self.notify.row_removed(row_count - index, count);
1284    }
1285
1286    fn reset(self: Pin<&Self>) {
1287        self.notify.reset()
1288    }
1289}
1290
1291impl<M> ReverseModel<M>
1292where
1293    M: Model + 'static,
1294{
1295    /// Creates a new ReverseModel based on the given `wrapped_model`.
1296    /// Alternatively you can use [`ModelExt::reverse`] on your Model.
1297    pub fn new(wrapped_model: M) -> Self {
1298        let inner = ReverseModelInner { wrapped_model, notify: Default::default() };
1299        let container = Box::pin(ModelChangeListenerContainer::new(inner));
1300        container.wrapped_model.model_tracker().attach_peer(container.as_ref().model_peer());
1301        Self(container)
1302    }
1303
1304    /// Returns a reference to the inner model
1305    pub fn source_model(&self) -> &M {
1306        &self.0.as_ref().get().get_ref().wrapped_model
1307    }
1308}
1309
1310impl<M> Model for ReverseModel<M>
1311where
1312    M: Model + 'static,
1313{
1314    type Data = M::Data;
1315
1316    fn row_count(&self) -> usize {
1317        self.0.wrapped_model.row_count()
1318    }
1319
1320    fn row_data(&self, row: usize) -> Option<Self::Data> {
1321        let count = self.0.wrapped_model.row_count();
1322        self.0.wrapped_model.row_data(count.checked_sub(row + 1)?)
1323    }
1324    fn set_row_data(&self, row: usize, data: Self::Data) {
1325        let count = self.0.as_ref().wrapped_model.row_count();
1326        self.0.wrapped_model.set_row_data(count - row - 1, data);
1327    }
1328
1329    fn model_tracker(&self) -> &dyn ModelTracker {
1330        &self.0.notify
1331    }
1332
1333    fn as_any(&self) -> &dyn core::any::Any {
1334        self
1335    }
1336}
1337
1338#[cfg(test)]
1339mod reversed_tests {
1340    use super::*;
1341    use std::vec;
1342    use tests_helper::*;
1343
1344    #[track_caller]
1345    fn check_content(model: &ReverseModel<Rc<VecModel<i32>>>, expected: &[i32]) {
1346        assert_eq!(model.row_count(), expected.len());
1347        for (i, v) in expected.iter().enumerate() {
1348            assert_eq!(model.row_data(i), Some(*v), "Expected {v} at index {i}");
1349        }
1350    }
1351
1352    #[test]
1353    fn test_reversed_model() {
1354        let wrapped_rc = Rc::new(VecModel::from(vec![1, 2, 3, 4]));
1355        let model = Rc::new(ReverseModel::new(wrapped_rc.clone()));
1356        let _checker = ModelChecker::new(model.clone());
1357
1358        let observer = Box::pin(ModelChangeListenerContainer::<TestView>::default());
1359        model.model_tracker().attach_peer(Pin::as_ref(&observer).model_peer());
1360
1361        check_content(&model, &[4, 3, 2, 1]);
1362    }
1363
1364    #[test]
1365    fn test_reversed_model_insert() {
1366        for (idx, mapped_idx) in [(0, 4), (1, 3), (2, 2), (3, 1), (4, 0)] {
1367            std::println!("Inserting at {idx} expecting mapped to {mapped_idx}");
1368            let wrapped_rc = Rc::new(VecModel::from(vec![1, 2, 3, 4]));
1369            let model = Rc::new(ReverseModel::new(wrapped_rc.clone()));
1370            let _checker = ModelChecker::new(model.clone());
1371
1372            let observer = Box::pin(ModelChangeListenerContainer::<TestView>::default());
1373            model.model_tracker().attach_peer(Pin::as_ref(&observer).model_peer());
1374
1375            wrapped_rc.insert(idx, 10);
1376
1377            assert_eq!(observer.added_rows.borrow().len(), 1);
1378            assert!(
1379                observer.added_rows.borrow().eq(&[(mapped_idx, 1)]),
1380                "Added rows: {:?}",
1381                observer.added_rows.borrow()
1382            );
1383            assert!(observer.changed_rows.borrow().is_empty());
1384            assert!(observer.removed_rows.borrow().is_empty());
1385            assert_eq!(*observer.reset.borrow(), 0);
1386            assert_eq!(model.row_data(mapped_idx), Some(10));
1387        }
1388    }
1389
1390    #[test]
1391    fn test_reversed_model_remove() {
1392        for (idx, mapped_idx) in [(0, 3), (1, 2), (2, 1), (3, 0)] {
1393            std::println!("Removing at {idx} expecting mapped to {mapped_idx}");
1394            let wrapped_rc = Rc::new(VecModel::from(vec![1, 2, 3, 4]));
1395            let model = Rc::new(ReverseModel::new(wrapped_rc.clone()));
1396            let _checker = ModelChecker::new(model.clone());
1397
1398            let observer = Box::pin(ModelChangeListenerContainer::<TestView>::default());
1399            model.model_tracker().attach_peer(Pin::as_ref(&observer).model_peer());
1400
1401            wrapped_rc.remove(idx);
1402
1403            assert_eq!(observer.removed_rows.borrow().len(), 1);
1404            assert!(
1405                observer.removed_rows.borrow().eq(&[(mapped_idx, 1)]),
1406                "Remove rows: {:?}",
1407                observer.removed_rows.borrow()
1408            );
1409            assert!(observer.added_rows.borrow().is_empty());
1410            assert!(observer.changed_rows.borrow().is_empty());
1411            assert_eq!(*observer.reset.borrow(), 0);
1412        }
1413    }
1414
1415    #[test]
1416    fn test_reversed_model_changed() {
1417        for (idx, mapped_idx) in [(0, 3), (1, 2), (2, 1), (3, 0)] {
1418            std::println!("Changing at {idx} expecting mapped to {mapped_idx}");
1419            let wrapped_rc = Rc::new(VecModel::from(std::vec![1, 2, 3, 4]));
1420            let model = Rc::new(ReverseModel::new(wrapped_rc.clone()));
1421            let _checker = ModelChecker::new(model.clone());
1422
1423            let observer = Box::pin(ModelChangeListenerContainer::<TestView>::default());
1424            model.model_tracker().attach_peer(Pin::as_ref(&observer).model_peer());
1425
1426            wrapped_rc.set_row_data(idx, 10);
1427
1428            assert_eq!(observer.changed_rows.borrow().len(), 1);
1429            assert!(
1430                observer.changed_rows.borrow().eq(&[mapped_idx]),
1431                "Changed rows: {:?}",
1432                observer.changed_rows.borrow()
1433            );
1434            assert!(observer.added_rows.borrow().is_empty());
1435            assert!(observer.removed_rows.borrow().is_empty());
1436            assert_eq!(*observer.reset.borrow(), 0);
1437            assert_eq!(model.row_data(mapped_idx), Some(10));
1438        }
1439    }
1440
1441    #[test]
1442    fn test_reversed_model_source_model() {
1443        let wrapped_rc = Rc::new(VecModel::from(std::vec![1, 2, 3, 4]));
1444        let model = Rc::new(ReverseModel::new(wrapped_rc.clone()));
1445        let _checker = ModelChecker::new(model.clone());
1446
1447        let observer = Box::pin(ModelChangeListenerContainer::<TestView>::default());
1448        model.model_tracker().attach_peer(Pin::as_ref(&observer).model_peer());
1449
1450        model.source_model().push(5);
1451
1452        check_content(&model, &[5, 4, 3, 2, 1]);
1453    }
1454
1455    #[test]
1456    fn test_reversed_broken_model() {
1457        let wrapped_rc = BrokenModel::new(std::vec![Some("1"), Some("2"), None, Some("4")]);
1458        let model = Rc::new(ReverseModel::new(wrapped_rc.clone()));
1459
1460        wrapped_rc.notify.row_added(1, 3);
1461
1462        assert_eq!(model.row_count(), 4);
1463        assert_eq!(model.row_data(0), Some("4"));
1464        assert_eq!(model.row_data(1), None);
1465        assert_eq!(model.row_data(2), Some("2"));
1466        assert_eq!(model.row_data(3), Some("1"));
1467    }
1468}
1469
1470#[test]
1471fn test_long_chain_integrity() {
1472    use alloc::string::ToString;
1473    use tests_helper::*;
1474    let origin_model = Rc::new(VecModel::from((0..100).collect::<Vec<_>>()));
1475    let checker1 = ModelChecker::new(origin_model.clone());
1476    let fizzbuzz = Rc::new(MapModel::new(origin_model.clone(), |number| {
1477        if (number % 3) == 0 && (number % 5) == 0 {
1478            "FizzBuzz".to_string()
1479        } else if (number % 3) == 0 {
1480            "Fizz".to_string()
1481        } else if (number % 5) == 0 {
1482            "Buzz".to_string()
1483        } else {
1484            number.to_string()
1485        }
1486    }));
1487    let checker2 = ModelChecker::new(fizzbuzz.clone());
1488    let filter = Rc::new(FilterModel::new(fizzbuzz, |s| s != "FizzBuzz"));
1489    let checker3 = ModelChecker::new(filter.clone());
1490    let reverse = Rc::new(ReverseModel::new(filter));
1491    let checker4 = ModelChecker::new(reverse.clone());
1492    let sorted = Rc::new(SortModel::new_ascending(reverse));
1493    let checker5 = ModelChecker::new(sorted.clone());
1494    let filter2 = Rc::new(FilterModel::new(sorted, |s| s != "Fizz"));
1495    let checker6 = ModelChecker::new(filter2.clone());
1496
1497    let check_all = || {
1498        checker1.check();
1499        checker2.check();
1500        checker3.check();
1501        checker4.check();
1502        checker5.check();
1503        checker6.check();
1504    };
1505
1506    origin_model.extend(50..150);
1507    check_all();
1508    origin_model.insert(8, 1000);
1509    check_all();
1510    origin_model.remove(9);
1511    check_all();
1512    origin_model.remove(10);
1513    origin_model.remove(11);
1514    origin_model.set_row_data(55, 10001);
1515    check_all();
1516    origin_model.set_row_data(58, 10002);
1517    origin_model.set_row_data(59, 10003);
1518    origin_model.remove(28);
1519    origin_model.remove(29);
1520    origin_model.insert(100, 8888);
1521    origin_model.remove(30);
1522    origin_model.set_row_data(60, 10004);
1523    origin_model.remove(130);
1524    origin_model.set_row_data(61, 10005);
1525    origin_model.remove(131);
1526    check_all();
1527    origin_model.remove(12);
1528    origin_model.remove(13);
1529    origin_model.remove(14);
1530    origin_model.set_row_data(62, 10006);
1531    origin_model.set_row_data(63, 10007);
1532    origin_model.set_row_data(64, 10008);
1533    origin_model.set_row_data(65, 10009);
1534    check_all();
1535
1536    // Since VecModel don't have this as public API, just add some function that use row_removed on a wider range.
1537    trait RemoveRange {
1538        fn remove_range(&self, range: core::ops::Range<usize>);
1539    }
1540    impl<T> RemoveRange for VecModel<T> {
1541        fn remove_range(&self, range: core::ops::Range<usize>) {
1542            self.array.borrow_mut().drain(range.clone());
1543            self.notify.row_removed(range.start, range.len())
1544        }
1545    }
1546
1547    origin_model.remove_range(25..110);
1548    check_all();
1549
1550    origin_model.extend(900..910);
1551    origin_model.set_row_data(45, 44444);
1552    origin_model.remove_range(10..30);
1553    origin_model.insert(45, 3000);
1554    origin_model.insert(45, 3001);
1555    origin_model.insert(45, 3002);
1556    origin_model.insert(45, 3003);
1557    origin_model.insert(45, 3004);
1558    origin_model.insert(45, 3006);
1559    origin_model.insert(45, 3007);
1560    check_all();
1561}