diff --git a/po/POTFILES b/po/POTFILES index c84aa9638..f8584d027 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -1,10 +1,11 @@ src/Application.vala src/MainWindow.vala src/Utils.vala -src/Helpers/KeyboardLayoutHelper.vala src/Helpers/LocaleHelper.vala src/Helpers/LogHelper.vala src/Objects/Configuration.vala +src/Objects/KeyboardLayout.vala +src/Objects/KeyboardVariant.vala src/Objects/Mount.vala src/Views/AbstractInstallerView.vala src/Views/CheckView.vala diff --git a/src/Helpers/KeyboardLayoutHelper.vala b/src/Helpers/KeyboardLayoutHelper.vala deleted file mode 100644 index e021a9a70..000000000 --- a/src/Helpers/KeyboardLayoutHelper.vala +++ /dev/null @@ -1,98 +0,0 @@ -// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*- -/*- - * Copyright (c) 2017 elementary LLC. (https://elementary.io) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -namespace KeyboardLayoutHelper { - public const string XKB_RULES_FILE = "base.xml"; - - public struct Layout { - public string name; - public string description; - public Gee.HashMap variants; - } - - public string get_xml_rules_file_path () { - unowned string? base_path = GLib.Environment.get_variable ("XKB_CONFIG_ROOT"); - if (base_path == null) { - base_path = Build.XKB_BASE; - } - - return Path.build_filename (base_path, "rules", XKB_RULES_FILE); - } - - public static Gee.LinkedList get_layouts () { - var layouts = new Gee.LinkedList (); - unowned Xml.Doc* doc = Xml.Parser.read_file (get_xml_rules_file_path ()); - Xml.Node* root = doc->get_root_element (); - Xml.Node* layout_list_node = get_xml_node_by_name (root, "layoutList"); - if (layout_list_node == null) { - delete doc; - return layouts; - } - - for (Xml.Node* layout_iter = layout_list_node->children; layout_iter != null; layout_iter = layout_iter->next) { - if (layout_iter->type == Xml.ElementType.ELEMENT_NODE) { - if (layout_iter->name == "layout") { - Xml.Node* config_node = get_xml_node_by_name (layout_iter, "configItem"); - Xml.Node* variant_node = get_xml_node_by_name (layout_iter, "variantList"); - Xml.Node* description_node = get_xml_node_by_name (config_node, "description"); - Xml.Node* name_node = get_xml_node_by_name (config_node, "name"); - if (name_node == null || description_node == null) { - continue; - } - - var layout = Layout (); - layout.name = name_node->children->content; - layout.description = dgettext ("xkeyboard-config", description_node->children->content); - var variants = new Gee.HashMap (); - layout.variants = variants; - if (variant_node != null) { - for (Xml.Node* variant_iter = variant_node->children; variant_iter != null; variant_iter = variant_iter->next) { - if (variant_iter->name == "variant") { - Xml.Node* variant_config_node = get_xml_node_by_name (variant_iter, "configItem"); - if (variant_config_node != null) { - Xml.Node* variant_description_node = get_xml_node_by_name (variant_config_node, "description"); - Xml.Node* variant_name_node = get_xml_node_by_name (variant_config_node, "name"); - if (variant_description_node != null && variant_name_node != null) { - variants[variant_name_node->children->content] = dgettext ("xkeyboard-config", variant_description_node->children->content); - } - } - } - } - } - - layouts.add (layout); - } - } - } - - delete doc; - return layouts; - } - - private static Xml.Node* get_xml_node_by_name (Xml.Node* root, string name) { - for (Xml.Node* iter = root->children; iter != null; iter = iter->next) { - if (iter->type == Xml.ElementType.ELEMENT_NODE) { - if (iter->name == name) { - return iter; - } - } - } - - return null; - } -} diff --git a/src/Helpers/LocaleHelper.vala b/src/Helpers/LocaleHelper.vala index d46131f18..13b538de2 100644 --- a/src/Helpers/LocaleHelper.vala +++ b/src/Helpers/LocaleHelper.vala @@ -45,8 +45,11 @@ namespace LocaleHelper { } private static Gee.HashMap lang_entries; + private static GLib.Mutex lang_mutex; + public static Gee.HashMap get_lang_entries () { if (lang_entries == null) { + lang_mutex = Mutex (); lang_entries = new Gee.HashMap (); var langs = Build.LANG_LIST.split (";"); @@ -112,26 +115,17 @@ namespace LocaleHelper { } // Now translate the labels in their original language. - var current_lang = Environment.get_variable ("LANGUAGE"); foreach (var lang_entry in lang_entries.values) { var lang_code = lang_entry.get_code (); - Environment.set_variable ("LANGUAGE", lang_code, true); - lang_entry.name = dgettext ("iso_639_3", lang_entry.name); + lang_entry.name = lang_gettext (lang_entry.name, lang_code, "iso_639_3"); if (lang_entry.countries.length > 0) { lang_entry.name = _("%s…").printf (lang_entry.name); } foreach (var country in lang_entry.countries) { - Environment.set_variable ("LANGUAGE", lang_code + "_" + country.alpha_2, true); - country.name = dgettext ("iso_3166", country.name); + country.name = lang_gettext (country.name, lang_code + "_" + country.alpha_2, "iso_3166"); } } - - if (current_lang != null) { - Environment.set_variable ("LANGUAGE", current_lang, true); - } else { - Environment.unset_variable ("LANGUAGE"); - } } return lang_entries; @@ -219,4 +213,33 @@ namespace LocaleHelper { return null; } + + /* + * Always use this function to translate into another language to make sure + * that no race occurs when switchbing the environment variable. + */ + public unowned string lang_gettext (string source, string lang, string? domain = null) { + lang_mutex.lock (); + unowned string translation; + var current_lang = GLib.Environment.get_variable ("LANGUAGE"); + GLib.Environment.set_variable ("LANGUAGE", lang, true); + + if (domain == null) { + Intl.textdomain (Build.GETTEXT_PACKAGE); + translation = _(source); + } else { + translation = dgettext (domain, source); + } + + if (current_lang != null) { + GLib.Environment.set_variable ("LANGUAGE", current_lang, true); + } else { + GLib.Environment.unset_variable ("LANGUAGE"); + } + + Intl.textdomain (Build.GETTEXT_PACKAGE); + lang_mutex.unlock (); + + return translation; + } } diff --git a/src/Views/KeyboardLayoutView.vala b/src/Views/KeyboardLayoutView.vala index 94126fc0e..40955a7bb 100644 --- a/src/Views/KeyboardLayoutView.vala +++ b/src/Views/KeyboardLayoutView.vala @@ -59,22 +59,6 @@ public class KeyboardLayoutView : AbstractInstallerView { action_box_end.add (back_button); action_box_end.add (next_button); - input_variant_widget.main_listbox.set_sort_func ((row1, row2) => { - return ((LayoutRow) row1).layout.description.collate (((LayoutRow) row2).layout.description); - }); - - input_variant_widget.variant_listbox.set_sort_func ((row1, row2) => { - if (((VariantRow) row1).code == null) { - return -1; - } - - if (((VariantRow) row2).code == null) { - return 1; - } - - return ((VariantRow) row1).description.collate (((VariantRow) row2).description); - }); - input_variant_widget.variant_listbox.row_activated.connect (() => { next_button.activate (); }); @@ -87,12 +71,13 @@ public class KeyboardLayoutView : AbstractInstallerView { var layout = ((LayoutRow) row).layout; unowned Configuration configuration = Configuration.get_default (); configuration.keyboard_layout = layout.name; + GLib.Variant? layout_variant = null; unowned Gtk.ListBoxRow vrow = input_variant_widget.variant_listbox.get_selected_row (); if (vrow != null) { - string variant = ((VariantRow) vrow).code; - configuration.keyboard_variant = variant; - } else if (layout.variants.is_empty) { + unowned var variant = ((VariantRow) vrow).variant; + configuration.keyboard_variant = variant.name; + } else if (!layout.has_variants ()) { configuration.keyboard_variant = null; } else { row.activate (); @@ -108,44 +93,48 @@ public class KeyboardLayoutView : AbstractInstallerView { }); input_variant_widget.main_listbox.row_activated.connect ((row) => { - var layout = ((LayoutRow) row).layout; - var variants = layout.variants; - if (variants.is_empty) { + unowned var layout = ((LayoutRow) row).layout; + if (!layout.has_variants ()) { return; } - input_variant_widget.clear_variants (); - input_variant_widget.variant_listbox.add (new VariantRow (null, _("Default"))); - foreach (var variant in variants.entries) { - input_variant_widget.variant_listbox.add (new VariantRow (variant.key, variant.value)); - } + input_variant_widget.variant_listbox.bind_model (layout.get_variants (), (variant) => { + return new VariantRow (variant as Installer.KeyboardVariant); + }); input_variant_widget.variant_listbox.select_row (input_variant_widget.variant_listbox.get_row_at_index (0)); - input_variant_widget.show_variants (_("Input Language"), "%s".printf (layout.description)); + input_variant_widget.show_variants (_("Input Language"), "%s".printf (layout.display_name)); }); input_variant_widget.variant_listbox.row_selected.connect (() => { - string layout_string = "us"; - - unowned Gtk.ListBoxRow row = input_variant_widget.main_listbox.get_selected_row (); + unowned var row = input_variant_widget.main_listbox.get_selected_row (); if (row != null) { - layout_string = ((LayoutRow) row).layout.name; + var layout = ((LayoutRow) row).layout; + unowned var configuration = Configuration.get_default (); + configuration.keyboard_layout = layout.name; + GLib.Variant? layout_variant = null; - unowned Gtk.ListBoxRow vrow = input_variant_widget.variant_listbox.get_selected_row (); + unowned var vrow = input_variant_widget.variant_listbox.get_selected_row (); if (vrow != null) { - string variant = ((VariantRow) vrow).code; - if (variant != null && variant != "") { - layout_string += "+" + variant; + unowned var variant = ((VariantRow) vrow).variant; + configuration.keyboard_variant = variant.name; + if (variant != null) { + layout_variant = variant.to_gsd_variant (); } + } else if (!layout.has_variants ()) { + configuration.keyboard_variant = null; + } + + if (layout_variant == null) { + layout_variant = layout.to_gsd_variant (); } - } - if (!Installer.App.test_mode) { - Variant[] entries = { new Variant ("(ss)", "xkb", layout_string) }; - var sources = new Variant.array (new VariantType ("(ss)"), entries); - keyboard_settings.set_value ("sources", sources); - keyboard_settings.set_value ("current", (uint)0); + if (!Installer.App.test_mode) { + var settings = new Settings ("org.gnome.desktop.input-sources"); + settings.set_value ("sources", layout_variant); + settings.set_uint ("current", 0); + } } }); @@ -154,36 +143,31 @@ public class KeyboardLayoutView : AbstractInstallerView { }); keyboard_test_entry.icon_release.connect (() => { - string layout_string; - unowned Gtk.ListBoxRow row = input_variant_widget.main_listbox.get_selected_row (); - if (row != null) { - layout_string = ((LayoutRow) row).layout.name; - - unowned Gtk.ListBoxRow vrow = input_variant_widget.variant_listbox.get_selected_row (); - if (vrow != null) { - string variant = ((VariantRow) vrow).code; - layout_string += "\t" + variant; + var layout_string = "us"; + unowned var config = Configuration.get_default (); + if (config.keyboard_layout != null) { + layout_string = config.keyboard_layout; + if (config.keyboard_variant != null) { + layout_string += "\t" + config.keyboard_variant; } - } else { - layout_string = "us"; } string command = "gkbd-keyboard-display --layout=%s".printf (layout_string); try { - AppInfo.create_from_commandline (command, null, NONE).launch (null, null); + AppInfo.create_from_commandline (command, null, AppInfoCreateFlags.NONE).launch (null, null); } catch (Error e) { warning ("Error launching keyboard layout display: %s", e.message); } }); - foreach (var layout in KeyboardLayoutHelper.get_layouts ()) { - input_variant_widget.main_listbox.add (new LayoutRow (layout)); - } + input_variant_widget.main_listbox.bind_model (Installer.KeyboardLayout.get_all (), (layout) => { + return new LayoutRow (layout as Installer.KeyboardLayout); + }); show_all (); Idle.add_once (() => { - string? country = Configuration.get_default ().country; + unowned string? country = Configuration.get_default ().country; if (country != null) { string default_layout = country.down (); @@ -202,17 +186,17 @@ public class KeyboardLayoutView : AbstractInstallerView { } private class LayoutRow : Gtk.ListBoxRow { - public KeyboardLayoutHelper.Layout layout { get; construct; } + public unowned Installer.KeyboardLayout layout { get; construct; } - public LayoutRow (KeyboardLayoutHelper.Layout layout) { + public LayoutRow (Installer.KeyboardLayout layout) { Object (layout: layout); } construct { - string layout_description = layout.description; - if (!layout.variants.is_empty) { + string layout_description = layout.display_name;; + if (layout.has_variants ()) { layout_description = _("%s…").printf (layout_description); - }; + } var label = new Gtk.Label (layout_description) { ellipsize = Pango.EllipsizeMode.END, @@ -230,18 +214,14 @@ public class KeyboardLayoutView : AbstractInstallerView { } private class VariantRow : Gtk.ListBoxRow { - public string? code { get; construct; } - public string description { get; construct; } - - public VariantRow (string? code, string description) { - Object ( - code: code, - description: description - ); + public unowned Installer.KeyboardVariant variant { get; construct; } + + public VariantRow (Installer.KeyboardVariant variant) { + Object (variant: variant); } construct { - var label = new Gtk.Label (description) { + var label = new Gtk.Label (variant.display_name) { ellipsize = Pango.EllipsizeMode.END, margin_top = 6, margin_end = 6, diff --git a/src/Views/LanguageView.vala b/src/Views/LanguageView.vala index 0d2eb2702..378e66ec4 100644 --- a/src/Views/LanguageView.vala +++ b/src/Views/LanguageView.vala @@ -23,13 +23,20 @@ public class Installer.LanguageView : AbstractInstallerView { Gtk.Button next_button; int select_number = 0; Gee.LinkedList preferred_langs; + private uint lang_timeout = 0U; private VariantWidget lang_variant_widget; public signal void next_step (); public LanguageView () { - GLib.Timeout.add_seconds (3, timeout); + lang_timeout = GLib.Timeout.add_seconds (3, timeout); + } + + ~LanguageView () { + if (lang_timeout > 0U) { + GLib.Source.remove (lang_timeout); + } } construct { @@ -194,10 +201,7 @@ public class Installer.LanguageView : AbstractInstallerView { lang_variant_widget.clear_variants (); lang_variant_widget.variant_listbox.row_selected.connect (variant_row_selected); - var current_lang = Environment.get_variable ("LANGUAGE"); var lang_entry = ((LangRow) row).lang_entry; - Environment.set_variable ("LANGUAGE", lang_entry.get_code (), true); - Intl.textdomain (Build.GETTEXT_PACKAGE); foreach (Gtk.Widget child in lang_variant_widget.main_listbox.get_children ()) { if (child is LangRow) { @@ -210,12 +214,6 @@ public class Installer.LanguageView : AbstractInstallerView { } } - if (current_lang != null) { - Environment.set_variable ("LANGUAGE", current_lang, true); - } else { - Environment.unset_variable ("LANGUAGE"); - } - next_button.sensitive = true; } @@ -265,24 +263,17 @@ public class Installer.LanguageView : AbstractInstallerView { row = lang_variant_widget.main_listbox.get_row_at_index (select_number); if (row == null) { + lang_timeout = 0; return Source.REMOVE; } } - var current_lang = Environment.get_variable ("LANGUAGE"); - Environment.set_variable ("LANGUAGE", ((LangRow) row).lang_entry.get_code (), true); - Intl.textdomain (Build.GETTEXT_PACKAGE); - select_label = new Gtk.Label (_("Select a Language")); + unowned string label_text = LocaleHelper.lang_gettext (N_("Select a Language"), ((LangRow) row).lang_entry.get_code ()); + select_label = new Gtk.Label (label_text); select_label.show_all (); select_stack.add (select_label); select_stack.set_visible_child (select_label); - if (current_lang != null) { - Environment.set_variable ("LANGUAGE", current_lang, true); - } else { - Environment.unset_variable ("LANGUAGE"); - } - select_number++; return GLib.Source.CONTINUE; } diff --git a/src/meson.build b/src/meson.build index 68ab4bbd7..917843ff1 100644 --- a/src/meson.build +++ b/src/meson.build @@ -3,10 +3,11 @@ vala_files = [ 'MainWindow.vala', 'Utils.vala', 'Helpers/InstallerDaemon.vala', - 'Helpers/KeyboardLayoutHelper.vala', 'Helpers/LocaleHelper.vala', 'Helpers/LogHelper.vala', 'Objects/Configuration.vala', + 'Objects/KeyboardLayout.vala', + 'Objects/KeyboardVariant.vala', 'Objects/Mount.vala', 'Views/AbstractInstallerView.vala', 'Views/CheckView.vala',