Parse pastes
This commit is contained in:
parent
3ab5597fc3
commit
a2560db6ba
2 changed files with 84 additions and 10 deletions
21
src/app.rs
21
src/app.rs
|
|
@ -33,7 +33,7 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
clipboard::{ClipboardContents, ClipboardKind},
|
clipboard::{ClipboardCopy, ClipboardKind, ClipboardPaste},
|
||||||
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,
|
||||||
|
|
@ -155,6 +155,7 @@ pub enum Message {
|
||||||
OpenTerminal(Option<Entity>),
|
OpenTerminal(Option<Entity>),
|
||||||
OpenWith(PathBuf, mime_app::MimeApp),
|
OpenWith(PathBuf, mime_app::MimeApp),
|
||||||
Paste(Option<Entity>),
|
Paste(Option<Entity>),
|
||||||
|
PasteContents(Option<Entity>, ClipboardPaste),
|
||||||
PendingComplete(u64),
|
PendingComplete(u64),
|
||||||
PendingError(u64, String),
|
PendingError(u64, String),
|
||||||
PendingProgress(u64, f32),
|
PendingProgress(u64, f32),
|
||||||
|
|
@ -808,12 +809,12 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
Message::Copy(entity_opt) => {
|
Message::Copy(entity_opt) => {
|
||||||
let paths = self.selected_paths(entity_opt);
|
let paths = self.selected_paths(entity_opt);
|
||||||
let contents = ClipboardContents::new(ClipboardKind::Copy, &paths);
|
let contents = ClipboardCopy::new(ClipboardKind::Copy, &paths);
|
||||||
return clipboard::write_data(contents);
|
return clipboard::write_data(contents);
|
||||||
}
|
}
|
||||||
Message::Cut(entity_opt) => {
|
Message::Cut(entity_opt) => {
|
||||||
let paths = self.selected_paths(entity_opt);
|
let paths = self.selected_paths(entity_opt);
|
||||||
let contents = ClipboardContents::new(ClipboardKind::Cut, &paths);
|
let contents = ClipboardCopy::new(ClipboardKind::Cut, &paths);
|
||||||
return clipboard::write_data(contents);
|
return clipboard::write_data(contents);
|
||||||
}
|
}
|
||||||
Message::DialogCancel => {
|
Message::DialogCancel => {
|
||||||
|
|
@ -990,8 +991,18 @@ impl Application for App {
|
||||||
// Close Open With context view
|
// Close Open With context view
|
||||||
self.core.window.show_context = false;
|
self.core.window.show_context = false;
|
||||||
}
|
}
|
||||||
Message::Paste(_entity_opt) => {
|
Message::Paste(entity_opt) => {
|
||||||
log::warn!("TODO: PASTE");
|
return clipboard::read_data::<ClipboardPaste, _>(move |contents_opt| {
|
||||||
|
match contents_opt {
|
||||||
|
Some(contents) => {
|
||||||
|
message::app(Message::PasteContents(entity_opt, contents))
|
||||||
|
}
|
||||||
|
None => message::none(),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Message::PasteContents(entity_opt, contents) => {
|
||||||
|
println!("{:?}", contents);
|
||||||
}
|
}
|
||||||
Message::PendingComplete(id) => {
|
Message::PendingComplete(id) => {
|
||||||
if let Some((op, _)) = self.pending_operations.remove(&id) {
|
if let Some((op, _)) = self.pending_operations.remove(&id) {
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,29 @@
|
||||||
// Copyright 2024 System76 <info@system76.com>
|
// Copyright 2024 System76 <info@system76.com>
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use cosmic::iced::clipboard::mime::AsMimeTypes;
|
use cosmic::iced::clipboard::mime::{AllowedMimeTypes, AsMimeTypes};
|
||||||
use std::{borrow::Cow, path::Path};
|
use std::{
|
||||||
|
borrow::Cow,
|
||||||
|
error::Error,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
str,
|
||||||
|
};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub enum ClipboardKind {
|
pub enum ClipboardKind {
|
||||||
Copy,
|
Copy,
|
||||||
Cut,
|
Cut,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ClipboardContents {
|
pub struct ClipboardCopy {
|
||||||
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]>,
|
pub x_special_gnome_copied_files: Cow<'static, [u8]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClipboardContents {
|
impl ClipboardCopy {
|
||||||
pub fn new<P: AsRef<Path>>(kind: ClipboardKind, paths: &[P]) -> Self {
|
pub fn new<P: AsRef<Path>>(kind: ClipboardKind, paths: &[P]) -> Self {
|
||||||
let available = vec![
|
let available = vec![
|
||||||
"text/plain".to_string(),
|
"text/plain".to_string(),
|
||||||
|
|
@ -80,7 +86,7 @@ impl ClipboardContents {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsMimeTypes for ClipboardContents {
|
impl AsMimeTypes for ClipboardCopy {
|
||||||
fn available(&self) -> Cow<'static, [String]> {
|
fn available(&self) -> Cow<'static, [String]> {
|
||||||
self.available.clone()
|
self.available.clone()
|
||||||
}
|
}
|
||||||
|
|
@ -94,3 +100,60 @@ impl AsMimeTypes for ClipboardContents {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct ClipboardPaste {
|
||||||
|
pub kind: ClipboardKind,
|
||||||
|
pub paths: Vec<PathBuf>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AllowedMimeTypes for ClipboardPaste {
|
||||||
|
fn allowed() -> Cow<'static, [String]> {
|
||||||
|
Cow::from(vec![
|
||||||
|
"x-special/gnome-copied-files".to_string(),
|
||||||
|
"text/uri-list".to_string(),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<(Vec<u8>, String)> for ClipboardPaste {
|
||||||
|
type Error = Box<dyn Error>;
|
||||||
|
fn try_from(value: (Vec<u8>, String)) -> Result<Self, Self::Error> {
|
||||||
|
let (data, mime) = value;
|
||||||
|
// Assume the kind is Copy if not provided by the mime type
|
||||||
|
let mut kind = ClipboardKind::Copy;
|
||||||
|
let mut paths = Vec::new();
|
||||||
|
match mime.as_str() {
|
||||||
|
"text/uri-list" => {
|
||||||
|
let text = str::from_utf8(&data)?;
|
||||||
|
for line in text.lines() {
|
||||||
|
let url = Url::parse(line)?;
|
||||||
|
match url.to_file_path() {
|
||||||
|
Ok(path) => paths.push(path),
|
||||||
|
Err(()) => Err(format!("invalid file URL {:?}", url))?,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"x-special/gnome-copied-files" => {
|
||||||
|
let text = str::from_utf8(&data)?;
|
||||||
|
for (i, line) in text.lines().enumerate() {
|
||||||
|
if i == 0 {
|
||||||
|
kind = match line {
|
||||||
|
"copy" => ClipboardKind::Copy,
|
||||||
|
"cut" => ClipboardKind::Cut,
|
||||||
|
_ => Err(format!("unsupported clipboard operation {:?}", line))?,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
let url = Url::parse(line)?;
|
||||||
|
match url.to_file_path() {
|
||||||
|
Ok(path) => paths.push(path),
|
||||||
|
Err(()) => Err(format!("invalid file URL {:?}", url))?,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => Err(format!("unsupported mime type {:?}", mime))?,
|
||||||
|
}
|
||||||
|
Ok(Self { kind, paths })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue