-
Notifications
You must be signed in to change notification settings - Fork 31
Expand file tree
/
Copy pathicons.rs
More file actions
130 lines (111 loc) · 3.81 KB
/
icons.rs
File metadata and controls
130 lines (111 loc) · 3.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
use std::path::{Path, PathBuf};
use std::env;
use crate::config::Config;
/// Resolve icon path from theme (supports svg, png, xpm, scalable, symbolic, etc.)
pub fn resolve_icon_path(icon_name: &str) -> Option<PathBuf> {
if icon_name.is_empty() { return None }
let path = Path::new(icon_name);
// If already a valid file path
if path.exists() {
return Some(path.to_path_buf());
}
// Get theme from config or fallback
let theme = Config::get()
.icon_theme
.clone()
.unwrap_or_else(|| "Adwaita".to_string());
// Collect all possible icon base directories
let mut icon_dirs = vec![
"/usr/share/icons".to_string(),
"/usr/local/share/icons".to_string(),
expand_tilde("~/.icons"),
expand_tilde("~/.local/share/icons"),
"/usr/share/pixmaps".to_string(),
"/var/lib/flatpak/exports/share/icons".to_string(),
];
// Add any extra paths from XDG_DATA_DIRS
if let Ok(xdg_data_dirs) = env::var("XDG_DATA_DIRS") {
for p in xdg_data_dirs.split(':') {
let p = format!("{}/icons", p.trim_end_matches('/'));
icon_dirs.push(p);
}
}
let subdirs = vec![
"apps", "status", "actions", "devices", "categories", "places", "mimetypes",
];
let sizes = vec![
"scalable", "symbolic", "16x16", "22x22", "24x24", "32x32", "48x48", "64x64", "128x128",
];
let extensions = vec!["svg", "svgz", "png", "xpm"];
for base_dir in &icon_dirs {
let base_path = Path::new(base_dir);
// skip base dirs that don't exists
if !base_path.exists() {
continue;
}
for size in &sizes {
for subdir in &subdirs {
let dir_path = base_path
.join(&theme)
.join(size)
.join(subdir);
// skip nonexistent subdirectories to save time
if !dir_path.is_dir() {
continue;
}
for ext in &extensions {
let full = dir_path.join(format!("{}.{}", icon_name, ext));
if full.exists() {
return Some(full);
}
}
}
}
}
// NOTE: fallback to hicolor theme (optional if you to make an option in config)
// PERF: skip dirs thats does not exists
//
// for base_dir in &icon_dirs {
// let base_path = Path::new(base_dir);
// if !base_path.exists() {
// continue;
// }
//
// for size in &sizes {
// for subdir in &subdirs {
// let dir_path = base_path.join("hicolor").join(size).join(subdir);
// if !dir_path.is_dir() {
// continue;
// }
//
// for ext in &extensions {
// let full = dir_path.join(format!("{}.{}", icon_name, ext));
//
// if full.exists() {
// return Some(full);
// }
// }
// }
// }
// }
// Last resort: search directly in /usr/share/pixmaps
// for ext in &extensions {
// let full = Path::new("/usr/share/pixmaps").join(format!("{}.{}", icon_name, ext));
// if full.exists() {
// return Some(full);
// }
// }
println!("Icon '{}' not found in any theme path.", icon_name);
None
}
/// Expand ~ to home directory manually (no external crates)
fn expand_tilde(path: &str) -> String {
if path.starts_with("~/") {
if let Some(home) = std::env::var_os("HOME") {
let mut p = PathBuf::from(home);
p.push(path.trim_start_matches("~/"));
return p.display().to_string();
}
}
path.to_string()
}