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',