mirror of
https://github.com/Zedfrigg/ironbar.git
synced 2025-07-01 10:41:03 +02:00
fix: poor error handling for missing images
Previously images that could not be located were handled by throwing a full report error, which incorrectly stated it was an invalid image *type*. This changes the image handling to instead log a single-line warning directly in the image provider code, reducing the error handling required by each consumer. Resolves #146.
This commit is contained in:
parent
960da55a05
commit
87ca399220
7 changed files with 52 additions and 62 deletions
|
@ -2,7 +2,6 @@ use super::ImageProvider;
|
||||||
use crate::gtk_helpers::add_class;
|
use crate::gtk_helpers::add_class;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::{Button, IconTheme, Image, Label, Orientation};
|
use gtk::{Button, IconTheme, Image, Label, Orientation};
|
||||||
use tracing::error;
|
|
||||||
|
|
||||||
#[cfg(any(feature = "music", feature = "workspaces", feature = "clipboard"))]
|
#[cfg(any(feature = "music", feature = "workspaces", feature = "clipboard"))]
|
||||||
pub fn new_icon_button(input: &str, icon_theme: &IconTheme, size: i32) -> Button {
|
pub fn new_icon_button(input: &str, icon_theme: &IconTheme, size: i32) -> Button {
|
||||||
|
@ -13,14 +12,13 @@ pub fn new_icon_button(input: &str, icon_theme: &IconTheme, size: i32) -> Button
|
||||||
add_class(&image, "image");
|
add_class(&image, "image");
|
||||||
|
|
||||||
match ImageProvider::parse(input, icon_theme, size)
|
match ImageProvider::parse(input, icon_theme, size)
|
||||||
.and_then(|provider| provider.load_into_image(image.clone()))
|
.map(|provider| provider.load_into_image(image.clone()))
|
||||||
{
|
{
|
||||||
Ok(_) => {
|
Some(_) => {
|
||||||
button.set_image(Some(&image));
|
button.set_image(Some(&image));
|
||||||
button.set_always_show_image(true);
|
button.set_always_show_image(true);
|
||||||
}
|
}
|
||||||
Err(err) => {
|
None => {
|
||||||
error!("{err:?}");
|
|
||||||
button.set_label(input);
|
button.set_label(input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,11 +39,8 @@ pub fn new_icon_label(input: &str, icon_theme: &IconTheme, size: i32) -> gtk::Bo
|
||||||
|
|
||||||
container.add(&image);
|
container.add(&image);
|
||||||
|
|
||||||
if let Err(err) = ImageProvider::parse(input, icon_theme, size)
|
ImageProvider::parse(input, icon_theme, size)
|
||||||
.and_then(|provider| provider.load_into_image(image))
|
.map(|provider| provider.load_into_image(image));
|
||||||
{
|
|
||||||
error!("{err:?}");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
let label = Label::new(Some(input));
|
let label = Label::new(Some(input));
|
||||||
add_class(&label, "label");
|
add_class(&label, "label");
|
||||||
|
|
|
@ -7,6 +7,7 @@ use gtk::gdk_pixbuf::Pixbuf;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::{IconLookupFlags, IconTheme};
|
use gtk::{IconLookupFlags, IconTheme};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
use tracing::warn;
|
||||||
|
|
||||||
cfg_if!(
|
cfg_if!(
|
||||||
if #[cfg(feature = "http")] {
|
if #[cfg(feature = "http")] {
|
||||||
|
@ -40,9 +41,9 @@ impl<'a> ImageProvider<'a> {
|
||||||
///
|
///
|
||||||
/// Note this checks that icons exist in theme, or files exist on disk
|
/// Note this checks that icons exist in theme, or files exist on disk
|
||||||
/// but no other check is performed.
|
/// but no other check is performed.
|
||||||
pub fn parse(input: &str, theme: &'a IconTheme, size: i32) -> Result<Self> {
|
pub fn parse(input: &str, theme: &'a IconTheme, size: i32) -> Option<Self> {
|
||||||
let location = Self::get_location(input, theme, size)?;
|
let location = Self::get_location(input, theme, size)?;
|
||||||
Ok(Self { location, size })
|
Some(Self { location, size })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the input starts with a prefix
|
/// Returns true if the input starts with a prefix
|
||||||
|
@ -56,44 +57,56 @@ impl<'a> ImageProvider<'a> {
|
||||||
|| input.starts_with("https://")
|
|| input.starts_with("https://")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_location(input: &str, theme: &'a IconTheme, size: i32) -> Result<ImageLocation<'a>> {
|
fn get_location(input: &str, theme: &'a IconTheme, size: i32) -> Option<ImageLocation<'a>> {
|
||||||
let (input_type, input_name) = input
|
let (input_type, input_name) = input
|
||||||
.split_once(':')
|
.split_once(':')
|
||||||
.map_or((None, input), |(t, n)| (Some(t), n));
|
.map_or((None, input), |(t, n)| (Some(t), n));
|
||||||
|
|
||||||
match input_type {
|
match input_type {
|
||||||
Some(input_type) if input_type == "icon" => Ok(ImageLocation::Icon {
|
Some(input_type) if input_type == "icon" => Some(ImageLocation::Icon {
|
||||||
name: input_name.to_string(),
|
name: input_name.to_string(),
|
||||||
theme,
|
theme,
|
||||||
}),
|
}),
|
||||||
Some(input_type) if input_type == "file" => Ok(ImageLocation::Local(PathBuf::from(
|
Some(input_type) if input_type == "file" => Some(ImageLocation::Local(PathBuf::from(
|
||||||
input_name[2..].to_string(),
|
input_name[2..].to_string(),
|
||||||
))),
|
))),
|
||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
Some(input_type) if input_type == "http" || input_type == "https" => {
|
Some(input_type) if input_type == "http" || input_type == "https" => {
|
||||||
Ok(ImageLocation::Remote(input.parse()?))
|
input.parse().ok().map(ImageLocation::Remote)
|
||||||
}
|
}
|
||||||
None if input.starts_with("steam_app_") => Ok(ImageLocation::Steam(
|
None if input.starts_with("steam_app_") => Some(ImageLocation::Steam(
|
||||||
input_name.chars().skip("steam_app_".len()).collect(),
|
input_name.chars().skip("steam_app_".len()).collect(),
|
||||||
)),
|
)),
|
||||||
None if theme
|
None if theme
|
||||||
.lookup_icon(input, size, IconLookupFlags::empty())
|
.lookup_icon(input, size, IconLookupFlags::empty())
|
||||||
.is_some() =>
|
.is_some() =>
|
||||||
{
|
{
|
||||||
Ok(ImageLocation::Icon {
|
Some(ImageLocation::Icon {
|
||||||
name: input_name.to_string(),
|
name: input_name.to_string(),
|
||||||
theme,
|
theme,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Some(input_type) => Err(Report::msg(format!("Unsupported image type: {input_type}"))
|
Some(input_type) => {
|
||||||
.note("You may need to recompile with support if available")),
|
warn!(
|
||||||
None if PathBuf::from(input_name).is_file() => {
|
"{:?}",
|
||||||
Ok(ImageLocation::Local(PathBuf::from(input_name)))
|
Report::msg(format!("Unsupported image type: {input_type}"))
|
||||||
|
.note("You may need to recompile with support if available")
|
||||||
|
);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
None if PathBuf::from(input_name).is_file() => {
|
||||||
|
Some(ImageLocation::Local(PathBuf::from(input_name)))
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
if let Some(location) = get_desktop_icon_name(input_name)
|
||||||
|
.map(|input| Self::get_location(&input, theme, size))
|
||||||
|
{
|
||||||
|
location
|
||||||
|
} else {
|
||||||
|
warn!("Failed to find image: {input}");
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
None => get_desktop_icon_name(input_name).map_or_else(
|
|
||||||
|| Err(Report::msg(format!("Unknown image type: '{input}'"))),
|
|
||||||
|input| Self::get_location(&input, theme, size),
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ use crate::image::ImageProvider;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::Image;
|
use gtk::Image;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use tracing::error;
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
pub struct ImageWidget {
|
pub struct ImageWidget {
|
||||||
|
@ -31,12 +30,8 @@ impl CustomWidget for ImageWidget {
|
||||||
let icon_theme = context.icon_theme.clone();
|
let icon_theme = context.icon_theme.clone();
|
||||||
|
|
||||||
DynamicString::new(&self.src, move |src| {
|
DynamicString::new(&self.src, move |src| {
|
||||||
let res = ImageProvider::parse(&src, &icon_theme, self.size)
|
ImageProvider::parse(&src, &icon_theme, self.size)
|
||||||
.and_then(|image| image.load_into_image(gtk_image.clone()));
|
.map(|image| image.load_into_image(gtk_image.clone()));
|
||||||
|
|
||||||
if let Err(err) = res {
|
|
||||||
error!("{err:?}");
|
|
||||||
}
|
|
||||||
|
|
||||||
Continue(true)
|
Continue(true)
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,7 +11,7 @@ use gtk::Label;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use tokio::spawn;
|
use tokio::spawn;
|
||||||
use tokio::sync::mpsc::{Receiver, Sender};
|
use tokio::sync::mpsc::{Receiver, Sender};
|
||||||
use tracing::{debug, error};
|
use tracing::debug;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
pub struct FocusedModule {
|
pub struct FocusedModule {
|
||||||
|
@ -113,11 +113,8 @@ impl Module<gtk::Box> for FocusedModule {
|
||||||
let icon_theme = icon_theme.clone();
|
let icon_theme = icon_theme.clone();
|
||||||
context.widget_rx.attach(None, move |(name, id)| {
|
context.widget_rx.attach(None, move |(name, id)| {
|
||||||
if self.show_icon {
|
if self.show_icon {
|
||||||
if let Err(err) = ImageProvider::parse(&id, &icon_theme, self.icon_size)
|
ImageProvider::parse(&id, &icon_theme, self.icon_size)
|
||||||
.and_then(|image| image.load_into_image(icon.clone()))
|
.map(|image| image.load_into_image(icon.clone()));
|
||||||
{
|
|
||||||
error!("{err:?}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.show_title {
|
if self.show_title {
|
||||||
|
|
|
@ -192,16 +192,13 @@ impl ItemButton {
|
||||||
let gtk_image = gtk::Image::new();
|
let gtk_image = gtk::Image::new();
|
||||||
let image =
|
let image =
|
||||||
ImageProvider::parse(&item.app_id.clone(), icon_theme, appearance.icon_size);
|
ImageProvider::parse(&item.app_id.clone(), icon_theme, appearance.icon_size);
|
||||||
match image {
|
if let Some(image) = image {
|
||||||
Ok(image) => {
|
button.set_image(Some(>k_image));
|
||||||
button.set_image(Some(>k_image));
|
button.set_always_show_image(true);
|
||||||
button.set_always_show_image(true);
|
|
||||||
|
|
||||||
if let Err(err) = image.load_into_image(gtk_image) {
|
if let Err(err) = image.load_into_image(gtk_image) {
|
||||||
error!("{err:?}");
|
error!("{err:?}");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Err(err) => error!("{err:?}"),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -342,19 +342,15 @@ impl Module<Button> for MusicModule {
|
||||||
let new_cover = update.song.cover_path;
|
let new_cover = update.song.cover_path;
|
||||||
if prev_cover != new_cover {
|
if prev_cover != new_cover {
|
||||||
prev_cover = new_cover.clone();
|
prev_cover = new_cover.clone();
|
||||||
let res = match new_cover.map(|cover_path| {
|
let res = if let Some(image) = new_cover.and_then(|cover_path| {
|
||||||
ImageProvider::parse(&cover_path, &icon_theme, image_size)
|
ImageProvider::parse(&cover_path, &icon_theme, image_size)
|
||||||
}) {
|
}) {
|
||||||
Some(Ok(image)) => image.load_into_image(album_image.clone()),
|
image.load_into_image(album_image.clone())
|
||||||
Some(Err(err)) => {
|
} else {
|
||||||
album_image.set_from_pixbuf(None);
|
album_image.set_from_pixbuf(None);
|
||||||
Err(err)
|
Ok(())
|
||||||
}
|
|
||||||
None => {
|
|
||||||
album_image.set_from_pixbuf(None);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(err) = res {
|
if let Err(err) = res {
|
||||||
error!("{err:?}");
|
error!("{err:?}");
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,11 +180,8 @@ impl Module<gtk::Box> for UpowerModule {
|
||||||
.attach(None, move |properties: UpowerProperties| {
|
.attach(None, move |properties: UpowerProperties| {
|
||||||
let format = format.replace("{percentage}", &properties.percentage.to_string());
|
let format = format.replace("{percentage}", &properties.percentage.to_string());
|
||||||
let icon_name = String::from("icon:") + &properties.icon_name;
|
let icon_name = String::from("icon:") + &properties.icon_name;
|
||||||
if let Err(err) = ImageProvider::parse(&icon_name, &icon_theme, 32)
|
ImageProvider::parse(&icon_name, &icon_theme, 32)
|
||||||
.and_then(|provider| provider.load_into_image(icon.clone()))
|
.map(|provider| provider.load_into_image(icon.clone()));
|
||||||
{
|
|
||||||
error!("{err:?}");
|
|
||||||
}
|
|
||||||
label.set_markup(format.as_ref());
|
label.set_markup(format.as_ref());
|
||||||
Continue(true)
|
Continue(true)
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue