2024-01-24 16:54:45 +01:00
|
|
|
use std::path::PathBuf;
|
|
|
|
|
|
2022-11-22 15:54:14 -05:00
|
|
|
use dirs::home_dir;
|
2022-05-12 14:41:08 +02:00
|
|
|
use ini::Ini;
|
|
|
|
|
use once_cell::sync::Lazy;
|
2022-11-22 17:49:56 -05:00
|
|
|
use xdg::BaseDirectories;
|
2022-05-12 14:41:08 +02:00
|
|
|
|
2024-01-24 16:54:45 +01:00
|
|
|
use crate::theme;
|
|
|
|
|
use crate::theme::error::ThemeError;
|
|
|
|
|
|
2022-05-12 15:34:02 +02:00
|
|
|
pub(crate) static BASE_PATHS: Lazy<Vec<PathBuf>> = Lazy::new(icon_theme_base_paths);
|
2022-05-12 14:41:08 +02:00
|
|
|
|
|
|
|
|
/// Look in $HOME/.icons (for backwards compatibility), in $XDG_DATA_DIRS/icons and in /usr/share/pixmaps (in that order).
|
|
|
|
|
/// Paths that are not found are filtered out.
|
|
|
|
|
fn icon_theme_base_paths() -> Vec<PathBuf> {
|
|
|
|
|
let home_icon_dir = home_dir().expect("No $HOME directory").join(".icons");
|
2022-11-22 17:49:56 -05:00
|
|
|
let mut data_dirs: Vec<_> = BaseDirectories::new()
|
|
|
|
|
.map(|bd| {
|
2024-01-24 16:54:45 +01:00
|
|
|
let mut data_dirs: Vec<_> = bd.get_data_dirs()
|
2022-11-22 17:49:56 -05:00
|
|
|
.into_iter()
|
|
|
|
|
.map(|p| p.join("icons"))
|
2024-01-24 16:54:45 +01:00
|
|
|
.collect();
|
|
|
|
|
data_dirs.push(bd.get_data_home().join("icons"));
|
|
|
|
|
data_dirs
|
2022-11-22 17:49:56 -05:00
|
|
|
})
|
|
|
|
|
.unwrap_or_default();
|
2022-11-22 15:54:14 -05:00
|
|
|
data_dirs.push(home_icon_dir);
|
2022-11-22 17:49:56 -05:00
|
|
|
data_dirs.into_iter().filter(|p| p.exists()).collect()
|
2024-01-24 16:54:45 +01:00
|
|
|
|
|
|
|
|
|
2022-05-12 14:41:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub struct ThemePath(pub PathBuf);
|
|
|
|
|
|
|
|
|
|
impl ThemePath {
|
|
|
|
|
pub(super) fn index(&self) -> theme::Result<Ini> {
|
|
|
|
|
let index = self.0.join("index.theme");
|
|
|
|
|
|
|
|
|
|
if !index.exists() {
|
|
|
|
|
return Err(ThemeError::ThemeIndexNotFound(index));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(Ini::load_from_file(index)?)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod test {
|
|
|
|
|
use crate::theme::paths::icon_theme_base_paths;
|
|
|
|
|
use crate::theme::{get_all_themes, Theme};
|
|
|
|
|
use anyhow::Result;
|
|
|
|
|
use speculoos::prelude::*;
|
|
|
|
|
|
2022-05-12 15:34:02 +02:00
|
|
|
#[test]
|
|
|
|
|
fn should_get_all_themes() {
|
|
|
|
|
let themes = get_all_themes().unwrap();
|
|
|
|
|
assert_that!(themes.get("hicolor")).is_some();
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-12 14:41:08 +02:00
|
|
|
#[test]
|
|
|
|
|
fn should_get_theme_paths_ordered() {
|
|
|
|
|
let base_paths = icon_theme_base_paths();
|
|
|
|
|
assert_that!(base_paths).is_not_empty()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn should_read_theme_index() -> Result<()> {
|
|
|
|
|
let themes = get_all_themes()?;
|
2023-01-09 23:54:07 +01:00
|
|
|
let themes: Vec<&Theme> = themes.values().flatten().collect();
|
2022-05-12 14:41:08 +02:00
|
|
|
assert_that!(themes).is_not_empty();
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
}
|