fix: merge themes from multiple locations
This commit is contained in:
parent
1be7d4e73b
commit
92f759fd09
4 changed files with 51 additions and 22 deletions
27
src/lib.rs
27
src/lib.rs
|
|
@ -75,15 +75,18 @@ mod theme;
|
||||||
/// ])
|
/// ])
|
||||||
/// # }
|
/// # }
|
||||||
pub fn list_themes() -> Vec<&'static str> {
|
pub fn list_themes() -> Vec<&'static str> {
|
||||||
THEMES
|
let mut themes = THEMES
|
||||||
.values()
|
.values()
|
||||||
|
.flatten()
|
||||||
.map(|path| &path.index)
|
.map(|path| &path.index)
|
||||||
.filter_map(|index| {
|
.filter_map(|index| {
|
||||||
index
|
index
|
||||||
.section(Some("Icon Theme"))
|
.section(Some("Icon Theme"))
|
||||||
.and_then(|section| section.get("Name"))
|
.and_then(|section| section.get("Name"))
|
||||||
})
|
})
|
||||||
.collect()
|
.collect::<Vec<_>>();
|
||||||
|
themes.dedup();
|
||||||
|
themes
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The lookup builder struct, holding all the lookup query parameters.
|
/// The lookup builder struct, holding all the lookup query parameters.
|
||||||
|
|
@ -232,14 +235,24 @@ impl<'a> LookupBuilder<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then lookup in the given theme
|
// Then lookup in the given theme
|
||||||
THEMES.get(self.theme).and_then(|icon_theme| {
|
THEMES.get(self.theme).and_then(|icon_themes| {
|
||||||
let icon = icon_theme
|
let icon = icon_themes
|
||||||
.try_get_icon(self.name, self.size, self.scale, self.force_svg)
|
.iter()
|
||||||
|
.find_map(|theme| {
|
||||||
|
theme.try_get_icon(self.name, self.size, self.scale, self.force_svg)
|
||||||
|
})
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
// Fallback to the parent themes recursively
|
// Fallback to the parent themes recursively
|
||||||
icon_theme.inherits().into_iter().find_map(|parent| {
|
let mut parents = icon_themes
|
||||||
|
.iter()
|
||||||
|
.flat_map(|t| t.inherits())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
parents.dedup();
|
||||||
|
parents.into_iter().find_map(|parent| {
|
||||||
THEMES.get(parent).and_then(|parent| {
|
THEMES.get(parent).and_then(|parent| {
|
||||||
parent.try_get_icon(self.name, self.size, self.scale, self.force_svg)
|
parent.iter().find_map(|t| {
|
||||||
|
t.try_get_icon(self.name, self.size, self.scale, self.force_svg)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ mod paths;
|
||||||
|
|
||||||
type Result<T> = std::result::Result<T, ThemeError>;
|
type Result<T> = std::result::Result<T, ThemeError>;
|
||||||
|
|
||||||
pub static THEMES: Lazy<BTreeMap<String, Theme>> =
|
pub static THEMES: Lazy<BTreeMap<String, Vec<Theme>>> =
|
||||||
Lazy::new(|| get_all_themes().expect("Failed to get theme paths"));
|
Lazy::new(|| get_all_themes().expect("Failed to get theme paths"));
|
||||||
|
|
||||||
pub struct Theme {
|
pub struct Theme {
|
||||||
|
|
@ -140,14 +140,14 @@ fn try_build_xmp<P: AsRef<Path>>(name: &str, path: P) -> Option<PathBuf> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iter through the base paths and get all theme directories
|
// Iter through the base paths and get all theme directories
|
||||||
pub(super) fn get_all_themes() -> Result<BTreeMap<String, Theme>> {
|
pub(super) fn get_all_themes() -> Result<BTreeMap<String, Vec<Theme>>> {
|
||||||
let mut icon_themes = BTreeMap::new();
|
let mut icon_themes = BTreeMap::<_, Vec<_>>::new();
|
||||||
for theme_base_dir in BASE_PATHS.iter() {
|
for theme_base_dir in BASE_PATHS.iter() {
|
||||||
for entry in theme_base_dir.read_dir()? {
|
for entry in theme_base_dir.read_dir()? {
|
||||||
let entry = entry?;
|
let entry = entry?;
|
||||||
if let Some(theme) = Theme::from_path(entry.path()) {
|
if let Some(theme) = Theme::from_path(entry.path()) {
|
||||||
let name = entry.file_name().to_string_lossy().to_string();
|
let name = entry.file_name().to_string_lossy().to_string();
|
||||||
icon_themes.insert(name, theme);
|
icon_themes.entry(name).or_default().push(theme);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -190,17 +190,24 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn get_one_icon() {
|
fn get_one_icon() {
|
||||||
let theme = THEMES.get("Adwaita").unwrap();
|
let themes = THEMES.get("Adwaita").unwrap();
|
||||||
println!(
|
println!(
|
||||||
"{:?}",
|
"{:?}",
|
||||||
theme.try_get_icon_exact_size("edit-delete-symbolic", 24, 1, false)
|
themes.iter().find_map(|t| t.try_get_icon_exact_size(
|
||||||
|
"edit-delete-symbolic",
|
||||||
|
24,
|
||||||
|
1,
|
||||||
|
false
|
||||||
|
))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_get_png_first() {
|
fn should_get_png_first() {
|
||||||
let theme = THEMES.get("hicolor").unwrap();
|
let themes = THEMES.get("hicolor").unwrap();
|
||||||
let icon = theme.try_get_icon_exact_size("blueman", 24, 1, true);
|
let icon = themes
|
||||||
|
.iter()
|
||||||
|
.find_map(|t| t.try_get_icon_exact_size("blueman", 24, 1, true));
|
||||||
assert_that!(icon).is_some().is_equal_to(PathBuf::from(
|
assert_that!(icon).is_some().is_equal_to(PathBuf::from(
|
||||||
"/usr/share/icons/hicolor/scalable/apps/blueman.svg",
|
"/usr/share/icons/hicolor/scalable/apps/blueman.svg",
|
||||||
));
|
));
|
||||||
|
|
@ -208,8 +215,10 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_get_svg_first() {
|
fn should_get_svg_first() {
|
||||||
let theme = THEMES.get("hicolor").unwrap();
|
let themes = THEMES.get("hicolor").unwrap();
|
||||||
let icon = theme.try_get_icon_exact_size("blueman", 24, 1, false);
|
let icon = themes
|
||||||
|
.iter()
|
||||||
|
.find_map(|t| t.try_get_icon_exact_size("blueman", 24, 1, false));
|
||||||
assert_that!(icon).is_some().is_equal_to(PathBuf::from(
|
assert_that!(icon).is_some().is_equal_to(PathBuf::from(
|
||||||
"/usr/share/icons/hicolor/22x22/apps/blueman.png",
|
"/usr/share/icons/hicolor/22x22/apps/blueman.png",
|
||||||
));
|
));
|
||||||
|
|
|
||||||
|
|
@ -88,11 +88,18 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_get_theme_parents() {
|
fn should_get_theme_parents() {
|
||||||
let theme = THEMES.get("Arc").unwrap();
|
for theme in THEMES.get("Arc").unwrap() {
|
||||||
let parents = theme.inherits();
|
let parents = theme.inherits();
|
||||||
|
|
||||||
assert_that!(parents).does_not_contain("hicolor");
|
assert_that!(parents).does_not_contain("hicolor");
|
||||||
|
|
||||||
assert_that!(parents).is_equal_to(vec!["Moka", "Faba", "elementary", "Adwaita", "gnome"]);
|
assert_that!(parents).is_equal_to(vec![
|
||||||
|
"Moka",
|
||||||
|
"Faba",
|
||||||
|
"elementary",
|
||||||
|
"Adwaita",
|
||||||
|
"gnome",
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn should_read_theme_index() -> Result<()> {
|
fn should_read_theme_index() -> Result<()> {
|
||||||
let themes = get_all_themes()?;
|
let themes = get_all_themes()?;
|
||||||
let themes: Vec<&Theme> = themes.values().collect();
|
let themes: Vec<&Theme> = themes.values().flatten().collect();
|
||||||
assert_that!(themes).is_not_empty();
|
assert_that!(themes).is_not_empty();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue