diff --git a/src/app.rs b/src/app.rs index bf1a151..2931c79 100644 --- a/src/app.rs +++ b/src/app.rs @@ -428,7 +428,7 @@ impl App { let mut children = Vec::new(); let entity = self.tab_model.active(); if let Some(tab) = self.tab_model.data::(entity) { - if let Some(ref items) = tab.items_opt { + if let Some(items) = tab.items_opt() { for item in items.iter() { if item.selected { children.push(item.property_view(tab.config.icon_sizes)); @@ -672,17 +672,8 @@ impl Application for App { return Command::none(); } - if let Some(ref mut items) = tab.items_opt { - let mut had_selection = false; - for item in items.iter_mut() { - if item.selected { - item.selected = false; - had_selection = true; - } - } - if had_selection { - return Command::none(); - } + if tab.select_none() { + return Command::none(); } } self.core.window.show_context = false; @@ -804,8 +795,8 @@ impl Application for App { let mut paths = Vec::new(); let entity = entity_opt.unwrap_or_else(|| self.tab_model.active()); if let Some(tab) = self.tab_model.data_mut::(entity) { - if let Some(ref mut items) = tab.items_opt { - for item in items.iter_mut() { + if let Some(ref items) = tab.items_opt() { + for item in items.iter() { if item.selected { paths.push(item.path.clone()); } @@ -894,7 +885,7 @@ impl Application for App { let entity = entity_opt.unwrap_or_else(|| self.tab_model.active()); if let Some(tab) = self.tab_model.data_mut::(entity) { if let Location::Path(parent) = &tab.location { - if let Some(items) = &tab.items_opt { + if let Some(items) = tab.items_opt() { let mut selected = Vec::new(); for item in items.iter() { if item.selected { @@ -926,8 +917,8 @@ impl Application for App { let mut paths = Vec::new(); let entity = entity_opt.unwrap_or_else(|| self.tab_model.active()); if let Some(tab) = self.tab_model.data_mut::(entity) { - if let Some(ref mut items) = tab.items_opt { - for item in items.iter_mut() { + if let Some(items) = tab.items_opt() { + for item in items.iter() { if item.selected { match &item.metadata { ItemMetadata::Trash { entry, .. } => { @@ -948,15 +939,7 @@ impl Application for App { Message::SelectAll(entity_opt) => { let entity = entity_opt.unwrap_or_else(|| self.tab_model.active()); if let Some(tab) = self.tab_model.data_mut::(entity) { - if let Some(ref mut items) = tab.items_opt { - for item in items.iter_mut() { - if !tab.config.show_hidden && item.hidden { - continue; - } - item.selected = true; - item.click_time = None; - } - } + tab.select_all(); } } Message::SystemThemeModeChange(_theme_mode) => { @@ -1093,7 +1076,7 @@ impl Application for App { } Message::TabRescan(entity, items) => match self.tab_model.data_mut::(entity) { Some(tab) => { - tab.items_opt = Some(items); + tab.set_items(items); } _ => (), }, @@ -1680,13 +1663,10 @@ pub(crate) mod test_utils { let location = Location::Path(path.to_owned()); let items = location.scan(IconSizes::default()); let mut tab = Tab::new(location, TabConfig::default()); - tab.items_opt = Some(items); + tab.set_items(items); // Ensure correct number of directories as a sanity check - let items = tab - .items_opt - .as_deref() - .expect("tab should be populated with Items"); + let items = tab.items_opt().expect("tab should be populated with Items"); assert_eq!(NUM_DIRS, items.len()); Ok((fs, tab)) @@ -1748,17 +1728,14 @@ pub(crate) mod test_utils { // Check lengths. // `items_opt` is optional and the directory at `path` may have zero entries // Therefore, this doesn't panic if `items_opt` is None - let items_len = tab - .items_opt - .as_ref() - .map(|items| items.len()) - .unwrap_or_default(); + let items_len = tab.items_opt().map(|items| items.len()).unwrap_or_default(); assert_eq!(entries.len(), items_len); + let empty = Vec::new(); assert!( entries .into_iter() - .zip(tab.items_opt.clone().unwrap_or_default()) + .zip(tab.items_opt().clone().unwrap_or(&empty)) .all(|(a, b)| eq_path_item(&a, &b)), "Path ({}) and Tab path ({}) don't have equal contents", path.display(), diff --git a/src/dialog.rs b/src/dialog.rs index 57e7bc2..c76d34a 100644 --- a/src/dialog.rs +++ b/src/dialog.rs @@ -451,7 +451,7 @@ impl Application for App { } // Select based on filename - if let Some(items) = &mut self.tab.items_opt { + if let Some(items) = self.tab.items_opt_mut() { for item in items.iter_mut() { item.selected = item.name == new_filename; } @@ -488,8 +488,8 @@ impl Application for App { }, Message::Open => { let mut paths = Vec::new(); - if let Some(ref mut items) = self.tab.items_opt { - for item in items.iter_mut() { + if let Some(items) = self.tab.items_opt() { + for item in items.iter() { if item.selected { paths.push(item.path.clone()); } @@ -563,7 +563,7 @@ impl Application for App { // Update filename box when anything is selected if let DialogKind::SaveFile { filename } = &mut self.flags.kind { if let Some(click_i) = click_i_opt { - if let Some(items) = &self.tab.items_opt { + if let Some(items) = self.tab.items_opt() { if let Some(item) = items.get(click_i) { if item.selected && !item.path.is_dir() { *filename = item.name.clone(); @@ -605,7 +605,7 @@ impl Application for App { } } - self.tab.items_opt = Some(items); + self.tab.set_items(items); // Reset focus on location change return widget::text_input::focus(self.filename_id.clone()); diff --git a/src/menu.rs b/src/menu.rs index bfe02c3..e71fddc 100644 --- a/src/menu.rs +++ b/src/menu.rs @@ -58,8 +58,7 @@ pub fn context_menu<'a>( }; let selected = tab - .items_opt - .as_ref() + .items_opt() .map_or(0, |items| items.iter().filter(|x| x.selected).count()); let mut children: Vec> = Vec::new(); diff --git a/src/tab.rs b/src/tab.rs index 9ca3f83..de497f5 100644 --- a/src/tab.rs +++ b/src/tab.rs @@ -552,7 +552,6 @@ pub enum HeadingOptions { pub struct Tab { pub location: Location, pub context_menu: Option, - pub items_opt: Option>, pub view: View, pub dialog: Option, pub scroll_opt: Option, @@ -562,6 +561,7 @@ pub struct Tab { pub history_i: usize, pub history: Vec, pub config: TabConfig, + items_opt: Option>, sort_name: HeadingOptions, sort_direction: bool, } @@ -574,7 +574,6 @@ impl Tab { Self { location, context_menu: None, - items_opt: None, view: View::Grid, dialog: None, scroll_opt: None, @@ -584,6 +583,7 @@ impl Tab { history_i: 0, history, config, + items_opt: None, sort_name, sort_direction, } @@ -601,6 +601,44 @@ impl Tab { } } + pub fn items_opt(&self) -> Option<&Vec> { + self.items_opt.as_ref() + } + + pub fn items_opt_mut(&mut self) -> Option<&mut Vec> { + self.items_opt.as_mut() + } + + pub fn set_items(&mut self, items: Vec) { + self.items_opt = Some(items); + } + + pub fn select_all(&mut self) { + if let Some(ref mut items) = self.items_opt { + for item in items.iter_mut() { + if !self.config.show_hidden && item.hidden { + item.selected = false; + continue; + } + item.selected = true; + item.click_time = None; + } + } + } + + pub fn select_none(&mut self) -> bool { + let mut had_selection = false; + if let Some(ref mut items) = self.items_opt { + for item in items.iter_mut() { + if item.selected { + item.selected = false; + had_selection = true; + } + } + } + had_selection + } + fn select_by_drag(&mut self, rect: Rectangle) { let items = match &mut self.items_opt { Some(some) => some,