Do not give trash items a path

This commit is contained in:
Jeremy Soller 2024-03-20 09:56:54 -06:00
parent 57fa0cdbc0
commit 94dd1b04d5
No known key found for this signature in database
GPG key ID: D02FD439211AF56F
3 changed files with 139 additions and 137 deletions

View file

@ -307,6 +307,23 @@ impl App {
Command::batch(commands) Command::batch(commands)
} }
fn selected_paths(&self, entity_opt: Option<Entity>) -> Vec<PathBuf> {
let mut paths = Vec::new();
let entity = entity_opt.unwrap_or_else(|| self.tab_model.active());
if let Some(tab) = self.tab_model.data::<Tab>(entity) {
if let Some(ref items) = tab.items_opt() {
for item in items.iter() {
if item.selected {
if let Some(path) = &item.path_opt {
paths.push(path.clone());
}
}
}
}
}
paths
}
fn update_config(&mut self) -> Command<Message> { fn update_config(&mut self) -> Command<Message> {
cosmic::app::command::set_theme(self.config.app_theme.theme()) cosmic::app::command::set_theme(self.config.app_theme.theme())
} }
@ -790,32 +807,12 @@ impl Application for App {
} }
} }
Message::Copy(entity_opt) => { Message::Copy(entity_opt) => {
let mut paths = Vec::new(); let paths = self.selected_paths(entity_opt);
let entity = entity_opt.unwrap_or_else(|| self.tab_model.active());
if let Some(tab) = self.tab_model.data_mut::<Tab>(entity) {
if let Some(ref items) = tab.items_opt() {
for item in items.iter() {
if item.selected {
paths.push(item.path.clone());
}
}
}
}
let contents = ClipboardContents::new(ClipboardKind::Copy, &paths); let contents = ClipboardContents::new(ClipboardKind::Copy, &paths);
return clipboard::write_data(contents); return clipboard::write_data(contents);
} }
Message::Cut(entity_opt) => { Message::Cut(entity_opt) => {
let mut paths = Vec::new(); let paths = self.selected_paths(entity_opt);
let entity = entity_opt.unwrap_or_else(|| self.tab_model.active());
if let Some(tab) = self.tab_model.data_mut::<Tab>(entity) {
if let Some(ref items) = tab.items_opt() {
for item in items.iter() {
if item.selected {
paths.push(item.path.clone());
}
}
}
}
let contents = ClipboardContents::new(ClipboardKind::Cut, &paths); let contents = ClipboardContents::new(ClipboardKind::Cut, &paths);
return clipboard::write_data(contents); return clipboard::write_data(contents);
} }
@ -882,17 +879,7 @@ impl Application for App {
self.modifiers = modifiers; self.modifiers = modifiers;
} }
Message::MoveToTrash(entity_opt) => { Message::MoveToTrash(entity_opt) => {
let mut paths = Vec::new(); let paths = self.selected_paths(entity_opt);
let entity = entity_opt.unwrap_or_else(|| self.tab_model.active());
if let Some(tab) = self.tab_model.data_mut::<Tab>(entity) {
if let Some(ref items) = tab.items_opt() {
for item in items.iter() {
if item.selected {
paths.push(item.path.clone());
}
}
}
}
if !paths.is_empty() { if !paths.is_empty() {
self.operation(Operation::Delete { paths }); self.operation(Operation::Delete { paths });
} }
@ -957,7 +944,9 @@ impl Application for App {
if let Some(items) = tab.items_opt() { if let Some(items) = tab.items_opt() {
for item in items.iter() { for item in items.iter() {
if item.selected { if item.selected {
paths.push(item.path.clone()); if let Some(path) = &item.path_opt {
paths.push(path.clone());
}
} }
} }
} }
@ -1032,7 +1021,9 @@ impl Application for App {
let mut selected = Vec::new(); let mut selected = Vec::new();
for item in items.iter() { for item in items.iter() {
if item.selected { if item.selected {
selected.push(item.path.clone()); if let Some(path) = &item.path_opt {
selected.push(path.clone());
}
} }
} }
if !selected.is_empty() { if !selected.is_empty() {

View file

@ -471,7 +471,9 @@ impl Application for App {
if let Some(items) = self.tab.items_opt() { if let Some(items) = self.tab.items_opt() {
for item in items.iter() { for item in items.iter() {
if item.selected { if item.selected {
paths.push(item.path.clone()); if let Some(path) = &item.path_opt {
paths.push(path.clone());
}
} }
} }
} }
@ -545,7 +547,7 @@ impl Application for App {
if let Some(click_i) = click_i_opt { 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 let Some(item) = items.get(click_i) {
if item.selected && !item.path.is_dir() { if item.selected && !item.metadata.is_dir() {
*filename = item.name.clone(); *filename = item.name.clone();
} }
} }

View file

@ -271,7 +271,7 @@ pub fn scan_path(tab_path: &PathBuf, sizes: IconSizes) -> Vec<Item> {
name, name,
metadata: ItemMetadata::Path { metadata, children }, metadata: ItemMetadata::Path { metadata, children },
hidden, hidden,
path, path_opt: Some(path),
mime, mime,
icon_handle_grid, icon_handle_grid,
icon_handle_list, icon_handle_list,
@ -336,7 +336,7 @@ pub fn scan_trash(sizes: IconSizes) -> Vec<Item> {
} }
}; };
let path = entry.original_path(); let original_path = entry.original_path();
let name = entry.name.clone(); let name = entry.name.clone();
let (mime, icon_handle_grid, icon_handle_list, icon_handle_list_condensed) = let (mime, icon_handle_grid, icon_handle_list, icon_handle_list_condensed) =
@ -344,12 +344,13 @@ pub fn scan_trash(sizes: IconSizes) -> Vec<Item> {
trash::TrashItemSize::Entries(_) => ( trash::TrashItemSize::Entries(_) => (
//TODO: make this a static //TODO: make this a static
"inode/directory".parse().unwrap(), "inode/directory".parse().unwrap(),
folder_icon(&path, sizes.grid()), folder_icon(&original_path, sizes.grid()),
folder_icon(&path, sizes.list()), folder_icon(&original_path, sizes.list()),
folder_icon(&path, sizes.list_condensed()), folder_icon(&original_path, sizes.list_condensed()),
), ),
trash::TrashItemSize::Bytes(_) => { trash::TrashItemSize::Bytes(_) => {
let mime = mime_for_path(&path); //TODO: do not use original path
let mime = mime_for_path(&original_path);
( (
mime.clone(), mime.clone(),
mime_icon(mime.clone(), sizes.grid()), mime_icon(mime.clone(), sizes.grid()),
@ -363,7 +364,7 @@ pub fn scan_trash(sizes: IconSizes) -> Vec<Item> {
name, name,
metadata: ItemMetadata::Trash { metadata, entry }, metadata: ItemMetadata::Trash { metadata, entry },
hidden: false, hidden: false,
path, path_opt: None,
mime, mime,
icon_handle_grid, icon_handle_grid,
icon_handle_list, icon_handle_list,
@ -478,7 +479,7 @@ pub struct Item {
pub name: String, pub name: String,
pub metadata: ItemMetadata, pub metadata: ItemMetadata,
pub hidden: bool, pub hidden: bool,
pub path: PathBuf, pub path_opt: Option<PathBuf>,
pub mime: Mime, pub mime: Mime,
pub icon_handle_grid: widget::icon::Handle, pub icon_handle_grid: widget::icon::Handle,
pub icon_handle_list: widget::icon::Handle, pub icon_handle_list: widget::icon::Handle,
@ -495,21 +496,32 @@ pub struct Item {
impl Item { impl Item {
fn preview(&self, sizes: IconSizes) -> Element<app::Message> { fn preview(&self, sizes: IconSizes) -> Element<app::Message> {
// This loads the image only if thumbnailing worked // This loads the image only if thumbnailing worked
let icon = widget::icon::icon(self.icon_handle_grid.clone())
.content_fit(ContentFit::Contain)
.size(sizes.grid())
.into();
match self match self
.thumbnail_opt .thumbnail_opt
.as_ref() .as_ref()
.unwrap_or(&ItemThumbnail::NotImage) .unwrap_or(&ItemThumbnail::NotImage)
{ {
ItemThumbnail::NotImage => widget::icon::icon(self.icon_handle_grid.clone()) ItemThumbnail::NotImage => icon,
.content_fit(ContentFit::Contain)
.size(sizes.grid())
.into(),
ItemThumbnail::Rgba(_) => { ItemThumbnail::Rgba(_) => {
widget::image::viewer(widget::image::Handle::from_path(&self.path)) if let Some(path) = &self.path_opt {
widget::image::viewer(widget::image::Handle::from_path(path))
.min_scale(1.0) .min_scale(1.0)
.into() .into()
} else {
icon
}
}
ItemThumbnail::Svg => {
if let Some(path) = &self.path_opt {
widget::Svg::from_path(path).into()
} else {
icon
}
} }
ItemThumbnail::Svg => widget::Svg::from_path(&self.path).into(),
} }
} }
@ -532,6 +544,7 @@ impl Item {
column = column.push(widget::text(format!("Type: {}", self.mime))); column = column.push(widget::text(format!("Type: {}", self.mime)));
if let Some(path) = &self.path_opt {
for app in self.open_with.iter() { for app in self.open_with.iter() {
column = column.push( column = column.push(
widget::button( widget::button(
@ -546,11 +559,12 @@ impl Item {
.spacing(space_xs), .spacing(space_xs),
) )
//TODO: do not clone so much? //TODO: do not clone so much?
.on_press(app::Message::OpenWith(self.path.clone(), app.clone())) .on_press(app::Message::OpenWith(path.clone(), app.clone()))
.padding(space_xs) .padding(space_xs)
.width(Length::Fill), .width(Length::Fill),
); );
} }
}
column.into() column.into()
} }
@ -928,7 +942,7 @@ impl Tab {
if Some(i) == click_i_opt { if Some(i) == click_i_opt {
// Filter out selection if it does not match dialog kind // Filter out selection if it does not match dialog kind
if let Some(dialog) = &self.dialog { if let Some(dialog) = &self.dialog {
let item_is_dir = item.path.is_dir(); let item_is_dir = item.metadata.is_dir();
if item_is_dir != dialog.is_dir() { if item_is_dir != dialog.is_dir() {
// Allow selecting folder if dialog is for files to make it // Allow selecting folder if dialog is for files to make it
// possible to double click // possible to double click
@ -941,21 +955,18 @@ impl Tab {
item.selected = true; item.selected = true;
if let Some(click_time) = item.click_time { if let Some(click_time) = item.click_time {
if click_time.elapsed() < DOUBLE_CLICK_DURATION { if click_time.elapsed() < DOUBLE_CLICK_DURATION {
match self.location { if let Some(path) = &item.path_opt {
Location::Path(_) => { if path.is_dir() {
if item.path.is_dir() {
//TODO: allow opening multiple tabs? //TODO: allow opening multiple tabs?
cd = Some(Location::Path(item.path.clone())); cd = Some(Location::Path(path.clone()));
} else { } else {
commands.push(Command::OpenFile(item.path.clone())); commands.push(Command::OpenFile(path.clone()));
} }
} } else {
Location::Trash => {
//TODO: open properties? //TODO: open properties?
} }
} }
} }
}
//TODO: prevent triple-click and beyond from opening file? //TODO: prevent triple-click and beyond from opening file?
item.click_time = Some(Instant::now()); item.click_time = Some(Instant::now());
} else if mod_ctrl { } else if mod_ctrl {
@ -1148,23 +1159,20 @@ impl Tab {
if let Some(ref mut items) = self.items_opt { if let Some(ref mut items) = self.items_opt {
for item in items.iter() { for item in items.iter() {
if item.selected { if item.selected {
match self.location { if let Some(path) = &item.path_opt {
Location::Path(_) => { if path.is_dir() {
if item.path.is_dir() {
//TODO: allow opening multiple tabs? //TODO: allow opening multiple tabs?
cd = Some(Location::Path(item.path.clone())); cd = Some(Location::Path(path.clone()));
} else { } else {
commands.push(Command::OpenFile(item.path.clone())); commands.push(Command::OpenFile(path.clone()));
} }
} } else {
Location::Trash => {
//TODO: open properties? //TODO: open properties?
} }
} }
} }
} }
} }
}
Message::Resize(size) => { Message::Resize(size) => {
self.size_opt = Some(size); self.size_opt = Some(size);
} }
@ -1198,7 +1206,7 @@ impl Tab {
Message::Thumbnail(path, thumbnail) => { Message::Thumbnail(path, thumbnail) => {
if let Some(ref mut items) = self.items_opt { if let Some(ref mut items) = self.items_opt {
for item in items.iter_mut() { for item in items.iter_mut() {
if item.path == path { if item.path_opt.as_ref() == Some(&path) {
if let ItemThumbnail::Rgba(rgba) = &thumbnail { if let ItemThumbnail::Rgba(rgba) = &thumbnail {
//TODO: pass handles already generated to avoid blocking main thread //TODO: pass handles already generated to avoid blocking main thread
let handle = widget::icon::from_raster_pixels( let handle = widget::icon::from_raster_pixels(
@ -1299,7 +1307,7 @@ impl Tab {
}) })
} }
HeadingOptions::Name => items.sort_by(|a, b| { HeadingOptions::Name => items.sort_by(|a, b| {
let ord = match (a.1.path.is_dir(), b.1.path.is_dir()) { let ord = match (a.1.metadata.is_dir(), b.1.metadata.is_dir()) {
(true, false) => Ordering::Less, (true, false) => Ordering::Less,
(false, true) => Ordering::Greater, (false, true) => Ordering::Greater,
_ => lexical_sort::natural_lexical_cmp(&a.1.name, &b.1.name), _ => lexical_sort::natural_lexical_cmp(&a.1.name, &b.1.name),
@ -1904,7 +1912,7 @@ impl Tab {
} }
} }
let path = item.path.clone(); if let Some(path) = item.path_opt.clone() {
subscriptions.push(subscription::channel( subscriptions.push(subscription::channel(
path.clone(), path.clone(),
1, 1,
@ -1950,6 +1958,7 @@ impl Tab {
} }
}, },
)); ));
}
if subscriptions.len() >= jobs { if subscriptions.len() >= jobs {
break; break;