From 1da8122a95c8866ebbbbe51a6c7d04c5a550bdb8 Mon Sep 17 00:00:00 2001 From: Kacper Paczos Date: Sat, 22 Aug 2026 22:32:18 +0200 Subject: [PATCH 1/4] fix: export apps to the menu by desktop-file id, not display name Add To Menu passed the application's display name to distrobox-export --app. --app matches against the desktop file, so a display name that is blank, shared between apps, or matches several files could export the wrong app or more than one. The host side is detected and removed by desktop-file id ({box}-{id}.desktop), so export was keyed on something else entirely. Identify the app by its desktop-file id everywhere: build the exact in-box path (/usr/share/applications/{id}.desktop) and hand that to --app for both export and delete, so one click exports exactly one app and it lines up with detection and removal. The path builder is a small pure function with a test. --- src/distrobox_handler.rs | 47 +++++++++++++++++++++++++++++++++++----- src/main.rs | 6 +++-- 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/src/distrobox_handler.rs b/src/distrobox_handler.rs index 22c6c82..9939657 100644 --- a/src/distrobox_handler.rs +++ b/src/distrobox_handler.rs @@ -232,8 +232,23 @@ pub fn open_terminal_in_box(box_name: String) { } } -/// Exports the desktop file from a box. -pub fn export_app_from_box(app_name: &str, box_name: &str) -> String { +/// The in-container path of an application's desktop file, built from the +/// desktop-file id that `get_apps_in_box` records (the file's basename). +/// distrobox reads a box's apps from `/usr/share/applications`. +fn desktop_file_path(desktop_file: &str) -> String { + format!("/usr/share/applications/{desktop_file}.desktop") +} + +/// Exports an application's desktop file from a box to the host menu. +/// +/// The app is identified by its desktop-file id, not its display name. `--app` +/// matches against the desktop file, and a display name can be empty, repeated +/// across apps, or match several files - which is how a single click could +/// export more than the one app. Handing distrobox the exact file path exports +/// precisely that app, and keeps export in step with how the host copy is +/// detected (`{box}-{id}.desktop`) and removed. +pub fn export_app_from_box(desktop_file: &str, box_name: &str) -> String { + let app_path = desktop_file_path(desktop_file); get_command_output( "distrobox", Some(&[ @@ -242,13 +257,15 @@ pub fn export_app_from_box(app_name: &str, box_name: &str) -> String { "--", "distrobox-export", "--app", - app_name, + &app_path, ]), ) } -/// Unexports a desktop file from the host. -pub fn remove_app_from_host(app_name: &str, box_name: &str) -> String { +/// Unexports an application's desktop file from the host. Identified by the same +/// desktop-file id used to export it, so removal always targets the right app. +pub fn remove_app_from_host(desktop_file: &str, box_name: &str) -> String { + let app_path = desktop_file_path(desktop_file); get_command_output( "distrobox", Some(&[ @@ -257,7 +274,7 @@ pub fn remove_app_from_host(app_name: &str, box_name: &str) -> String { "--", "distrobox-export", "--app", - app_name, + &app_path, "--delete", ]), ) @@ -937,3 +954,21 @@ mod stream_tests { assert!(exists, "streaming create did not produce a listable box"); } } + +#[cfg(test)] +mod export_tests { + use super::desktop_file_path; + + #[test] + fn builds_the_in_container_desktop_path_from_an_id() { + assert_eq!( + desktop_file_path("org.gnome.TextEditor"), + "/usr/share/applications/org.gnome.TextEditor.desktop" + ); + // A plain, single-word id is handled the same way. + assert_eq!( + desktop_file_path("gimp"), + "/usr/share/applications/gimp.desktop" + ); + } +} diff --git a/src/main.rs b/src/main.rs index a20908a..0b9e09f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1440,13 +1440,15 @@ fn on_show_applications_clicked(window: &ApplicationWindow, box_name: String) { } fn add_app_to_menu(app: &DBoxApp, box_name: &str, success_lbl: >k::Label) { - let _ = export_app_from_box(&app.name, box_name); + // Export by the desktop-file id, not the display name, so exactly this one + // app is exported and it matches how the host copy is detected and removed. + let _ = export_app_from_box(&app.desktop_file, box_name); //TRANSLATORS: Success Message success_lbl.set_text(&gettext("App Exported!")); } fn remove_app_from_menu(app: &DBoxApp, box_name: &str, success_lbl: >k::Label) { - let _ = remove_app_from_host(&app.name, box_name); + let _ = remove_app_from_host(&app.desktop_file, box_name); //TRANSLATORS: Success Message success_lbl.set_text(&gettext("App Removed!")); } From bdfe8449dcb563e691363ea498694f8793bbfe9e Mon Sep 17 00:00:00 2001 From: Kacper Paczos Date: Sun, 23 Aug 2026 00:00:52 +0200 Subject: [PATCH 2/4] feat: let each box set the menu label its exported apps get MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit distrobox tags exported apps with "(on )" and has no way to rename a container in place, so this adds a per-box label the user controls instead. A new "Menu Label" row shows the current label and opens a dialog to change it; applying stores the alias in GSettings and re-exports the apps already on the menu so they pick up the new label too. Empty falls back to distrobox's default, so a box nobody touched behaves exactly as before. export_app_from_box gains an optional --export-label, the alias is persisted in a new a{ss} GSettings key, and the (on …) wrapping is a small tested function. --- io.github.dvlv.boxbuddyrs.gschema.xml | 9 +++ src/distrobox_handler.rs | 29 ++++--- src/main.rs | 110 +++++++++++++++++++++++++- src/utils.rs | 27 ++++++- 4 files changed, 159 insertions(+), 16 deletions(-) diff --git a/io.github.dvlv.boxbuddyrs.gschema.xml b/io.github.dvlv.boxbuddyrs.gschema.xml index 19e8785..414460d 100644 --- a/io.github.dvlv.boxbuddyrs.gschema.xml +++ b/io.github.dvlv.boxbuddyrs.gschema.xml @@ -8,5 +8,14 @@ The terminal which should be checked for first when performing an action which spawns a terminal window. + + + {} + Per-box menu label overrides for exported applications + + Maps a box name to the label distrobox-export puts after an exported app's + name in the host menu. Empty means the distrobox default, "(on <box>)". + + diff --git a/src/distrobox_handler.rs b/src/distrobox_handler.rs index 9939657..e92b0b2 100644 --- a/src/distrobox_handler.rs +++ b/src/distrobox_handler.rs @@ -247,19 +247,24 @@ fn desktop_file_path(desktop_file: &str) -> String { /// export more than the one app. Handing distrobox the exact file path exports /// precisely that app, and keeps export in step with how the host copy is /// detected (`{box}-{id}.desktop`) and removed. -pub fn export_app_from_box(desktop_file: &str, box_name: &str) -> String { +/// +/// `label` overrides the text distrobox puts after the app's name in the menu +/// (`--export-label`); `None` leaves distrobox's own default, `(on )`. +pub fn export_app_from_box(desktop_file: &str, box_name: &str, label: Option<&str>) -> String { let app_path = desktop_file_path(desktop_file); - get_command_output( - "distrobox", - Some(&[ - "enter", - box_name, - "--", - "distrobox-export", - "--app", - &app_path, - ]), - ) + let mut args: Vec<&str> = vec![ + "enter", + box_name, + "--", + "distrobox-export", + "--app", + app_path.as_str(), + ]; + if let Some(label) = label { + args.push("--export-label"); + args.push(label); + } + get_command_output("distrobox", Some(&args)) } /// Unexports an application's desktop file from the host. Identified by the same diff --git a/src/main.rs b/src/main.rs index 0b9e09f..8dd163c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,8 +27,9 @@ use distrobox_handler::{ mod utils; use utils::{ get_assemble_icon, get_available_app_icon_name, get_available_icon_name, get_cpu_and_mem_usage, - get_deb_distros, get_distro_img, get_download_dir_path, get_my_deb_boxes, get_my_rpm_boxes, - get_rpm_distros, get_supported_terminals, get_supported_terminals_list, + get_deb_distros, get_distro_img, get_download_dir_path, get_exported_app_label, get_my_deb_boxes, + get_my_rpm_boxes, get_rpm_distros, set_exported_app_label, get_supported_terminals, + get_supported_terminals_list, get_terminal_and_separator_arg, has_distrobox_installed, has_file_extension, has_host_access, has_podman_or_docker_installed, set_up_localisation, ADD_ICON_NAMES, APPLICATIONS_ICON_NAMES, ASSEMBLE_FALLBACK_ICON_NAMES, COPY_ICON_NAMES, INFO_ICON_NAMES, INSTALL_PACKAGE_ICON_NAMES, @@ -515,6 +516,25 @@ fn make_box_tab(dbox: &DBox, window: &ApplicationWindow, tab_num: u32) -> gtk::B on_show_applications_clicked(&win_clone, show_bn_clone.clone()); }); + // Menu-label row: sets the "(on …)" label used for this box's exported apps. + let menu_label_icon = gtk::Image::from_icon_name(&get_available_icon_name(INFO_ICON_NAMES)); + let menu_label_row = ActionRow::new(); + // TRANSLATORS: Row Label - opens a dialog to set the menu label for exported apps + menu_label_row.set_title(&gettext("Menu Label")); + menu_label_row.set_subtitle(&format!( + "{} \"(on {})\"", + // TRANSLATORS: Row subtitle prefix, followed by the current menu label + gettext("Exported apps show"), + get_exported_app_label(&box_name).unwrap_or_else(|| box_name.clone()) + )); + menu_label_row.add_suffix(&menu_label_icon); + menu_label_row.set_activatable(true); + let ml_bn_clone = box_name.clone(); + let ml_win = window.clone(); + menu_label_row.connect_activated(move |_row| { + show_menu_label_dialog(&ml_win, ml_bn_clone.clone()); + }); + // Install Deb Icon let deb_bn_clone = box_name.clone(); let install_deb_icon = @@ -555,6 +575,7 @@ fn make_box_tab(dbox: &DBox, window: &ApplicationWindow, tab_num: u32) -> gtk::B boxed_list.append(&open_terminal_row); boxed_list.append(&upgrade_row); boxed_list.append(&show_applications_row); + boxed_list.append(&menu_label_row); // Make deb / rpm row if applicable let deb_distros = get_deb_distros(); @@ -1439,14 +1460,86 @@ fn on_show_applications_clicked(window: &ApplicationWindow, box_name: String) { )); } +fn show_menu_label_dialog(window: &ApplicationWindow, box_name: String) { + let dialog = adw::MessageDialog::new( + Some(window), + // TRANSLATORS: Title of the dialog that sets a box's exported-app menu label + Some(&gettext("Menu Label")), + // TRANSLATORS: Body of the menu-label dialog + Some(&gettext( + "Set the name shown in the menu after each exported app, as \"(on …)\". Leave empty to use the box name.", + )), + ); + dialog.set_transient_for(Some(window)); + + let entry = adw::EntryRow::new(); + // TRANSLATORS: Entry field label in the menu-label dialog + entry.set_title(&gettext("Menu label")); + if let Some(current) = get_exported_app_label(&box_name) { + entry.set_text(¤t); + } + + let group = adw::PreferencesGroup::new(); + group.add(&entry); + dialog.set_extra_child(Some(&group)); + + // TRANSLATORS: Button + dialog.add_response("cancel", &gettext("Cancel")); + // TRANSLATORS: Button + dialog.add_response("apply", &gettext("Apply")); + dialog.set_response_appearance("apply", adw::ResponseAppearance::Suggested); + dialog.set_default_response(Some("apply")); + dialog.set_close_response("cancel"); + + let window_clone = window.clone(); + dialog.connect_response(None, move |dialog, res| { + if res == "apply" { + set_exported_app_label(&box_name, &entry.text()); + // Bring the entries already in the menu up to date with the new label. + reexport_box_apps(&box_name); + dialog.close(); + delayed_rerender(&window_clone, None); + } + }); + + dialog.present(); +} + fn add_app_to_menu(app: &DBoxApp, box_name: &str, success_lbl: >k::Label) { // Export by the desktop-file id, not the display name, so exactly this one // app is exported and it matches how the host copy is detected and removed. - let _ = export_app_from_box(&app.desktop_file, box_name); + let label = menu_label_for_export(box_name); + let _ = export_app_from_box(&app.desktop_file, box_name, label.as_deref()); //TRANSLATORS: Success Message success_lbl.set_text(&gettext("App Exported!")); } +/// The `--export-label` to hand distrobox for a box, or `None` for its default. +/// A custom alias is shown in the same `(on …)` shape distrobox uses, so a box +/// with no alias set behaves exactly as before. +fn menu_label_for_export(box_name: &str) -> Option { + get_exported_app_label(box_name).map(|alias| format_export_label(&alias)) +} + +/// Wraps a box alias in the `(on …)` shape distrobox uses for its own labels, so +/// a custom alias and the default read the same way in the menu. +fn format_export_label(alias: &str) -> String { + format!("(on {alias})") +} + +/// Re-applies the current menu label to every app already exported from a box, +/// by unexporting and re-exporting each one. Used after the alias changes so the +/// entries already in the menu pick up the new label too. +fn reexport_box_apps(box_name: &str) { + let label = menu_label_for_export(box_name); + for app in get_apps_in_box(box_name) { + if app.is_on_host { + let _ = remove_app_from_host(&app.desktop_file, box_name); + let _ = export_app_from_box(&app.desktop_file, box_name, label.as_deref()); + } + } +} + fn remove_app_from_menu(app: &DBoxApp, box_name: &str, success_lbl: >k::Label) { let _ = remove_app_from_host(&app.desktop_file, box_name); //TRANSLATORS: Success Message @@ -2083,3 +2176,14 @@ fn show_preferred_terminal_popup(window: &ApplicationWindow) { term_pref_popup.set_child(Some(&main_box)); term_pref_popup.present(); } + +#[cfg(test)] +mod menu_label_tests { + use super::format_export_label; + + #[test] + fn alias_is_wrapped_the_same_way_distrobox_labels_are() { + assert_eq!(format_export_label("work"), "(on work)"); + assert_eq!(format_export_label("my box"), "(on my box)"); + } +} diff --git a/src/utils.rs b/src/utils.rs index 20f3743..dff9a6a 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,7 +1,7 @@ use adw::StyleManager; use gettextrs::{bind_textdomain_codeset, setlocale, textdomain, LocaleCategory}; use gtk::gio::Settings; -use gtk::prelude::SettingsExt; +use gtk::prelude::{SettingsExt, SettingsExtManual}; use std::collections::HashMap; use std::env; use std::path::Path; @@ -890,6 +890,31 @@ pub fn get_download_dir_path() -> String { }) } +/// The custom menu-label alias the user set for a box, or `None` for the +/// distrobox default. Stored per box in GSettings, keyed by box name. +pub fn get_exported_app_label(box_name: &str) -> Option { + let settings = Settings::new(APP_ID); + let labels: HashMap = settings.get("exported-app-labels"); + labels + .get(box_name) + .map(|s| s.trim().to_string()) + .filter(|s| !s.is_empty()) +} + +/// Sets (or, for an empty value, clears) the custom menu-label alias for a box. +/// Clearing it means exports fall back to distrobox's own "(on )" label. +pub fn set_exported_app_label(box_name: &str, label: &str) { + let settings = Settings::new(APP_ID); + let mut labels: HashMap = settings.get("exported-app-labels"); + let trimmed = label.trim(); + if trimmed.is_empty() { + labels.remove(box_name); + } else { + labels.insert(box_name.to_string(), trimmed.to_string()); + } + let _ = settings.set("exported-app-labels", &labels); +} + #[cfg(test)] mod tests { use super::{detect_pkg_manager, PkgManager}; From b1cc453b1024e8ffecdccac22e717eb702efd059 Mon Sep 17 00:00:00 2001 From: Kacper Paczos Date: Sun, 23 Aug 2026 09:59:58 +0200 Subject: [PATCH 3/4] simplify: one label helper, keep the tab, Enter applies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The "(on …)" wrapping lived in its own function with a test, and the row subtitle spelled the shape out a third time by hand; one helper now formats it for export and display alike. Applying the dialog goes back to the box's own tab instead of the first one, Enter in the entry triggers Apply, and the redundant transient/close calls are gone. --- src/main.rs | 64 +++++++++++++++++++---------------------------------- 1 file changed, 23 insertions(+), 41 deletions(-) diff --git a/src/main.rs b/src/main.rs index 8dd163c..ef13cfa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,9 @@ use std::path::Path; use std::thread; use adw::{ - prelude::{ActionRowExt, MessageDialogExt, PreferencesGroupExt, PreferencesRowExt}, + prelude::{ + ActionRowExt, EntryRowExt, MessageDialogExt, PreferencesGroupExt, PreferencesRowExt, + }, ActionRow, Application, StyleManager, ToastOverlay, }; use gtk::{ @@ -27,13 +29,13 @@ use distrobox_handler::{ mod utils; use utils::{ get_assemble_icon, get_available_app_icon_name, get_available_icon_name, get_cpu_and_mem_usage, - get_deb_distros, get_distro_img, get_download_dir_path, get_exported_app_label, get_my_deb_boxes, - get_my_rpm_boxes, get_rpm_distros, set_exported_app_label, get_supported_terminals, - get_supported_terminals_list, - get_terminal_and_separator_arg, has_distrobox_installed, has_file_extension, has_host_access, - has_podman_or_docker_installed, set_up_localisation, ADD_ICON_NAMES, APPLICATIONS_ICON_NAMES, - ASSEMBLE_FALLBACK_ICON_NAMES, COPY_ICON_NAMES, INFO_ICON_NAMES, INSTALL_PACKAGE_ICON_NAMES, - MENU_ICON_NAMES, OPEN_FILE_ICON_NAMES, REMOVE_ICON_NAMES, STOP_ICON_NAMES, TERMINAL_ICON_NAMES, + get_deb_distros, get_distro_img, get_download_dir_path, get_exported_app_label, + get_my_deb_boxes, get_my_rpm_boxes, get_rpm_distros, get_supported_terminals, + get_supported_terminals_list, get_terminal_and_separator_arg, has_distrobox_installed, + has_file_extension, has_host_access, has_podman_or_docker_installed, set_exported_app_label, + set_up_localisation, ADD_ICON_NAMES, APPLICATIONS_ICON_NAMES, ASSEMBLE_FALLBACK_ICON_NAMES, + COPY_ICON_NAMES, INFO_ICON_NAMES, INSTALL_PACKAGE_ICON_NAMES, MENU_ICON_NAMES, + OPEN_FILE_ICON_NAMES, REMOVE_ICON_NAMES, STOP_ICON_NAMES, TERMINAL_ICON_NAMES, TRASH_ICON_NAMES, UPGRADE_ICON_NAMES, WARNING_ICON_NAMES, }; const APP_ID: &str = "io.github.dvlv.boxbuddyrs"; @@ -522,17 +524,17 @@ fn make_box_tab(dbox: &DBox, window: &ApplicationWindow, tab_num: u32) -> gtk::B // TRANSLATORS: Row Label - opens a dialog to set the menu label for exported apps menu_label_row.set_title(&gettext("Menu Label")); menu_label_row.set_subtitle(&format!( - "{} \"(on {})\"", + "{} \"{}\"", // TRANSLATORS: Row subtitle prefix, followed by the current menu label gettext("Exported apps show"), - get_exported_app_label(&box_name).unwrap_or_else(|| box_name.clone()) + menu_label_for_export(&box_name).unwrap_or_else(|| format!("(on {box_name})")) )); menu_label_row.add_suffix(&menu_label_icon); menu_label_row.set_activatable(true); let ml_bn_clone = box_name.clone(); let ml_win = window.clone(); menu_label_row.connect_activated(move |_row| { - show_menu_label_dialog(&ml_win, ml_bn_clone.clone()); + show_menu_label_dialog(&ml_win, ml_bn_clone.clone(), tab_num); }); // Install Deb Icon @@ -1460,7 +1462,7 @@ fn on_show_applications_clicked(window: &ApplicationWindow, box_name: String) { )); } -fn show_menu_label_dialog(window: &ApplicationWindow, box_name: String) { +fn show_menu_label_dialog(window: &ApplicationWindow, box_name: String, tab_num: u32) { let dialog = adw::MessageDialog::new( Some(window), // TRANSLATORS: Title of the dialog that sets a box's exported-app menu label @@ -1470,11 +1472,11 @@ fn show_menu_label_dialog(window: &ApplicationWindow, box_name: String) { "Set the name shown in the menu after each exported app, as \"(on …)\". Leave empty to use the box name.", )), ); - dialog.set_transient_for(Some(window)); let entry = adw::EntryRow::new(); // TRANSLATORS: Entry field label in the menu-label dialog entry.set_title(&gettext("Menu label")); + entry.set_activates_default(true); if let Some(current) = get_exported_app_label(&box_name) { entry.set_text(¤t); } @@ -1492,14 +1494,11 @@ fn show_menu_label_dialog(window: &ApplicationWindow, box_name: String) { dialog.set_close_response("cancel"); let window_clone = window.clone(); - dialog.connect_response(None, move |dialog, res| { - if res == "apply" { - set_exported_app_label(&box_name, &entry.text()); - // Bring the entries already in the menu up to date with the new label. - reexport_box_apps(&box_name); - dialog.close(); - delayed_rerender(&window_clone, None); - } + dialog.connect_response(Some("apply"), move |_dialog, _res| { + set_exported_app_label(&box_name, &entry.text()); + // Bring the entries already in the menu up to date with the new label. + reexport_box_apps(&box_name); + delayed_rerender(&window_clone, Some(tab_num)); }); dialog.present(); @@ -1515,16 +1514,10 @@ fn add_app_to_menu(app: &DBoxApp, box_name: &str, success_lbl: >k::Label) { } /// The `--export-label` to hand distrobox for a box, or `None` for its default. -/// A custom alias is shown in the same `(on …)` shape distrobox uses, so a box -/// with no alias set behaves exactly as before. +/// A custom alias is wrapped in the same `(on …)` shape distrobox uses, so a +/// box with no alias set behaves exactly as before. fn menu_label_for_export(box_name: &str) -> Option { - get_exported_app_label(box_name).map(|alias| format_export_label(&alias)) -} - -/// Wraps a box alias in the `(on …)` shape distrobox uses for its own labels, so -/// a custom alias and the default read the same way in the menu. -fn format_export_label(alias: &str) -> String { - format!("(on {alias})") + get_exported_app_label(box_name).map(|alias| format!("(on {alias})")) } /// Re-applies the current menu label to every app already exported from a box, @@ -2176,14 +2169,3 @@ fn show_preferred_terminal_popup(window: &ApplicationWindow) { term_pref_popup.set_child(Some(&main_box)); term_pref_popup.present(); } - -#[cfg(test)] -mod menu_label_tests { - use super::format_export_label; - - #[test] - fn alias_is_wrapped_the_same_way_distrobox_labels_are() { - assert_eq!(format_export_label("work"), "(on work)"); - assert_eq!(format_export_label("my box"), "(on my box)"); - } -} From d2a65e88e2760ac49a6d69eb8f5625af9d8bb81e Mon Sep 17 00:00:00 2001 From: Kacper Paczos Date: Mon, 24 Aug 2026 13:26:08 +0200 Subject: [PATCH 4/4] fix: give the Menu Label row an edit icon that resolves as symbolic The row edits a label, so document-edit-symbolic fits better than the info icon - and Breeze has no dialog-information-symbolic, which made the row fall back to a full-colour icon in an otherwise monochrome list. document-edit-symbolic exists in both Adwaita and Breeze. --- src/main.rs | 7 ++++--- src/utils.rs | 10 ++++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index ef13cfa..577ff60 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,8 +35,8 @@ use utils::{ has_file_extension, has_host_access, has_podman_or_docker_installed, set_exported_app_label, set_up_localisation, ADD_ICON_NAMES, APPLICATIONS_ICON_NAMES, ASSEMBLE_FALLBACK_ICON_NAMES, COPY_ICON_NAMES, INFO_ICON_NAMES, INSTALL_PACKAGE_ICON_NAMES, MENU_ICON_NAMES, - OPEN_FILE_ICON_NAMES, REMOVE_ICON_NAMES, STOP_ICON_NAMES, TERMINAL_ICON_NAMES, - TRASH_ICON_NAMES, UPGRADE_ICON_NAMES, WARNING_ICON_NAMES, + MENU_LABEL_ICON_NAMES, OPEN_FILE_ICON_NAMES, REMOVE_ICON_NAMES, STOP_ICON_NAMES, + TERMINAL_ICON_NAMES, TRASH_ICON_NAMES, UPGRADE_ICON_NAMES, WARNING_ICON_NAMES, }; const APP_ID: &str = "io.github.dvlv.boxbuddyrs"; @@ -519,7 +519,8 @@ fn make_box_tab(dbox: &DBox, window: &ApplicationWindow, tab_num: u32) -> gtk::B }); // Menu-label row: sets the "(on …)" label used for this box's exported apps. - let menu_label_icon = gtk::Image::from_icon_name(&get_available_icon_name(INFO_ICON_NAMES)); + let menu_label_icon = + gtk::Image::from_icon_name(&get_available_icon_name(MENU_LABEL_ICON_NAMES)); let menu_label_row = ActionRow::new(); // TRANSLATORS: Row Label - opens a dialog to set the menu label for exported apps menu_label_row.set_title(&gettext("Menu Label")); diff --git a/src/utils.rs b/src/utils.rs index dff9a6a..d65b9e0 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -139,6 +139,16 @@ pub const UPGRADE_ICON_NAMES: &[&str] = &[ ]; pub const WARNING_ICON_NAMES: &[&str] = &["dialog-warning-symbolic", "dialog-warning"]; pub const INFO_ICON_NAMES: &[&str] = &["dialog-information-symbolic", "dialog-information"]; +// The Menu Label row edits a label, so an edit icon fits better than an +// info one - and Breeze has no dialog-information-symbolic, which made the +// row fall back to a full-colour icon in an otherwise monochrome list. +// document-edit-symbolic exists in both Adwaita and Breeze. +pub const MENU_LABEL_ICON_NAMES: &[&str] = &[ + "document-edit-symbolic", + "tag-symbolic", + "dialog-information-symbolic", + "dialog-information", +]; pub const APPLICATIONS_ICON_NAMES: &[&str] = &[ "application-x-executable-symbolic", "application-x-executable",