Allow copy to clipboard
This commit is contained in:
parent
12edca1df1
commit
dca3f4c08d
5 changed files with 93 additions and 2 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -1091,6 +1091,7 @@ dependencies = [
|
||||||
"test-log",
|
"test-log",
|
||||||
"tokio",
|
"tokio",
|
||||||
"trash",
|
"trash",
|
||||||
|
"url",
|
||||||
"vergen",
|
"vergen",
|
||||||
"xdg",
|
"xdg",
|
||||||
"xdg-mime",
|
"xdg-mime",
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ tokio = { version = "1" }
|
||||||
trash = "3.2.0"
|
trash = "3.2.0"
|
||||||
xdg = { version = "2.5.2", optional = true }
|
xdg = { version = "2.5.2", optional = true }
|
||||||
xdg-mime = "0.3"
|
xdg-mime = "0.3"
|
||||||
|
url = "2.5"
|
||||||
# Internationalization
|
# Internationalization
|
||||||
i18n-embed = { version = "0.14", features = [
|
i18n-embed = { version = "0.14", features = [
|
||||||
"fluent-system",
|
"fluent-system",
|
||||||
|
|
|
||||||
18
src/app.rs
18
src/app.rs
|
|
@ -14,6 +14,7 @@ use cosmic::{
|
||||||
widget::scrollable,
|
widget::scrollable,
|
||||||
window, Alignment, Event, Length,
|
window, Alignment, Event, Length,
|
||||||
},
|
},
|
||||||
|
iced_runtime::clipboard,
|
||||||
style, theme,
|
style, theme,
|
||||||
widget::{
|
widget::{
|
||||||
self,
|
self,
|
||||||
|
|
@ -32,6 +33,7 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
clipboard::ClipboardContents,
|
||||||
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,
|
||||||
|
|
@ -787,8 +789,20 @@ impl Application for App {
|
||||||
return self.update_config();
|
return self.update_config();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::Copy(_entity_opt) => {
|
Message::Copy(entity_opt) => {
|
||||||
log::warn!("TODO: COPY");
|
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(&paths);
|
||||||
|
return clipboard::write_data(contents);
|
||||||
}
|
}
|
||||||
Message::Cut(_entity_opt) => {
|
Message::Cut(_entity_opt) => {
|
||||||
log::warn!("TODO: CUT");
|
log::warn!("TODO: CUT");
|
||||||
|
|
|
||||||
74
src/clipboard.rs
Normal file
74
src/clipboard.rs
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
// Copyright 2024 System76 <info@system76.com>
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
|
use cosmic::iced::clipboard::mime::AsMimeTypes;
|
||||||
|
use std::{borrow::Cow, path::Path};
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
pub struct ClipboardContents {
|
||||||
|
pub available: Cow<'static, [String]>,
|
||||||
|
pub text_plain: Cow<'static, [u8]>,
|
||||||
|
pub text_uri_list: Cow<'static, [u8]>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ClipboardContents {
|
||||||
|
pub fn new<P: AsRef<Path>>(paths: &[P]) -> Self {
|
||||||
|
let available = vec!["text/plain".to_string(), "text/uri-list".to_string()];
|
||||||
|
let mut text_plain = String::new();
|
||||||
|
let mut text_uri_list = String::new();
|
||||||
|
//TODO: do we have to use \r\n?
|
||||||
|
let newline = "\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);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TOOD: what if the path contains a newline?
|
||||||
|
text_plain.push_str(path_str);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
log::warn!(
|
||||||
|
"{:?} is not valid UTF-8, not adding to text/plain clipboard",
|
||||||
|
path
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match Url::from_file_path(path) {
|
||||||
|
Ok(url) => {
|
||||||
|
text_uri_list.push_str(&url.to_string());
|
||||||
|
text_uri_list.push_str(newline);
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
log::warn!(
|
||||||
|
"{:?} cannot be turned into a URL, not adding to text/uri-list clipboard: {}",
|
||||||
|
path, err
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Self {
|
||||||
|
available: Cow::from(available),
|
||||||
|
text_plain: Cow::from(text_plain.into_bytes()),
|
||||||
|
text_uri_list: Cow::from(text_uri_list.into_bytes()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsMimeTypes for ClipboardContents {
|
||||||
|
fn available(&self) -> Cow<'static, [String]> {
|
||||||
|
self.available.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_bytes(&self, mime_type: &str) -> Option<Cow<'static, [u8]>> {
|
||||||
|
match mime_type {
|
||||||
|
"text/plain" => Some(self.text_plain.clone()),
|
||||||
|
"text/uri-list" => Some(self.text_uri_list.clone()),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -10,6 +10,7 @@ use std::{path::PathBuf, process};
|
||||||
|
|
||||||
use app::{App, Flags};
|
use app::{App, Flags};
|
||||||
mod app;
|
mod app;
|
||||||
|
mod clipboard;
|
||||||
use config::{Config, CONFIG_VERSION};
|
use config::{Config, CONFIG_VERSION};
|
||||||
mod config;
|
mod config;
|
||||||
pub mod dialog;
|
pub mod dialog;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue