refactor sorting

This commit is contained in:
Dominic Gerhauser 2024-02-29 03:46:14 +01:00 committed by Jeremy Soller
parent d47002bb0d
commit 197398fe4e

View file

@ -542,15 +542,15 @@ pub struct Tab {
pub history_i: usize,
pub history: Vec<Location>,
pub config: TabConfig,
//TODO: this no longer needs to be a map
sort_map: HashMap<HeadingOptions, bool>,
sort_name: HeadingOptions,
sort_direction: bool,
}
impl Tab {
pub fn new(location: Location, config: TabConfig) -> Self {
let history = vec![location.clone()];
let mut sort_map = HashMap::new();
sort_map.insert(HeadingOptions::Name, true);
let sort_name = HeadingOptions::Name;
let sort_direction = true;
Self {
location,
context_menu: None,
@ -564,7 +564,8 @@ impl Tab {
history_i: 0,
history,
config,
sort_map,
sort_name,
sort_direction,
}
}
@ -840,69 +841,13 @@ impl Tab {
self.view = view;
}
Message::ToggleSort(heading_option) => {
let heading_sort = !self.sort_map.get(&heading_option).unwrap_or(&false);
self.sort_map.clear();
self.sort_map.insert(heading_option, heading_sort);
let check_reverse = |ord: Ordering, sort: bool| {
if sort {
ord
} else {
ord.reverse()
}
let heading_sort = if self.sort_name == heading_option {
!self.sort_direction
} else {
true
};
if let Some(item) = &mut self.items_opt {
match heading_option {
HeadingOptions::Size => {
item.sort_by(|a, b| {
// entries take precedence over size
let get_size = |x: &Item| match &x.metadata {
ItemMetadata::Path { metadata, children } => {
if metadata.is_dir() {
(true, *children as u64)
} else {
(false, metadata.len())
}
}
ItemMetadata::Trash { metadata, .. } => match metadata.size {
trash::TrashItemSize::Entries(entries) => {
(true, entries as u64)
}
trash::TrashItemSize::Bytes(bytes) => (false, bytes),
},
};
let (a_is_entry, a_size) = get_size(a);
let (b_is_entry, b_size) = get_size(b);
let ord = match (a_is_entry, b_is_entry) {
(true, false) => Ordering::Less,
(false, true) => Ordering::Greater,
_ => a_size.cmp(&b_size),
};
check_reverse(ord, heading_sort)
})
}
HeadingOptions::Name => item.sort_by(|a, b| {
let ord = match (a.path.is_dir(), b.path.is_dir()) {
(true, false) => Ordering::Less,
(false, true) => Ordering::Greater,
_ => lexical_sort::natural_lexical_cmp(&a.name, &b.name),
};
check_reverse(ord, heading_sort)
}),
HeadingOptions::Modified => {
item.sort_by(|a, b| {
let get_modified = |x: &Item| match &x.metadata {
ItemMetadata::Path { metadata, .. } => metadata.modified().ok(),
ItemMetadata::Trash { .. } => None,
};
let a = get_modified(a);
let b = get_modified(b);
check_reverse(a.cmp(&b), heading_sort)
});
}
}
}
self.sort_direction = heading_sort;
self.sort_name = heading_option;
}
}
if let Some(location) = cd {
@ -927,6 +872,68 @@ impl Tab {
commands
}
fn column_sort(&self) -> Option<Vec<Item>> {
let check_reverse = |ord: Ordering, sort: bool| {
if sort {
ord
} else {
ord.reverse()
}
};
let mut item = self.items_opt.clone()?;
let heading_sort = self.sort_direction;
match self.sort_name {
HeadingOptions::Size => {
item.sort_by(|a, b| {
// entries take precedence over size
let get_size = |x: &Item| match &x.metadata {
ItemMetadata::Path { metadata, children } => {
if metadata.is_dir() {
(true, *children as u64)
} else {
(false, metadata.len())
}
}
ItemMetadata::Trash { metadata, .. } => match metadata.size {
trash::TrashItemSize::Entries(entries) => (true, entries as u64),
trash::TrashItemSize::Bytes(bytes) => (false, bytes),
},
};
let (a_is_entry, a_size) = get_size(a);
let (b_is_entry, b_size) = get_size(b);
let ord = match (a_is_entry, b_is_entry) {
(true, false) => Ordering::Less,
(false, true) => Ordering::Greater,
_ => a_size.cmp(&b_size),
};
check_reverse(ord, heading_sort)
})
}
HeadingOptions::Name => item.sort_by(|a, b| {
let ord = match (a.path.is_dir(), b.path.is_dir()) {
(true, false) => Ordering::Less,
(false, true) => Ordering::Greater,
_ => lexical_sort::natural_lexical_cmp(&a.name, &b.name),
};
check_reverse(ord, heading_sort)
}),
HeadingOptions::Modified => {
item.sort_by(|a, b| {
let get_modified = |x: &Item| match &x.metadata {
ItemMetadata::Path { metadata, .. } => metadata.modified().ok(),
ItemMetadata::Trash { .. } => None,
};
let a = get_modified(a);
let b = get_modified(b);
check_reverse(a.cmp(&b), heading_sort)
});
}
}
Some(item)
}
pub fn location_view(&self, core: &Core) -> Element<Message> {
let cosmic_theme::Spacing {
space_xxxs,
@ -1168,11 +1175,13 @@ impl Tab {
($name: literal, $width: expr, $msg: expr) => {
widget::row::with_children(vec![
widget::text::heading(fl!($name)).into(),
widget::button(widget::icon::from_name(match self.sort_map.get(&$msg) {
Some(true) => "go-down-symbolic",
Some(false) => "go-up-symbolic",
None => "list-remove-symbolic",
}))
widget::button(widget::icon::from_name(
match (self.sort_name == $msg, self.sort_direction) {
(true, true) => "go-down-symbolic",
(true, false) => "go-up-symbolic",
_ => "list-remove-symbolic",
},
))
.on_press(Message::ToggleSort($msg))
.style(cosmic::style::Button::Icon)
.into(),
@ -1200,7 +1209,7 @@ impl Tab {
children.push(horizontal_rule(1).into());
if let Some(ref items) = self.items_opt {
if let Some(ref items) = self.column_sort() {
let mut count = 0;
let mut hidden = 0;
let TabConfig {