This patch introduces the libxklavier wrapper and makes a use of it for getting
available layouts in the KeyboardSpoke.
---
anaconda.spec.in | 1 +
pyanaconda/ui/gui/spokes/keyboard.py | 12 ++--
pyanaconda/xklavier.py | 102 ++++++++++++++++++++++++++++++++++
3 files changed, 109 insertions(+), 6 deletions(-)
create mode 100755 pyanaconda/xklavier.py
diff --git a/anaconda.spec.in b/anaconda.spec.in
index cddcb77..834106d 100644
--- a/anaconda.spec.in
+++ b/anaconda.spec.in
@@ -133,6 +133,7 @@ Requires: python-bugzilla
Requires: python-nss
Requires: tigervnc-server-minimal
Requires: pytz
+Requires: libxklavier-devel
%ifarch %livearches
Requires: usermode
Requires: zenity
diff --git a/pyanaconda/ui/gui/spokes/keyboard.py b/pyanaconda/ui/gui/spokes/keyboard.py
index 441f43b..1f7dc95 100644
--- a/pyanaconda/ui/gui/spokes/keyboard.py
+++ b/pyanaconda/ui/gui/spokes/keyboard.py
@@ -30,6 +30,7 @@ from pyanaconda.ui.gui import UIObject
from pyanaconda.ui.gui.spokes import NormalSpoke
from pyanaconda.ui.gui.categories.localization import LocalizationCategory
from pyanaconda.ui.gui.utils import enlightbox
+from pyanaconda import xklavier
__all__ = ["KeyboardSpoke"]
@@ -38,6 +39,9 @@ class AddLayoutDialog(UIObject):
mainWidgetName = "addLayoutDialog"
uiFile = "spokes/keyboard.ui"
+ def __init__(self):
+ self._xkl_wrapper = xklavier.XklWrapper()
+
def matches_entry(self, model, itr, user_data=None):
value = model.get_value(itr, 0)
entry_text = self._entry.get_text()
@@ -64,12 +68,8 @@ class AddLayoutDialog(UIObject):
def initialize(self):
self._store = self.builder.get_object("newLayoutStore")
- #XXX: will use values from the libxklavier
- self._addLayout(self._store, "English (US)")
- self._addLayout(self._store, "English (US, with some other stuff)")
- self._addLayout(self._store, "Czech")
- self._addLayout(self._store, "Czech (qwerty)")
- self._addLayout(self._store, "values from libxklavier")
+ for layout in self._xkl_wrapper.get_available_layouts():
+ self._addLayout(self._store, layout)
def run(self):
rc = self.window.run()
diff --git a/pyanaconda/xklavier.py b/pyanaconda/xklavier.py
new file mode 100755
index 0000000..bac19db
--- /dev/null
+++ b/pyanaconda/xklavier.py
@@ -0,0 +1,102 @@
+#
+# Copyright (C) 2012 Red Hat, Inc.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions of
+# the GNU General Public License v.2, or (at your option) any later version.
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY expressed or implied, including the implied warranties 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, write to the
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
+# source code or documentation are not subject to the GNU General Public
+# License and may only be used or replicated with the express permission of
+# Red Hat, Inc.
+#
+# Red Hat Author(s): Martin Gracik <mgracik(a)redhat.com>
+# Vratislav Podzimek <vpodzime(a)redhat.com>
+#
+
+"""
+This module wraps the libxklavier functionality to protect Anaconda
+from dealing with it's "nice" API that looks like a Lisp-influenced
+"good old C".
+
+It provides a XklWrapper class with several methods that can be used
+for listing and various modifications of keyboard layouts settings.
+"""
+
+from gi.repository import Xkl, Gdk, GdkX11
+
+def item_str(s):
+ """Convert a zero-terminated byte array to a proper str"""
+
+ i = s.find(b'\x00')
+ return s[:i].decode("utf-8") #there are some non-ascii layout descriptions
+
+class _Variant(object):
+ """Internal class representing a single layout variant"""
+
+ def __init__(self, name, desc):
+ self.name = name
+ self.desc = desc
+
+ def __str__(self):
+ return '%s (%s)' % (self.name, self.desc)
+
+ @property
+ def description(self):
+ return self.desc
+
+class XklWrapper(object):
+ """Class wrapping the libxklavier functionality"""
+
+ def __init__(self):
+ #initialize Xkl-related stuff
+ display = GdkX11.x11_get_default_xdisplay()
+ engine = Xkl.Engine.get_instance(display)
+ self._configreg = Xkl.ConfigRegistry.get_instance(engine)
+ self._configreg.load(False)
+
+ self._language_keyboard_variants = dict()
+ self._country_keyboard_variants = dict()
+
+ def get_variant(self, c_reg, item, subitem, user_data=None):
+ variants = list()
+
+ if subitem:
+ variants.append(_Variant(item_str(subitem.name), item_str(subitem.description)))
+ else:
+ variants.append(_Variant(item_str(item.name), item_str(item.description)))
+
+ self._variants_list.append(variants)
+
+ def get_language_variants(self, c_reg, item, user_data=None):
+ #helper "global" variable
+ self._variants_list = list()
+ lang_name, lang_desc = item_str(item.name), item_str(item.description)
+
+ c_reg.foreach_language_variant(lang_name, self.get_variant, None)
+
+ self._language_keyboard_variants[(lang_name, lang_desc)] = self._variants_list
+
+ def get_country_variants(self, c_reg, item, user_data=None):
+ #helper "global" variable
+ self._variants_list = list()
+ country_name, country_desc = item_str(item.name), item_str(item.description)
+
+ c_reg.foreach_country_variant(country_name, self.get_variant, None)
+
+ self._country_keyboard_variants[(country_name, country_desc)] = self._variants_list
+
+ def get_available_layouts(self):
+ """A generator yielding layouts (no need to store them as a bunch)"""
+ self._configreg.foreach_language(self.get_language_variants, None)
+
+ for (lang_name, lang_desc), variants in sorted(self._language_keyboard_variants.items()):
+ for variant in variants:
+ for layout in variant:
+ yield "%s (%s)" % (lang_desc.encode("utf-8"), layout.description.encode("utf-8"))
+
--
1.7.4.4