1
0
forked from brl/citadel-tools

Handle icon paths to specific image files

This commit is contained in:
Bruce Leidl 2022-09-19 09:49:49 -04:00
parent 3dbfda2c40
commit dc6ddc4e85
5 changed files with 69 additions and 5 deletions

View File

@ -74,6 +74,10 @@ impl DesktopFile {
self.get_key_val("Icon") self.get_key_val("Icon")
} }
pub fn update_icon(&mut self, value: &str) {
self.update_key_val("Icon", value);
}
fn show_in_gnome(&self) -> bool { fn show_in_gnome(&self) -> bool {
if self.key_exists("NotShowIn") && self.key_value_contains("NotShowIn", "GNOME") { if self.key_exists("NotShowIn") && self.key_value_contains("NotShowIn", "GNOME") {
return false; return false;
@ -118,6 +122,14 @@ impl DesktopFile {
None None
} }
fn update_key_val(&mut self, key: &str, value: &str) {
if let Some(&idx) = self.main_map.get(key) {
if idx < self.lines.len() {
self.lines[idx] = Line::KeyValue(key.to_string(), value.to_string());
}
}
}
pub fn new(filename: &str) -> DesktopFile { pub fn new(filename: &str) -> DesktopFile {
DesktopFile { DesktopFile {
filename: filename.to_string(), filename: filename.to_string(),

View File

@ -6,6 +6,7 @@ use std::time::SystemTime;
use libcitadel::{Realm, Realms, Result, util}; use libcitadel::{Realm, Realms, Result, util};
use crate::sync::parser::DesktopFileParser; use crate::sync::parser::DesktopFileParser;
use std::fs::DirEntry; use std::fs::DirEntry;
use crate::sync::desktop_file::DesktopFile;
use crate::sync::icons::IconSync; use crate::sync::icons::IconSync;
/// Synchronize dot-desktop files from active realm to a target directory in Citadel. /// Synchronize dot-desktop files from active realm to a target directory in Citadel.
@ -161,15 +162,31 @@ impl DesktopFileSync {
Ok(()) Ok(())
} }
fn sync_item_icon(&self, file: &mut DesktopFile) {
let icon_val = match file.icon() {
Some(icon) => icon.to_string(),
None => return,
};
if let Some(ref icons) = self.icons {
if let Err(err) = icons.sync_icon(file, &icon_val) {
warn!("Failed to sync desktop file icon '{}': {}", icon_val, err);
}
}
}
fn sync_item(&self, item: &DesktopItem) -> Result<()> { fn sync_item(&self, item: &DesktopItem) -> Result<()> {
let dfp = DesktopFileParser::parse_from_path(&item.path, "/usr/libexec/citadel-run ")?; let mut dfp = DesktopFileParser::parse_from_path(&item.path, "/usr/libexec/citadel-run ")?;
if dfp.is_showable() { if dfp.is_showable() {
self.sync_item_icon(&mut dfp);
dfp.write_to_dir(Self::CITADEL_APPLICATIONS, Some(&self.realm))?; dfp.write_to_dir(Self::CITADEL_APPLICATIONS, Some(&self.realm))?;
/*
if let Some(icon_name)= dfp.icon() { if let Some(icon_name)= dfp.icon() {
if let Some(ref icons) = self.icons { if let Some(ref icons) = self.icons {
icons.sync_icon(icon_name)?; icons.sync_icon(icon_name)?;
} }
} }
*/
} else { } else {
debug!("Ignoring desktop file {} as not showable", dfp.filename()); debug!("Ignoring desktop file {} as not showable", dfp.filename());
} }

View File

@ -24,7 +24,7 @@ impl IconCache {
let hash = Self::icon_name_hash(icon_name) % nbuckets; let hash = Self::icon_name_hash(icon_name) % nbuckets;
let mut chain_offset = self.read_offset(hash_offset + 4 + (4 * hash as usize))?; let mut chain_offset = self.read_offset(hash_offset + 4 + (4 * hash as usize))?;
while chain_offset != u32::max_value() as usize { while chain_offset != u32::MAX as usize {
let name_offset = self.read_offset(chain_offset + 4)?; let name_offset = self.read_offset(chain_offset + 4)?;
chain_offset = self.read_offset(chain_offset)?; chain_offset = self.read_offset(chain_offset)?;
let name = self.read_string(name_offset)?; let name = self.read_string(name_offset)?;

View File

@ -4,6 +4,7 @@ use std::path::{Path, PathBuf};
use libcitadel::{Result, util, Realm}; use libcitadel::{Result, util, Realm};
use std::cell::{RefCell, Cell}; use std::cell::{RefCell, Cell};
use crate::sync::desktop_file::DesktopFile;
pub struct IconSync { pub struct IconSync {
realm_base: PathBuf, realm_base: PathBuf,
@ -26,7 +27,40 @@ impl IconSync {
Ok(IconSync { realm_base, cache, known, known_changed }) Ok(IconSync { realm_base, cache, known, known_changed })
} }
pub fn sync_icon(&self, icon_name: &str) -> Result<()> { fn sync_icon_filepath(&self, file: &mut DesktopFile, path: &Path) -> Result<()> {
let icon_path = path.canonicalize()
.map_err(context!("Failed to canonicalize icon path {}", path.display()))?;
let icon_path = icon_path.strip_prefix("/")
.map_err(context!("Failed to strip initial / from {}", icon_path.display()))?;
let realm_path = self.realm_base.join(icon_path);
if !realm_path.is_file() {
bail!("Failed to find icon file {}", realm_path.display());
}
let dir = Path::new(Self::CITADEL_ICONS).join("filepaths-icons");
let target = dir.join(realm_path.file_name()
.expect("Icon has no filename?"));
util::create_dir(&dir)?;
util::copy_file(&realm_path, &target)?;
util::chmod(&target, 0o644)?;
let target_str = target.display().to_string();
file.update_icon(&target_str);
info!("Copied icon from {} to {}", icon_path.display(), target_str);
Ok(())
}
pub fn sync_icon(&self, file: &mut DesktopFile, icon_name: &str) -> Result<()> {
if icon_name.starts_with("/") {
return self.sync_icon_filepath(file, Path::new(icon_name));
}
if self.is_known(icon_name) { if self.is_known(icon_name) {
return Ok(()) return Ok(())
} }
@ -116,7 +150,8 @@ impl IconSync {
let target = Path::new(Self::CITADEL_ICONS).join("hicolor").join(stripped); let target = Path::new(Self::CITADEL_ICONS).join("hicolor").join(stripped);
let parent = target.parent().unwrap(); let parent = target.parent().unwrap();
util::create_dir(parent)?; util::create_dir(parent)?;
util::copy_file(icon_path, target)?; util::copy_file(icon_path, &target)?;
util::chmod(&target, 0o644)?;
Ok(()) Ok(())
} }
} }

View File

@ -34,4 +34,4 @@ fn sync(clear: bool) -> Result<()> {
} else { } else {
DesktopFileSync::clear_target_files() DesktopFileSync::clear_target_files()
} }
} }