From 26b1003bae40b0fd531a3df2743c43654592ffef Mon Sep 17 00:00:00 2001 From: Nicola Guerrera Date: Wed, 22 Feb 2023 21:07:40 +0100 Subject: [PATCH] Using linicon crate for icons Removed file --- Cargo.lock | 134 +++++++++++++++++++++++++++++++++++++++++++++-- Cargo.toml | 1 + src/protostar.rs | 19 +++---- src/xdg.rs | 96 +++++++++++++-------------------- 4 files changed, 176 insertions(+), 74 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a46c15b..0250d62 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,6 +23,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e" + [[package]] name = "ahash" version = "0.7.6" @@ -343,7 +349,7 @@ dependencies = [ "autocfg", "cfg-if", "crossbeam-utils", - "memoffset", + "memoffset 0.7.1", "scopeguard", ] @@ -461,6 +467,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "dlv-list" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68df3f2b690c1b86e65ef7830956aededf3cb0a16f898f79b9a6f421a7b6211b" +dependencies = [ + "rand 0.8.5", +] + [[package]] name = "either" version = "1.8.0" @@ -522,6 +537,15 @@ dependencies = [ "color-maps", ] +[[package]] +name = "file-locker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91c8a37357ab5d51f1a8053900fe8374283449695c5418b66f45deece50705f" +dependencies = [ + "nix 0.25.1", +] + [[package]] name = "flagset" version = "0.4.3" @@ -602,6 +626,16 @@ dependencies = [ "ttf-parser", ] +[[package]] +name = "freedesktop_entry_parser" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db9c27b72f19a99a895f8ca89e2d26e4ef31013376e56fdafef697627306c3e4" +dependencies = [ + "nom", + "thiserror", +] + [[package]] name = "fuchsia-cprng" version = "0.1.1" @@ -683,6 +717,15 @@ dependencies = [ "crunchy", ] +[[package]] +name = "hashbrown" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" +dependencies = [ + "ahash 0.4.7", +] + [[package]] name = "heck" version = "0.4.0" @@ -838,6 +881,29 @@ version = "0.2.138" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" +[[package]] +name = "linicon" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee8c5653188a809616c97296180a0547a61dba205bcdcbdd261dbd022a25fd9" +dependencies = [ + "file-locker", + "freedesktop_entry_parser", + "linicon-theme", + "memmap2", + "thiserror", +] + +[[package]] +name = "linicon-theme" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4f8240c33bb08c5d8b8cdea87b683b05e61037aa76ff26bef40672cc6ecbb80" +dependencies = [ + "freedesktop_entry_parser", + "rust-ini", +] + [[package]] name = "link-cplusplus" version = "1.0.7" @@ -908,6 +974,15 @@ dependencies = [ "libc", ] +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + [[package]] name = "memoffset" version = "0.7.1" @@ -917,6 +992,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.5.4" @@ -974,6 +1055,20 @@ dependencies = [ "getrandom", ] +[[package]] +name = "nix" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" +dependencies = [ + "autocfg", + "bitflags", + "cfg-if", + "libc", + "memoffset 0.6.5", + "pin-utils", +] + [[package]] name = "nix" version = "0.26.1" @@ -983,11 +1078,21 @@ dependencies = [ "bitflags", "cfg-if", "libc", - "memoffset", + "memoffset 0.7.1", "pin-utils", "static_assertions", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -1074,6 +1179,16 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" +[[package]] +name = "ordered-multimap" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c672c7ad9ec066e428c00eb917124a06f08db19e2584de982cc34b1f4c12485" +dependencies = [ + "dlv-list", + "hashbrown", +] + [[package]] name = "os_str_bytes" version = "6.4.1" @@ -1275,9 +1390,10 @@ dependencies = [ "glam", "image", "lazy_static", + "linicon", "manifest-dir-macros", "mint", - "nix", + "nix 0.26.1", "resvg", "rustc-hash", "sha2", @@ -1484,6 +1600,16 @@ dependencies = [ "xmlparser", ] +[[package]] +name = "rust-ini" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63471c4aa97a1cf8332a5f97709a79a4234698de6a1f5087faf66f2dae810e22" +dependencies = [ + "cfg-if", + "ordered-multimap", +] + [[package]] name = "rustc-demangle" version = "0.1.21" @@ -2069,7 +2195,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "371436099f2980de56dc385b615696d3eabbdac9649a72b85f9d75f68474fa9c" dependencies = [ - "ahash", + "ahash 0.7.6", "byteorder", "lazy_static", "parking_lot 0.11.2", diff --git a/Cargo.toml b/Cargo.toml index db08348..6e0d20e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ ez-pixmap = "0.2.2" glam = { version = "0.22.0", features = ["mint"] } image = "0.24.5" lazy_static = "1.4.0" +linicon = "2.3.0" manifest-dir-macros = "0.1.16" mint = "0.5.9" nix = "0.26.1" diff --git a/src/protostar.rs b/src/protostar.rs index aefc336..60e6911 100644 --- a/src/protostar.rs +++ b/src/protostar.rs @@ -20,8 +20,8 @@ use tween::{QuartInOut, Tweener}; use ustr::ustr; fn model_from_icon(parent: &Spatial, icon: &Icon) -> Result { - let model = match icon { - Icon::Png(path) => { + return match &icon.icon_type { + RawIconType::Png(path) => { let model = Model::create( parent, Transform::from_rotation(Quat::from_rotation_y(PI)), @@ -32,15 +32,15 @@ fn model_from_icon(parent: &Spatial, icon: &Icon) -> Result { "diffuse", MaterialParameter::Texture(ResourceID::Direct(path.clone())), )?; - model + Ok(model) } - Icon::Gltf(path) => Model::create( + RawIconType::Gltf(path) => Ok(Model::create( parent, Transform::from_scale([0.05; 3]), &ResourceID::new_direct(path)?, - )?, + )?), + _ => panic!("asd"), }; - Ok(model) } pub struct ProtoStar { @@ -54,11 +54,12 @@ pub struct ProtoStar { impl ProtoStar { pub fn create_from_desktop_file(parent: &Spatial, desktop_file: DesktopFile) -> Result { // dbg!(&desktop_file); - let mut raw_icons = desktop_file.get_raw_icons(); + dbg!(&desktop_file); + let mut raw_icons = dbg!(desktop_file.get_raw_icons()); let last_icon = raw_icons.pop(); let icon = raw_icons .into_iter() - .find(|i| match i { + .find(|i| match i.icon_type { RawIconType::Png(_) => false, RawIconType::Svg(_) => false, RawIconType::Gltf(_) => true, @@ -77,7 +78,7 @@ impl ProtoStar { parent, Transform::default(), match icon.as_ref() { - Some(Icon::Png(_)) => [0.05, 0.0665, 0.005], + Some(_) => [0.05, 0.0665, 0.005], _ => [0.05; 3], } .into(), diff --git a/src/xdg.rs b/src/xdg.rs index ea24c0d..04f81f2 100644 --- a/src/xdg.rs +++ b/src/xdg.rs @@ -10,8 +10,7 @@ use std::str::FromStr; use std::{env, fs}; use walkdir::WalkDir; use sha2::{Sha224, Digest}; - -const ICON_SIZES: &[&str] = &["64x64", "32x32", "scalable", "128x128"]; +use linicon; fn get_data_dirs() -> Vec { let xdg_data_dirs_str = std::env::var("XDG_DATA_DIRS") @@ -108,7 +107,7 @@ pub fn parse_desktop_file(path: PathBuf) -> Result { Some((key, value)) => (key, value), None => continue, }; - + // Parse the key-value pair based on the key match key { "Name" => name = Some(value.to_string()), @@ -171,71 +170,54 @@ pub struct DesktopFile { pub no_display: bool, } impl DesktopFile { - pub fn get_raw_icons(&self) -> Vec { + pub fn get_raw_icons(&self) -> Vec { // Get the name of the icon from the DesktopFile struct let Some(icon_name) = self.icon.as_ref() else { return Vec::new(); }; let test_icon_path = self.path.join(Path::new(icon_name)); if test_icon_path.exists() { - return RawIconType::from_path(test_icon_path) - .map(|i| vec![i]) - .unwrap_or_default(); + if let Some(icon) = Icon::from_path(test_icon_path,128) { + return vec![icon] + } } - - let Ok(icon_name) = OsString::from_str(icon_name) else { return Vec::new(); }; - - // Get the current icon theme from the XDG_ICON_THEME environment variable, or use "hicolor" as the default theme if the variable is not defined - let icon_theme = env::var_os("XDG_ICON_THEME").unwrap_or("hicolor".into()); - - // Get the XDG_DATA_HOME and XDG_DATA_DIRS environment variables, and split the XDG_DATA_DIRS variable into a list of directories - let xdg_data_dirs = get_data_dirs(); - - // Concatenate the XDG_DATA_HOME and XDG_DATA_DIRS directories with the default path for icon themes - xdg_data_dirs // XDG_DATA_DIRS directories - .into_iter() - .flat_map(|dir| { - let icons_path = dir.join("icons").join(&icon_theme); - ICON_SIZES - .iter() - .map(|path| icons_path.join(path).join("apps")) - .collect::>() - }) - .filter_map(|dir| { - let dir = fs::read_dir(dir).ok()?; - Some( - dir.filter_map(|e| e.ok()) - .map(|file| file.path()) - .filter(|file| file.file_stem() == Some(&icon_name)), - ) - }) - .flatten() - .filter_map(RawIconType::from_path) - .collect() + + let mut icons_iter= linicon::lookup_icon(icon_name); + + let sized_png : Vec = icons_iter + .filter_map(|i| i.ok()) + .filter(|i| i.icon_type != linicon::IconType::XMP) //TODO: support XMP + .map(|i| Icon::from_path(i.path,i.max_size - 2 ).unwrap()) + .collect(); + sized_png } } +#[derive(Debug, PartialEq, Eq)] +pub struct Icon { + pub icon_type: RawIconType, + pub size: u16, +} + #[derive(Debug, PartialEq, Eq)] pub enum RawIconType { Png(PathBuf), Svg(PathBuf), Gltf(PathBuf), } -impl RawIconType { - pub fn from_path(path: PathBuf) -> Option { - match path.extension().and_then(|ext| ext.to_str()) { +impl Icon { + pub fn from_path(path: PathBuf, size: u16) -> Option{ + let icon_type = match path.extension().and_then(|ext| ext.to_str()) { Some("png") => Some(RawIconType::Png(path)), Some("svg") => Some(RawIconType::Svg(path)), Some("glb") | Some("gltf") => Some(RawIconType::Gltf(path)), - _ => None, - } + _ => {return None}, + }.unwrap(); + return Some(Icon{icon_type,size}) } - pub fn process(self, size: u32) -> Result { - match self { - RawIconType::Png(path) => Ok(Icon::Png(path)), - RawIconType::Svg(path) => { - Ok(Icon::Png(get_png_from_svg(&path, size)?)) - } - RawIconType::Gltf(path) => Ok(Icon::Gltf(path)), + pub fn process(self, size: u16) -> Result { + match self.icon_type { + RawIconType::Svg(path) => Ok(Icon::from_path(get_png_from_svg(&path, size)?,size).unwrap()), + _ => Ok(self), } } } @@ -257,18 +239,10 @@ fn test_get_icon_path() { dbg!(&icon_paths); // Assert that the get_icon_path() function returns the expected result - assert!(icon_paths.contains(&RawIconType::Png(PathBuf::from( - "/usr/share/icons/hicolor/32x32/apps/krita.png" - )))); + assert!(icon_paths.contains(&Icon::from_path(PathBuf::from("/usr/share/icons/hicolor/32x32/apps/krita.png"),32).unwrap())); } -#[derive(Debug, PartialEq, Eq)] -pub enum Icon { - Png(PathBuf), - Gltf(PathBuf), -} - -pub fn get_png_from_svg(svg_path: impl AsRef, size: u32,) -> Result { +pub fn get_png_from_svg(svg_path: impl AsRef, size: u16,) -> Result { let svg_path = fs::canonicalize(svg_path)?; let tree = Tree::from_data( fs::read(svg_path.as_path())?.as_slice(), @@ -303,10 +277,10 @@ pub fn get_png_from_svg(svg_path: impl AsRef, size: u32,) -> Result