Implement cut, fill in x-special/gnome-copied-files mime

This commit is contained in:
Jeremy Soller 2024-03-20 08:53:08 -06:00
parent dca3f4c08d
commit 57fa0cdbc0
No known key found for this signature in database
GPG key ID: D02FD439211AF56F
2 changed files with 49 additions and 15 deletions

View file

@ -33,7 +33,7 @@ use std::{
}; };
use crate::{ use crate::{
clipboard::ClipboardContents, clipboard::{ClipboardContents, ClipboardKind},
config::{AppTheme, Config, IconSizes, TabConfig, CONFIG_VERSION}, config::{AppTheme, Config, IconSizes, TabConfig, CONFIG_VERSION},
fl, home_dir, fl, home_dir,
key_bind::key_binds, 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); return clipboard::write_data(contents);
} }
Message::Cut(_entity_opt) => { Message::Cut(entity_opt) => {
log::warn!("TODO: CUT"); 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::<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);
return clipboard::write_data(contents);
} }
Message::DialogCancel => { Message::DialogCancel => {
self.dialog_pages.pop_front(); self.dialog_pages.pop_front();

View file

@ -5,32 +5,47 @@ use cosmic::iced::clipboard::mime::AsMimeTypes;
use std::{borrow::Cow, path::Path}; use std::{borrow::Cow, path::Path};
use url::Url; use url::Url;
pub enum ClipboardKind {
Copy,
Cut,
}
pub struct ClipboardContents { pub struct ClipboardContents {
pub available: Cow<'static, [String]>, pub available: Cow<'static, [String]>,
pub text_plain: Cow<'static, [u8]>, pub text_plain: Cow<'static, [u8]>,
pub text_uri_list: Cow<'static, [u8]>, pub text_uri_list: Cow<'static, [u8]>,
pub x_special_gnome_copied_files: Cow<'static, [u8]>,
} }
impl ClipboardContents { impl ClipboardContents {
pub fn new<P: AsRef<Path>>(paths: &[P]) -> Self { pub fn new<P: AsRef<Path>>(kind: ClipboardKind, paths: &[P]) -> Self {
let available = vec!["text/plain".to_string(), "text/uri-list".to_string()]; 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_plain = String::new();
let mut text_uri_list = 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? //TODO: do we have to use \r\n?
let newline = "\r\n"; let cr_nl = "\r\n";
for path in paths.iter() { for path in paths.iter() {
let path = path.as_ref(); let path = path.as_ref();
match path.to_str() { match path.to_str() {
Some(path_str) => { Some(path_str) => {
if !text_plain.is_empty() { if !text_plain.is_empty() {
text_plain.push_str(newline); text_plain.push_str(cr_nl);
} }
//TOOD: what if the path contains CR or NL?
//TOOD: what if the path contains a newline?
text_plain.push_str(path_str); text_plain.push_str(path_str);
} }
None => { None => {
//TODO: allow non-UTF-8?
log::warn!( log::warn!(
"{:?} is not valid UTF-8, not adding to text/plain clipboard", "{:?} is not valid UTF-8, not adding to text/plain clipboard",
path path
@ -40,13 +55,18 @@ impl ClipboardContents {
match Url::from_file_path(path) { match Url::from_file_path(path) {
Ok(url) => { Ok(url) => {
text_uri_list.push_str(&url.to_string()); let url_str = url.to_string();
text_uri_list.push_str(newline);
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!( log::warn!(
"{:?} cannot be turned into a URL, not adding to text/uri-list clipboard: {}", "{:?} cannot be turned into a URL, not adding to text/uri-list clipboard",
path, err path
); );
} }
} }
@ -55,6 +75,7 @@ impl ClipboardContents {
available: Cow::from(available), available: Cow::from(available),
text_plain: Cow::from(text_plain.into_bytes()), text_plain: Cow::from(text_plain.into_bytes()),
text_uri_list: Cow::from(text_uri_list.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 { match mime_type {
"text/plain" => Some(self.text_plain.clone()), "text/plain" => Some(self.text_plain.clone()),
"text/uri-list" => Some(self.text_uri_list.clone()), "text/uri-list" => Some(self.text_uri_list.clone()),
"x-special/gnome-copied-files" => Some(self.x_special_gnome_copied_files.clone()),
_ => None, _ => None,
} }
} }