1
0
Fork 0
mirror of https://github.com/Zedfrigg/ironbar.git synced 2025-08-16 22:31:03 +02:00

Merge pull request #746 from JakeStanger/fix/markup-escape

fix: markup escape issues
This commit is contained in:
Jake Stanger 2024-10-15 22:14:15 +01:00 committed by GitHub
commit 6240b4b4fd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 51 additions and 30 deletions

View file

@ -22,7 +22,7 @@ enum DynamicStringSegment {
/// ///
/// ```rs /// ```rs
/// dynamic_string(&text, move |string| { /// dynamic_string(&text, move |string| {
/// label.set_markup(&string); /// label.set_label_escaped(&string);
/// }); /// });
/// ``` /// ```
pub fn dynamic_string<F>(input: &str, mut f: F) pub fn dynamic_string<F>(input: &str, mut f: F)

View file

@ -1,4 +1,4 @@
use glib::IsA; use glib::{markup_escape_text, IsA};
use gtk::prelude::*; use gtk::prelude::*;
use gtk::{Orientation, Widget}; use gtk::{Orientation, Widget};
@ -75,3 +75,22 @@ impl<W: IsA<Widget>> IronbarGtkExt for W {
unsafe { self.set_data(key, value) } unsafe { self.set_data(key, value) }
} }
} }
pub trait IronbarLabelExt {
/// Sets the label value to the provided string.
///
/// If the label does not contain markup `span` tags,
/// the text is escaped to avoid issues with special characters (ie `&`).
/// Otherwise, the text is used verbatim, and it is up to the user to escape.
fn set_label_escaped(&self, label: &str);
}
impl IronbarLabelExt for gtk::Label {
fn set_label_escaped(&self, label: &str) {
if !label.contains("<span") {
self.set_label(&markup_escape_text(label));
} else {
self.set_label(label);
}
}
}

View file

@ -2,13 +2,13 @@ use gtk::prelude::*;
use gtk::{Button, Label, Orientation}; use gtk::{Button, Label, Orientation};
use serde::Deserialize; use serde::Deserialize;
use super::{CustomWidget, CustomWidgetContext, ExecEvent, WidgetConfig};
use crate::config::ModuleOrientation; use crate::config::ModuleOrientation;
use crate::dynamic_value::dynamic_string; use crate::dynamic_value::dynamic_string;
use crate::gtk_helpers::IronbarLabelExt;
use crate::modules::PopupButton; use crate::modules::PopupButton;
use crate::{build, try_send}; use crate::{build, try_send};
use super::{CustomWidget, CustomWidgetContext, ExecEvent, WidgetConfig};
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ButtonWidget { pub struct ButtonWidget {
@ -75,7 +75,7 @@ impl CustomWidget for ButtonWidget {
button.add(&label); button.add(&label);
dynamic_string(&text, move |string| { dynamic_string(&text, move |string| {
label.set_markup(&string); label.set_label_escaped(&string);
}); });
} }

View file

@ -2,11 +2,11 @@ use gtk::prelude::*;
use gtk::Label; use gtk::Label;
use serde::Deserialize; use serde::Deserialize;
use super::{CustomWidget, CustomWidgetContext};
use crate::build; use crate::build;
use crate::config::ModuleOrientation; use crate::config::ModuleOrientation;
use crate::dynamic_value::dynamic_string; use crate::dynamic_value::dynamic_string;
use crate::gtk_helpers::IronbarLabelExt;
use super::{CustomWidget, CustomWidgetContext};
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
@ -50,7 +50,7 @@ impl CustomWidget for LabelWidget {
{ {
let label = label.clone(); let label = label.clone();
dynamic_string(&self.label, move |string| { dynamic_string(&self.label, move |string| {
label.set_markup(&string); label.set_label_escaped(&string);
}); });
} }

View file

@ -1,9 +1,9 @@
use crate::config::CommonConfig; use crate::config::CommonConfig;
use crate::dynamic_value::dynamic_string; use crate::dynamic_value::dynamic_string;
use crate::gtk_helpers::IronbarLabelExt;
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext}; use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
use crate::{glib_recv, module_impl, try_send}; use crate::{glib_recv, module_impl, try_send};
use color_eyre::Result; use color_eyre::Result;
use gtk::prelude::*;
use gtk::Label; use gtk::Label;
use serde::Deserialize; use serde::Deserialize;
use tokio::sync::mpsc; use tokio::sync::mpsc;
@ -56,12 +56,11 @@ impl Module<Label> for LabelModule {
context: WidgetContext<Self::SendMessage, Self::ReceiveMessage>, context: WidgetContext<Self::SendMessage, Self::ReceiveMessage>,
_info: &ModuleInfo, _info: &ModuleInfo,
) -> Result<ModuleParts<Label>> { ) -> Result<ModuleParts<Label>> {
let label = Label::new(None); let label = Label::builder().use_markup(true).build();
label.set_use_markup(true);
{ {
let label = label.clone(); let label = label.clone();
glib_recv!(context.subscribe(), string => label.set_markup(&string)); glib_recv!(context.subscribe(), string => label.set_label_escaped(&string));
} }
Ok(ModuleParts { Ok(ModuleParts {

View file

@ -5,7 +5,7 @@ use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use color_eyre::Result; use color_eyre::Result;
use glib::{markup_escape_text, Propagation, PropertySet}; use glib::{Propagation, PropertySet};
use gtk::prelude::*; use gtk::prelude::*;
use gtk::{Button, IconTheme, Label, Orientation, Scale}; use gtk::{Button, IconTheme, Label, Orientation, Scale};
use regex::Regex; use regex::Regex;
@ -16,7 +16,7 @@ use crate::clients::music::{
self, MusicClient, PlayerState, PlayerUpdate, ProgressTick, Status, Track, self, MusicClient, PlayerState, PlayerUpdate, ProgressTick, Status, Track,
}; };
use crate::clients::Clients; use crate::clients::Clients;
use crate::gtk_helpers::IronbarGtkExt; use crate::gtk_helpers::{IronbarGtkExt, IronbarLabelExt};
use crate::image::{new_icon_button, new_icon_label, ImageProvider}; use crate::image::{new_icon_button, new_icon_label, ImageProvider};
use crate::modules::PopupButton; use crate::modules::PopupButton;
use crate::modules::{ use crate::modules::{
@ -189,10 +189,11 @@ impl Module<Button> for MusicModule {
let icon_play = new_icon_label(&self.icons.play, info.icon_theme, self.icon_size); let icon_play = new_icon_label(&self.icons.play, info.icon_theme, self.icon_size);
let icon_pause = new_icon_label(&self.icons.pause, info.icon_theme, self.icon_size); let icon_pause = new_icon_label(&self.icons.pause, info.icon_theme, self.icon_size);
let label = Label::new(None);
label.set_use_markup(true); let label = Label::builder()
label.set_angle(info.bar_position.get_angle()); .use_markup(true)
.angle(info.bar_position.get_angle())
.build();
if let Some(truncate) = self.truncate { if let Some(truncate) = self.truncate {
truncate.truncate_label(&label); truncate.truncate_label(&label);
@ -222,7 +223,7 @@ impl Module<Button> for MusicModule {
}; };
if let Some(event) = event.take() { if let Some(event) = event.take() {
label.set_label(&event.display_string); label.set_label_escaped(&event.display_string);
button.show(); button.show();
@ -473,7 +474,7 @@ impl Module<Button> for MusicModule {
if let (Some(elapsed), Some(duration)) = if let (Some(elapsed), Some(duration)) =
(progress_tick.elapsed, progress_tick.duration) (progress_tick.elapsed, progress_tick.duration)
{ {
progress_label.set_label(&format!( progress_label.set_label_escaped(&format!(
"{}/{}", "{}/{}",
format_time(elapsed), format_time(elapsed),
format_time(duration) format_time(duration)
@ -498,7 +499,7 @@ impl Module<Button> for MusicModule {
fn update_popup_metadata_label(text: Option<String>, label: &IconLabel) { fn update_popup_metadata_label(text: Option<String>, label: &IconLabel) {
match text { match text {
Some(value) => { Some(value) => {
label.label.set_text(&value); label.label.set_label_escaped(&value);
label.container.show_all(); label.container.show_all();
} }
None => { None => {
@ -531,7 +532,6 @@ fn get_token_value(song: &Track, token: &str) -> String {
"track" => song.track.map(|x| x.to_string()), "track" => song.track.map(|x| x.to_string()),
_ => Some(token.to_string()), _ => Some(token.to_string()),
} }
.map(|str| markup_escape_text(str.as_str()).to_string())
.unwrap_or_default() .unwrap_or_default()
} }

View file

@ -1,4 +1,5 @@
use crate::config::CommonConfig; use crate::config::CommonConfig;
use crate::gtk_helpers::IronbarLabelExt;
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext}; use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
use crate::script::{OutputStream, Script, ScriptMode}; use crate::script::{OutputStream, Script, ScriptMode};
use crate::{glib_recv, module_impl, spawn, try_send}; use crate::{glib_recv, module_impl, spawn, try_send};
@ -103,7 +104,7 @@ impl Module<Label> for ScriptModule {
{ {
let label = label.clone(); let label = label.clone();
glib_recv!(context.subscribe(), s => label.set_markup(s.as_str())); glib_recv!(context.subscribe(), s => label.set_label_escaped(&s));
} }
Ok(ModuleParts { Ok(ModuleParts {

View file

@ -1,4 +1,5 @@
use crate::config::{CommonConfig, TruncateMode}; use crate::config::{CommonConfig, TruncateMode};
use crate::gtk_helpers::IronbarLabelExt;
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext}; use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
use crate::{await_sync, glib_recv, module_impl, try_send}; use crate::{await_sync, glib_recv, module_impl, try_send};
use color_eyre::{Report, Result}; use color_eyre::{Report, Result};
@ -59,6 +60,7 @@ impl Module<Label> for SwayModeModule {
_info: &ModuleInfo, _info: &ModuleInfo,
) -> Result<ModuleParts<Label>> { ) -> Result<ModuleParts<Label>> {
let label = Label::new(None); let label = Label::new(None);
label.set_use_markup(true);
{ {
let label = label.clone(); let label = label.clone();
@ -71,9 +73,9 @@ impl Module<Label> for SwayModeModule {
trace!("mode: {:?}", mode); trace!("mode: {:?}", mode);
label.set_use_markup(mode.pango_markup); label.set_use_markup(mode.pango_markup);
if mode.change == "default" { if mode.change == "default" {
label.set_markup(""); label.set_label_escaped("");
} else { } else {
label.set_markup(&mode.change); label.set_label_escaped(&mode.change);
} }
}; };

View file

@ -1,5 +1,5 @@
use crate::config::{CommonConfig, ModuleOrientation}; use crate::config::{CommonConfig, ModuleOrientation};
use crate::gtk_helpers::IronbarGtkExt; use crate::gtk_helpers::{IronbarGtkExt, IronbarLabelExt};
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext}; use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
use crate::{glib_recv, module_impl, send_async, spawn}; use crate::{glib_recv, module_impl, send_async, spawn};
use color_eyre::Result; use color_eyre::Result;
@ -266,7 +266,7 @@ impl Module<gtk::Box> for SysInfoModule {
.to_string() .to_string()
}); });
label.set_markup(format_compiled.as_ref()); label.set_label_escaped(format_compiled.as_ref());
} }
}); });
} }

View file

@ -9,7 +9,7 @@ use zbus;
use zbus::fdo::PropertiesProxy; use zbus::fdo::PropertiesProxy;
use crate::config::CommonConfig; use crate::config::CommonConfig;
use crate::gtk_helpers::IronbarGtkExt; use crate::gtk_helpers::{IronbarGtkExt, IronbarLabelExt};
use crate::image::ImageProvider; use crate::image::ImageProvider;
use crate::modules::PopupButton; use crate::modules::PopupButton;
use crate::modules::{ use crate::modules::{
@ -212,7 +212,7 @@ impl Module<gtk::Button> for UpowerModule {
ImageProvider::parse(&icon_name, &icon_theme, false, self.icon_size) ImageProvider::parse(&icon_name, &icon_theme, false, self.icon_size)
.map(|provider| provider.load_into_image(icon.clone())); .map(|provider| provider.load_into_image(icon.clone()));
label.set_markup(format.as_ref()); label.set_label_escaped(&format);
}); });
let rx = context.subscribe(); let rx = context.subscribe();
@ -237,7 +237,7 @@ impl Module<gtk::Button> for UpowerModule {
.orientation(Orientation::Horizontal) .orientation(Orientation::Horizontal)
.build(); .build();
let label = Label::new(None); let label = Label::builder().use_markup(true).build();
label.add_class("upower-details"); label.add_class("upower-details");
container.add(&label); container.add(&label);
@ -263,7 +263,7 @@ impl Module<gtk::Button> for UpowerModule {
_ => String::new(), _ => String::new(),
}; };
label.set_markup(&format); label.set_label_escaped(&format);
}); });
container.show_all(); container.show_all();