From 9b7e065b0f9f9b802720870a283ecfa31c72847c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Wed, 8 Dec 2021 14:18:14 +0100 Subject: [PATCH] popover: Move Emoji and Terminal to ui file This allows them to be translated via po so we don't have to maintain the translation list by hand or care about empty translation files. The only downside is that the "overlay layouts" in OVERLAY_NAMES need to match the ones in the ui file but since a missing one is a clean crash when selected there's little potential for subtle breackage. We could even ensure consistency by comparing the two at run time but they change only slowly this is not much of an issue (compared to how e.g. new languages can be added now). --- data/popup.ui | 13 +++++- src/popover.rs | 121 +++++++++++++------------------------------------ 2 files changed, 43 insertions(+), 91 deletions(-) diff --git a/data/popup.ui b/data/popup.ui index 214fbea6..94b15e1e 100644 --- a/data/popup.ui +++ b/data/popup.ui @@ -1,7 +1,16 @@ - - + + + Emoji + layout + emoji + + + Terminal + layout + terminal +
Keyboard Settings diff --git a/src/popover.rs b/src/popover.rs index 9a1b6902..e2b8aebf 100644 --- a/src/popover.rs +++ b/src/popover.rs @@ -20,10 +20,9 @@ use gio::SimpleActionExt; use glib::translate::FromGlibPtrNone; use glib::variant::ToVariant; #[cfg(not(feature = "gtk_v0_5"))] -use gtk::BuilderExtManual; +use gtk::prelude::*; use gtk::PopoverExt; use gtk::WidgetExt; -use std::io::Write; use ::logging::Warn; mod c { @@ -111,46 +110,6 @@ mod variants { } } -fn make_menu_builder(inputs: Vec<(&str, OwnedTranslation)>) -> gtk::Builder { - let mut xml: Vec = Vec::new(); - writeln!( - xml, - " - - -
" - ).unwrap(); - for (input_name, translation) in inputs { - writeln!( - xml, - " - - {} - layout - {} - ", - translation.0, - input_name, - ).unwrap(); - } - writeln!( - xml, - " -
-
- - Keyboard Settings - settings - -
-
-
" - ).unwrap(); - gtk::Builder::new_from_string( - &String::from_utf8(xml).expect("Bad menu definition") - ) -} - fn get_settings(schema_name: &str) -> Option { let mut error_handler = logging::Print{}; gio::SettingsSchemaSource::get_default() @@ -350,12 +309,12 @@ pub fn show( .chain(overlay_layouts) .collect(); - let translated_names = translate_layout_names(&all_layouts); - - // sorted collection of human and machine names + let translated_names = translate_layout_names(&system_layouts); + + // sorted collection of language layouts let mut human_names: Vec<(OwnedTranslation, LayoutId)> = translated_names .into_iter() - .zip(all_layouts.clone().into_iter()) + .zip(system_layouts.clone().into_iter()) .collect(); human_names.sort_unstable_by(|(tr_a, layout_a), (tr_b, layout_b)| { @@ -367,32 +326,14 @@ pub fn show( } }); - // GVariant doesn't natively support `enum`s, - // so the `choices` vector will serve as a lookup table. - let choices_with_translations: Vec<(String, (OwnedTranslation, LayoutId))> - = human_names.into_iter() - .enumerate() - .map(|(i, human_entry)| {( - format!("{}_{}", i, human_entry.1.get_name()), - human_entry, - )}).collect(); + let builder = gtk::Builder::new_from_resource("/sm/puri/squeekboard/popup.ui"); + let model: gio::Menu = builder.get_object("app-menu").unwrap(); - - let builder = make_menu_builder( - choices_with_translations.iter() - .map(|(id, (translation, _))| (id.as_str(), (*translation).clone())) - .collect() - ); - - let choices: Vec<(String, LayoutId)> - = choices_with_translations.into_iter() - .map(|(id, (_tr, layout))| (id, layout)) - .collect(); - - // Much more debuggable to populate the model & menu - // from a string representation - // than add items imperatively - let model: gio::MenuModel = builder.get_object("app-menu").unwrap(); + for (tr, l) in human_names.iter().rev() { + let detailed_action = format!("layout::{}", l.get_name()); + let item = gio::MenuItem::new(Some(&tr.0), Some(detailed_action.as_str())); + model.prepend_item (&item); + } let menu = gtk::Popover::new_from_model(Some(&window), &model); menu.set_pointing_to(>k::Rectangle { @@ -403,32 +344,36 @@ pub fn show( }); menu.set_constrain_to(gtk::PopoverConstraint::None); + let action_group = gio::SimpleActionGroup::new(); + if let Some(current_layout) = get_current_layout(manager, &system_layouts) { - let current_name_variant = choices.iter() + let current_layout_name = all_layouts.iter() .find( - |(_id, layout)| layout == ¤t_layout + |l| l.get_name() == current_layout.get_name() ).unwrap() - .0.to_variant(); + .get_name(); + log_print!(logging::Level::Debug, "Current Layout {}", current_layout_name); let layout_action = gio::SimpleAction::new_stateful( "layout", - Some(current_name_variant.type_()), - ¤t_name_variant, + Some(current_layout_name.to_variant().type_()), + ¤t_layout_name.to_variant() ); let menu_inner = menu.clone(); layout_action.connect_change_state(move |_action, state| { match state { Some(v) => { + log_print!(logging::Level::Debug, "Selected layout {}", v); v.get::() .or_print( logging::Problem::Bug, &format!("Variant is not string: {:?}", v) ) .map(|state| { - let (_id, layout) = choices.iter() + let layout = all_layouts.iter() .find( - |choices| state == choices.0 + |choices| state == choices.get_name() ).unwrap(); set_visible_layout( manager, @@ -443,20 +388,18 @@ pub fn show( }; menu_inner.popdown(); }); - - let settings_action = gio::SimpleAction::new("settings", None); - settings_action.connect_activate(move |_, _| { - let s = CString::new("region").unwrap(); - unsafe { c::popover_open_settings_panel(s.as_ptr()) }; - }); - - let action_group = gio::SimpleActionGroup::new(); action_group.add_action(&layout_action); - action_group.add_action(&settings_action); - - menu.insert_action_group("popup", Some(&action_group)); }; + let settings_action = gio::SimpleAction::new("settings", None); + settings_action.connect_activate(move |_, _| { + let s = CString::new("region").unwrap(); + unsafe { c::popover_open_settings_panel(s.as_ptr()) }; + }); + action_group.add_action(&settings_action); + + menu.insert_action_group("popup", Some(&action_group)); + menu.bind_model(Some(&model), Some("popup")); menu.popup(); }