1use 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#[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 pub fn out_of_bounds(row_count: usize) -> Self {
44 Self(ErrorImpl::OutOfBounds(row_count))
45 }
46
47 pub fn unsupported(model: &(impl Model + ?Sized)) -> Self {
49 Self(ErrorImpl::Unsupported(core::any::type_name_of_val(model).into()))
50 }
51
52 #[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
66pub trait ModelTracker {
70 fn attach_peer(&self, peer: ModelPeer);
72 fn track_row_count_changes(&self);
75 fn track_row_data_changes(&self, row: usize);
78
79 #[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
107pub trait Model {
176 type Data;
178 fn row_count(&self) -> usize;
180 fn row_data(&self, row: usize) -> Option<Self::Data>;
187 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 fn push_row(&self, data: Self::Data) -> Result<(), ModelError> {
210 self.insert_row(self.row_count(), data)
211 }
212
213 fn remove_row(&self, _row: usize) -> Result<(), ModelError> {
223 Err(ModelError::unsupported(self))
224 }
225
226 fn insert_row(&self, _row: usize, _data: Self::Data) -> Result<(), ModelError> {
234 Err(ModelError::unsupported(self))
235 }
236
237 fn model_tracker(&self) -> &dyn ModelTracker;
241
242 fn iter(&self) -> ModelIterator<'_, Self::Data>
244 where
245 Self: Sized,
246 {
247 ModelIterator::new(self)
248 }
249
250 fn as_any(&self) -> &dyn core::any::Any {
317 &()
318 }
319}
320
321pub trait ModelExt: Model {
323 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 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 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 #[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 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 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#[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 (0..row_count).all(|index| model.row_data(index).is_none_or(&mut predicate))
418}
419
420pub 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
433pub struct ModelIterator<'a, T> {
436 model: &'a dyn Model<Data = T>,
437 row: usize,
438}
439
440impl<'a, T> ModelIterator<'a, T> {
441 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
505pub 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 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 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 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 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 pub fn set_vec(&self, new: impl Into<Vec<T>>) {
550 *self.array.borrow_mut() = new.into();
551 self.notify.reset();
552 }
553
554 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 pub fn clear(&self) {
570 self.array.borrow_mut().clear();
571 self.notify.reset();
572 }
573
574 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 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#[derive(Default)]
657pub struct SharedVectorModel<T> {
658 array: RefCell<SharedVector<T>>,
659 notify: ModelNotify,
660}
661
662impl<T: Clone + 'static> SharedVectorModel<T> {
663 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 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
766pub 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 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 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 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 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 handle.model_tracker().track_row_data_changes(0);
1192 model.set_row_data(0, 100);
1193 assert!(!tracker.is_dirty());
1194
1195 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 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 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 #[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 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 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 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 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 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}