Compare commits
4 changed files with 10 additions and 186 deletions
85
Cargo.lock
generated
85
Cargo.lock
generated
|
|
@ -136,27 +136,6 @@ version = "1.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1"
|
checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "arboard"
|
|
||||||
version = "3.6.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0348a1c054491f4bfe6ab86a7b6ab1e44e45d899005de92f58b3df180b36ddaf"
|
|
||||||
dependencies = [
|
|
||||||
"clipboard-win",
|
|
||||||
"image",
|
|
||||||
"log",
|
|
||||||
"objc2 0.6.4",
|
|
||||||
"objc2-app-kit 0.3.2",
|
|
||||||
"objc2-core-foundation",
|
|
||||||
"objc2-core-graphics",
|
|
||||||
"objc2-foundation 0.3.2",
|
|
||||||
"parking_lot",
|
|
||||||
"percent-encoding",
|
|
||||||
"windows-sys 0.59.0",
|
|
||||||
"wl-clipboard-rs",
|
|
||||||
"x11rb",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arg_enum_proc_macro"
|
name = "arg_enum_proc_macro"
|
||||||
version = "0.3.4"
|
version = "0.3.4"
|
||||||
|
|
@ -1247,12 +1226,6 @@ version = "0.1.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fixedbitset"
|
|
||||||
version = "0.5.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flate2"
|
name = "flate2"
|
||||||
version = "1.1.9"
|
version = "1.1.9"
|
||||||
|
|
@ -1927,13 +1900,11 @@ dependencies = [
|
||||||
name = "imagey"
|
name = "imagey"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arboard",
|
|
||||||
"dirs",
|
"dirs",
|
||||||
"iced",
|
"iced",
|
||||||
"image",
|
"image",
|
||||||
"jxl-oxide",
|
"jxl-oxide",
|
||||||
"rfd",
|
"rfd",
|
||||||
"size",
|
|
||||||
"zip",
|
"zip",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -3093,16 +3064,6 @@ dependencies = [
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "os_pipe"
|
|
||||||
version = "1.2.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"windows-sys 0.52.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "owned_ttf_parser"
|
name = "owned_ttf_parser"
|
||||||
version = "0.25.1"
|
version = "0.25.1"
|
||||||
|
|
@ -3169,17 +3130,6 @@ version = "2.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
|
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "petgraph"
|
|
||||||
version = "0.8.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455"
|
|
||||||
dependencies = [
|
|
||||||
"fixedbitset",
|
|
||||||
"hashbrown 0.15.5",
|
|
||||||
"indexmap",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project"
|
name = "pin-project"
|
||||||
version = "1.1.13"
|
version = "1.1.13"
|
||||||
|
|
@ -3837,12 +3787,6 @@ version = "0.1.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
|
checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "size"
|
|
||||||
version = "0.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1b6709c7b6754dca1311b3c73e79fcce40dd414c782c66d88e8823030093b02b"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "skrifa"
|
name = "skrifa"
|
||||||
version = "0.37.0"
|
version = "0.37.0"
|
||||||
|
|
@ -4302,17 +4246,6 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tree_magic_mini"
|
|
||||||
version = "3.2.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b8765b90061cba6c22b5831f675da109ae5561588290f9fa2317adab2714d5a6"
|
|
||||||
dependencies = [
|
|
||||||
"memchr",
|
|
||||||
"nom",
|
|
||||||
"petgraph",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ttf-parser"
|
name = "ttf-parser"
|
||||||
version = "0.25.1"
|
version = "0.25.1"
|
||||||
|
|
@ -5176,24 +5109,6 @@ version = "0.57.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
|
checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wl-clipboard-rs"
|
|
||||||
version = "0.9.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e9651471a32e87d96ef3a127715382b2d11cc7c8bb9822ded8a7cc94072eb0a3"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"log",
|
|
||||||
"os_pipe",
|
|
||||||
"rustix 1.1.4",
|
|
||||||
"thiserror 2.0.18",
|
|
||||||
"tree_magic_mini",
|
|
||||||
"wayland-backend",
|
|
||||||
"wayland-client",
|
|
||||||
"wayland-protocols",
|
|
||||||
"wayland-protocols-wlr",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "x11-dl"
|
name = "x11-dl"
|
||||||
version = "2.21.0"
|
version = "2.21.0"
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ license = "AGPL-3.0-or-later"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
dirs = "6.0.0"
|
dirs = "6.0.0"
|
||||||
rfd = "0.17.2"
|
rfd = "0.17.2"
|
||||||
size = "0.5.0"
|
|
||||||
zip = "8.6.0"
|
zip = "8.6.0"
|
||||||
|
|
||||||
[dependencies.iced]
|
[dependencies.iced]
|
||||||
|
|
@ -22,7 +21,3 @@ features = [ "avif-native" ]
|
||||||
version = "0.12.6"
|
version = "0.12.6"
|
||||||
# I really wish the image crate was named better
|
# I really wish the image crate was named better
|
||||||
features = [ "image" ]
|
features = [ "image" ]
|
||||||
|
|
||||||
[dependencies.arboard]
|
|
||||||
version = "3.6.1"
|
|
||||||
features = [ "wayland-data-control" ]
|
|
||||||
|
|
|
||||||
85
src/main.rs
85
src/main.rs
|
|
@ -2,18 +2,15 @@ use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
env,
|
env,
|
||||||
ffi::OsStr,
|
ffi::OsStr,
|
||||||
os::unix::fs::MetadataExt,
|
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
use arboard::Clipboard;
|
|
||||||
use iced::{
|
use iced::{
|
||||||
Alignment, Color, Element, Length, Renderer, Subscription, Task, Theme, event,
|
Alignment, Color, Element, Length, Renderer, Subscription, Task, Theme, event,
|
||||||
keyboard::{self, Key, key},
|
keyboard::{self, Key, key},
|
||||||
theme, widget, window,
|
theme, widget, window,
|
||||||
};
|
};
|
||||||
use image::{EncodableLayout, RgbaImage, imageops};
|
use image::{EncodableLayout, RgbaImage, imageops};
|
||||||
use size::Size;
|
|
||||||
|
|
||||||
mod kra;
|
mod kra;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
@ -27,7 +24,7 @@ enum Message {
|
||||||
Event(iced::Event),
|
Event(iced::Event),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
struct State {
|
struct State {
|
||||||
image: Option<RgbaImage>,
|
image: Option<RgbaImage>,
|
||||||
image_display: Option<widget::image::Allocation>,
|
image_display: Option<widget::image::Allocation>,
|
||||||
|
|
@ -36,8 +33,6 @@ struct State {
|
||||||
error: Option<String>,
|
error: Option<String>,
|
||||||
info: Option<String>,
|
info: Option<String>,
|
||||||
infobar_shown: bool,
|
infobar_shown: bool,
|
||||||
|
|
||||||
clipboard: Option<Clipboard>,
|
|
||||||
}
|
}
|
||||||
impl State {
|
impl State {
|
||||||
fn new() -> (Self, Task<Message>) {
|
fn new() -> (Self, Task<Message>) {
|
||||||
|
|
@ -53,7 +48,9 @@ impl State {
|
||||||
(state, Task::none())
|
(state, Task::none())
|
||||||
}
|
}
|
||||||
fn view(&self) -> Element<'_, Message, Theme, Renderer> {
|
fn view(&self) -> Element<'_, Message, Theme, Renderer> {
|
||||||
let main = self.image_display.as_ref().map_or_else(
|
let mut main = Vec::new();
|
||||||
|
|
||||||
|
main.push(self.image_display.as_ref().map_or_else(
|
||||||
|| {
|
|| {
|
||||||
widget::container(widget::text(include_str!("usage.txt")))
|
widget::container(widget::text(include_str!("usage.txt")))
|
||||||
.height(Length::Fill)
|
.height(Length::Fill)
|
||||||
|
|
@ -71,27 +68,16 @@ impl State {
|
||||||
.height(Length::Fill)
|
.height(Length::Fill)
|
||||||
.into()
|
.into()
|
||||||
},
|
},
|
||||||
);
|
));
|
||||||
|
|
||||||
let mut bar = Vec::new();
|
|
||||||
if let Some(error) = self.error.as_ref() {
|
if let Some(error) = self.error.as_ref() {
|
||||||
bar.push(
|
main.push(widget::text(error).style(widget::text::danger).into());
|
||||||
widget::container(widget::text(error).style(widget::text::danger))
|
|
||||||
.align_x(Alignment::Start)
|
|
||||||
.width(Length::Fill)
|
|
||||||
.into(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if self.infobar_shown && self.info.is_some() {
|
if self.infobar_shown && self.info.is_some() {
|
||||||
bar.push(
|
main.push(widget::text(self.title()).into());
|
||||||
widget::container(widget::text(self.title()))
|
|
||||||
.align_x(Alignment::End)
|
|
||||||
.width(Length::Fill)
|
|
||||||
.into(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
widget::column([main, widget::row(bar).into()]).into()
|
widget::column(main).into()
|
||||||
}
|
}
|
||||||
fn update(&mut self, message: Message) -> Task<Message> {
|
fn update(&mut self, message: Message) -> Task<Message> {
|
||||||
match message {
|
match message {
|
||||||
|
|
@ -169,52 +155,6 @@ impl State {
|
||||||
|
|
||||||
Key::Character("q") => return window::latest().and_then(window::close),
|
Key::Character("q") => return window::latest().and_then(window::close),
|
||||||
|
|
||||||
Key::Character("y") | Key::Character("c") => {
|
|
||||||
if let Some(image) = self.image.as_ref() {
|
|
||||||
match match self.clipboard.take() {
|
|
||||||
Some(c) => Ok(c),
|
|
||||||
None => Clipboard::new(),
|
|
||||||
} {
|
|
||||||
Ok(mut clipboard) => {
|
|
||||||
self.error = clipboard
|
|
||||||
.set_image(utils::arboard_from_rgbaimage(image))
|
|
||||||
.map_err(|e| e.to_string())
|
|
||||||
.err();
|
|
||||||
self.clipboard = Some(clipboard);
|
|
||||||
}
|
|
||||||
Err(e) => self.error = Some(e.to_string()),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.error = Some("no image to yank".into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Key::Character("p") | Key::Character("v") => {
|
|
||||||
match match self.clipboard.take() {
|
|
||||||
Some(c) => Ok(c),
|
|
||||||
None => Clipboard::new(),
|
|
||||||
} {
|
|
||||||
Ok(mut clipboard) => {
|
|
||||||
match clipboard.get_image().map(utils::rgbaimage_from_arboard) {
|
|
||||||
Ok(image) => {
|
|
||||||
self.error = None;
|
|
||||||
self.clipboard = Some(clipboard);
|
|
||||||
|
|
||||||
self.info =
|
|
||||||
Some(format!("{}x{}", image.width(), image.height(),));
|
|
||||||
if image.dimensions() < (100, 100) {
|
|
||||||
self.image_filter = widget::image::FilterMethod::Nearest;
|
|
||||||
}
|
|
||||||
self.image = Some(image);
|
|
||||||
return self.allocate_image();
|
|
||||||
}
|
|
||||||
Err(e) => self.error = Some(e.to_string()),
|
|
||||||
};
|
|
||||||
self.clipboard = Some(clipboard);
|
|
||||||
}
|
|
||||||
Err(e) => self.error = Some(e.to_string()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ignore unused keys
|
// ignore unused keys
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
|
|
@ -239,17 +179,10 @@ impl State {
|
||||||
fn load_image(&mut self, path: impl AsRef<Path>) -> Result<Task<Message>, String> {
|
fn load_image(&mut self, path: impl AsRef<Path>) -> Result<Task<Message>, String> {
|
||||||
utils::load_image(&path).map(|image| {
|
utils::load_image(&path).map(|image| {
|
||||||
self.info = Some(format!(
|
self.info = Some(format!(
|
||||||
"{} {} {}x{}",
|
"{} {}x{}",
|
||||||
path.as_ref()
|
path.as_ref()
|
||||||
.file_name()
|
.file_name()
|
||||||
.map_or(Cow::Borrowed("[no file]"), OsStr::to_string_lossy),
|
.map_or(Cow::Borrowed("[no file]"), OsStr::to_string_lossy),
|
||||||
path.as_ref().metadata().map_or_else(
|
|
||||||
|e| {
|
|
||||||
eprintln!("failed to read metadata: {e}");
|
|
||||||
Cow::Borrowed("[no size]")
|
|
||||||
},
|
|
||||||
|m| Cow::Owned(Size::from_bytes(m.size()).to_string())
|
|
||||||
),
|
|
||||||
image.width(),
|
image.width(),
|
||||||
image.height(),
|
image.height(),
|
||||||
));
|
));
|
||||||
|
|
|
||||||
21
src/utils.rs
21
src/utils.rs
|
|
@ -1,7 +1,4 @@
|
||||||
use std::{
|
use std::path::{Path, PathBuf};
|
||||||
borrow::Cow,
|
|
||||||
path::{Path, PathBuf},
|
|
||||||
};
|
|
||||||
|
|
||||||
use iced::widget;
|
use iced::widget;
|
||||||
use image::{DynamicImage, ImageDecoder, ImageReader, ImageResult, RgbaImage};
|
use image::{DynamicImage, ImageDecoder, ImageReader, ImageResult, RgbaImage};
|
||||||
|
|
@ -55,19 +52,3 @@ pub const fn string_from_filter_type(f: widget::image::FilterMethod) -> &'static
|
||||||
widget::image::FilterMethod::Nearest => "nearest neighbor",
|
widget::image::FilterMethod::Nearest => "nearest neighbor",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn arboard_from_rgbaimage<'a>(image: &'a RgbaImage) -> arboard::ImageData<'a> {
|
|
||||||
arboard::ImageData {
|
|
||||||
width: image.width() as usize,
|
|
||||||
height: image.height() as usize,
|
|
||||||
bytes: Cow::Borrowed(image.as_ref()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn rgbaimage_from_arboard(image: arboard::ImageData) -> RgbaImage {
|
|
||||||
RgbaImage::from_raw(
|
|
||||||
image.width as u32,
|
|
||||||
image.height as u32,
|
|
||||||
image.bytes.into_owned(),
|
|
||||||
)
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue