diff --git a/src/app.rs b/src/app.rs index 7da62a7..a3054b8 100644 --- a/src/app.rs +++ b/src/app.rs @@ -33,7 +33,7 @@ use std::{ }; use crate::{ - clipboard::ClipboardContents, + clipboard::{ClipboardContents, ClipboardKind}, config::{AppTheme, Config, IconSizes, TabConfig, CONFIG_VERSION}, fl, home_dir, key_bind::key_binds, @@ -801,11 +801,23 @@ impl Application for App { } } } - let contents = ClipboardContents::new(&paths); + let contents = ClipboardContents::new(ClipboardKind::Copy, &paths); return clipboard::write_data(contents); } - Message::Cut(_entity_opt) => { - log::warn!("TODO: CUT"); + Message::Cut(entity_opt) => { + 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 items) = tab.items_opt() { + for item in items.iter() { + if item.selected { + paths.push(item.path.clone()); + } + } + } + } + let contents = ClipboardContents::new(ClipboardKind::Cut, &paths); + return clipboard::write_data(contents); } Message::DialogCancel => { self.dialog_pages.pop_front(); diff --git a/src/clipboard.rs b/src/clipboard.rs index 94d0ea6..43844a6 100644 --- a/src/clipboard.rs +++ b/src/clipboard.rs @@ -5,32 +5,47 @@ use cosmic::iced::clipboard::mime::AsMimeTypes; use std::{borrow::Cow, path::Path}; use url::Url; +pub enum ClipboardKind { + Copy, + Cut, +} + pub struct ClipboardContents { pub available: Cow<'static, [String]>, pub text_plain: Cow<'static, [u8]>, pub text_uri_list: Cow<'static, [u8]>, + pub x_special_gnome_copied_files: Cow<'static, [u8]>, } impl ClipboardContents { - pub fn new>(paths: &[P]) -> Self { - let available = vec!["text/plain".to_string(), "text/uri-list".to_string()]; + pub fn new>(kind: ClipboardKind, paths: &[P]) -> Self { + let available = vec![ + "text/plain".to_string(), + "text/uri-list".to_string(), + "x-special/gnome-copied-files".to_string(), + ]; let mut text_plain = String::new(); let mut text_uri_list = String::new(); + let mut x_special_gnome_copied_files = match kind { + ClipboardKind::Copy => "copy", + ClipboardKind::Cut => "cut", + } + .to_string(); //TODO: do we have to use \r\n? - let newline = "\r\n"; + let cr_nl = "\r\n"; for path in paths.iter() { let path = path.as_ref(); match path.to_str() { Some(path_str) => { if !text_plain.is_empty() { - text_plain.push_str(newline); + text_plain.push_str(cr_nl); } - - //TOOD: what if the path contains a newline? + //TOOD: what if the path contains CR or NL? text_plain.push_str(path_str); } None => { + //TODO: allow non-UTF-8? log::warn!( "{:?} is not valid UTF-8, not adding to text/plain clipboard", path @@ -40,13 +55,18 @@ impl ClipboardContents { match Url::from_file_path(path) { Ok(url) => { - text_uri_list.push_str(&url.to_string()); - text_uri_list.push_str(newline); + let url_str = url.to_string(); + + text_uri_list.push_str(&url_str); + text_uri_list.push_str(cr_nl); + + x_special_gnome_copied_files.push('\n'); + x_special_gnome_copied_files.push_str(&url_str); } - Err(err) => { + Err(()) => { log::warn!( - "{:?} cannot be turned into a URL, not adding to text/uri-list clipboard: {}", - path, err + "{:?} cannot be turned into a URL, not adding to text/uri-list clipboard", + path ); } } @@ -55,6 +75,7 @@ impl ClipboardContents { available: Cow::from(available), text_plain: Cow::from(text_plain.into_bytes()), text_uri_list: Cow::from(text_uri_list.into_bytes()), + x_special_gnome_copied_files: Cow::from(x_special_gnome_copied_files.into_bytes()), } } } @@ -68,6 +89,7 @@ impl AsMimeTypes for ClipboardContents { match mime_type { "text/plain" => Some(self.text_plain.clone()), "text/uri-list" => Some(self.text_uri_list.clone()), + "x-special/gnome-copied-files" => Some(self.x_special_gnome_copied_files.clone()), _ => None, } }