[PATCH 4/4] Add dialog for configuring layout switching options

Vratislav Podzimek vpodzime at redhat.com
Mon Oct 22 16:29:46 UTC 2012


Resolves: rhbz#864785
Resolves: rhbz#859606

Signed-off-by: Vratislav Podzimek <vpodzime at redhat.com>
---
 pyanaconda/ui/gui/spokes/keyboard.glade | 181 +++++++++++++++++++++++++++++++-
 pyanaconda/ui/gui/spokes/keyboard.py    | 133 +++++++++++++++++++++++
 2 files changed, 311 insertions(+), 3 deletions(-)

diff --git a/pyanaconda/ui/gui/spokes/keyboard.glade b/pyanaconda/ui/gui/spokes/keyboard.glade
index c122366..40c0e09 100644
--- a/pyanaconda/ui/gui/spokes/keyboard.glade
+++ b/pyanaconda/ui/gui/spokes/keyboard.glade
@@ -2,7 +2,6 @@
 <interface>
   <!-- interface-requires gtk+ 3.0 -->
   <!-- interface-requires AnacondaWidgets 1.0 -->
-  <object class="GtkTextBuffer" id="layoutTestBuffer"/>
   <object class="GtkDialog" id="addLayoutDialog">
     <property name="can_focus">False</property>
     <property name="border_width">5</property>
@@ -422,6 +421,7 @@
                             <property name="visible">True</property>
                             <property name="can_focus">False</property>
                             <property name="halign">end</property>
+                            <property name="valign">start</property>
                             <property name="label" translatable="yes">Alt + Shift to switch layouts.</property>
                             <attributes>
                               <attribute name="font-desc" value="Cantarell Italic 10"/>
@@ -436,17 +436,18 @@
                         </child>
                         <child>
                           <object class="GtkButton" id="optionsButton">
-                            <property name="label" translatable="yes">_Options...</property>
+                            <property name="label" translatable="yes">_Options</property>
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
                             <property name="receives_default">True</property>
                             <property name="halign">end</property>
+                            <property name="valign">start</property>
                             <property name="use_underline">True</property>
+                            <signal name="clicked" handler="on_options_clicked" swapped="no"/>
                           </object>
                           <packing>
                             <property name="expand">False</property>
                             <property name="fill">True</property>
-                            <property name="pack_type">end</property>
                             <property name="position">3</property>
                           </packing>
                         </child>
@@ -476,6 +477,7 @@
       </object>
     </child>
   </object>
+  <object class="GtkTextBuffer" id="layoutTestBuffer"/>
   <object class="GtkListStore" id="newLayoutStore">
     <columns>
       <!-- column-name name -->
@@ -488,4 +490,177 @@
   <object class="GtkTreeModelSort" id="newLayoutStoreSort">
     <property name="model">newLayoutStoreFilter</property>
   </object>
+  <object class="GtkDialog" id="switchingDialog">
+    <property name="can_focus">False</property>
+    <property name="border_width">5</property>
+    <property name="default_height">450</property>
+    <property name="type_hint">dialog</property>
+    <property name="decorated">False</property>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="dialog-vbox2">
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="dialog-action_area2">
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="button2">
+                <property name="label">gtk-cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="button1">
+                <property name="label">gtk-ok</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox" id="box1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="orientation">vertical</property>
+            <property name="spacing">6</property>
+            <child>
+              <object class="GtkLabel" id="headerLabel">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">start</property>
+                <property name="valign">start</property>
+                <property name="label" translatable="yes">LAYOUT SWITCHING OPTIONS</property>
+                <attributes>
+                  <attribute name="font-desc" value="Cantarell Bold 10"/>
+                  <attribute name="weight" value="bold"/>
+                </attributes>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="descriptionLabel">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">start</property>
+                <property name="label" translatable="yes">Which combination(s) would you prefer for switching between keyboard layouts?</property>
+                <property name="wrap">True</property>
+                <attributes>
+                  <attribute name="font-desc" value="Cantarell 12"/>
+                </attributes>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkScrolledWindow" id="scrolledwindow2">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="margin_left">6</property>
+                <property name="margin_right">6</property>
+                <property name="margin_top">6</property>
+                <property name="vexpand">True</property>
+                <property name="hscrollbar_policy">never</property>
+                <property name="shadow_type">in</property>
+                <child>
+                  <object class="GtkTreeView" id="treeview2">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="vexpand">True</property>
+                    <property name="model">switchingOptsSort</property>
+                    <property name="headers_visible">False</property>
+                    <property name="headers_clickable">False</property>
+                    <property name="search_column">0</property>
+                    <child internal-child="selection">
+                      <object class="GtkTreeSelection" id="treeview-selection"/>
+                    </child>
+                    <child>
+                      <object class="GtkTreeViewColumn" id="useColumn">
+                        <property name="title" translatable="yes">use</property>
+                        <child>
+                          <object class="GtkCellRendererToggle" id="useRenderer">
+                            <signal name="toggled" handler="on_use_option_toggled" swapped="no"/>
+                          </object>
+                          <attributes>
+                            <attribute name="active">1</attribute>
+                          </attributes>
+                        </child>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkTreeViewColumn" id="descColumn">
+                        <property name="title" translatable="yes">description</property>
+                        <property name="expand">True</property>
+                        <child>
+                          <object class="GtkCellRendererText" id="descRenderer"/>
+                          <attributes>
+                            <attribute name="markup">0</attribute>
+                          </attributes>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="0">button2</action-widget>
+      <action-widget response="1">button1</action-widget>
+    </action-widgets>
+  </object>
+  <object class="GtkListStore" id="switchingOptsStore">
+    <columns>
+      <!-- column-name description -->
+      <column type="gchararray"/>
+      <!-- column-name use -->
+      <column type="gboolean"/>
+    </columns>
+  </object>
+  <object class="GtkTreeModelSort" id="switchingOptsSort">
+    <property name="model">switchingOptsStore</property>
+  </object>
 </interface>
diff --git a/pyanaconda/ui/gui/spokes/keyboard.py b/pyanaconda/ui/gui/spokes/keyboard.py
index ee248c4..e0c4d54 100644
--- a/pyanaconda/ui/gui/spokes/keyboard.py
+++ b/pyanaconda/ui/gui/spokes/keyboard.py
@@ -36,10 +36,19 @@ from pyanaconda import flags
 
 __all__ = ["KeyboardSpoke"]
 
+# %s will be replaced by key combination like Alt+Shift
+LAYOUT_SWITCHING_INFO = _("%s to switch layouts.")
+
 def _show_layout(column, renderer, model, itr, wrapper):
     value = wrapper.name_to_show_str[model[itr][0]]
     renderer.set_property("text", value)
 
+def _show_description(column, renderer, model, itr, wrapper):
+    value = wrapper.switch_to_show_str[model[itr][0]]
+    if model[itr][1]:
+        value = "<b>%s</b>" % value
+    renderer.set_property("markup", value)
+
 class AddLayoutDialog(GUIObject):
     builderObjects = ["addLayoutDialog", "newLayoutStore",
                       "newLayoutStoreFilter", "newLayoutStoreSort"]
@@ -155,6 +164,95 @@ class AddLayoutDialog(GUIObject):
     def _addLayout(self, store, name):
         store.append([name])
 
+
+class ConfigureSwitchingDialog(GUIObject):
+    """Class representing a dialog for layout switching configuration"""
+
+    builderObjects = ["switchingDialog", "switchingOptsStore",
+                      "switchingOptsSort",]
+    mainWidgetName = "switchingDialog"
+    uiFile = "spokes/keyboard.glade"
+
+    def __init__(self, *args):
+        GUIObject.__init__(self, *args)
+        self._xkl_wrapper = keyboard.XklWrapper.get_instance()
+
+        self._switchingOptsStore = self.builder.get_object("switchingOptsStore")
+
+    def initialize(self):
+        # we want to display "Alt + Shift" rather than "grp:alt_shift_toggle"
+        descColumn = self.builder.get_object("descColumn")
+        descRenderer = self.builder.get_object("descRenderer")
+        descColumn.set_cell_data_func(descRenderer, _show_description,
+                                            self._xkl_wrapper)
+
+        self._switchingOptsSort = self.builder.get_object("switchingOptsSort")
+        self._switchingOptsSort.set_default_sort_func(self._compare_options, None)
+
+        for opt in self._xkl_wrapper.get_switching_options():
+            self._add_option(opt)
+
+    def refresh(self):
+        itr = self._switchingOptsStore.get_iter_first()
+        while itr:
+            option = self._switchingOptsStore[itr][0]
+            if option in self.data.keyboard.switch_options:
+                self._switchingOptsStore.set_value(itr, 1, True)
+            else:
+                self._switchingOptsStore.set_value(itr, 1, False)
+
+            itr = self._switchingOptsStore.iter_next(itr)
+
+    def run(self):
+        rc = self.window.run()
+        self.window.hide()
+        return rc
+
+    def _add_option(self, option):
+        """Add option to the list as unchecked"""
+
+        self._switchingOptsStore.append([option, False])
+
+    def _compare_options(self, model, itr1, itr2, user_data=None):
+        """
+        We want to sort options by their show strings not their names.
+        This function is an instance of GtkTreeIterCompareFunc().
+
+        """
+
+        value1 = model[itr1][0]
+        value2 = model[itr2][0]
+        show_str1 = self._xkl_wrapper.switch_to_show_str[value1]
+        show_str2 = self._xkl_wrapper.switch_to_show_str[value2]
+
+        if show_str1 < show_str2:
+            return -1
+        elif show_str1 == show_str2:
+            return 0
+        else:
+            return 1
+
+    @property
+    def checked_options(self):
+        """Property returning all checked options from the list"""
+
+        ret = []
+        for row in self._switchingOptsSort:
+            if row[1] and row[0]:
+                ret.append(row[0])
+
+        return ret
+
+    def on_use_option_toggled(self, renderer, path, *args):
+        itr = self._switchingOptsSort.get_iter(path)
+
+        # Get itr for the *store*.
+        itr = self._switchingOptsSort.convert_iter_to_child_iter(itr)
+        old_value = self._switchingOptsStore[itr][1]
+
+        self._switchingOptsStore.set_value(itr, 1, not old_value)
+
+
 class KeyboardSpoke(NormalSpoke):
     builderObjects = ["addedLayoutStore", "keyboardWindow",
                       "layoutTestBuffer"]
@@ -202,6 +300,11 @@ class KeyboardSpoke(NormalSpoke):
         self._store = self.builder.get_object("addedLayoutStore")
         self._add_data_layouts()
 
+        self._switching_dialog = ConfigureSwitchingDialog(self.data)
+        self._switching_dialog.initialize()
+
+        self._layoutSwitchLabel = self.builder.get_object("layoutSwitchLabel")
+
         if not flags.can_touch_runtime_system("test X layouts"):
             # Disable area for testing layouts as we cannot make
             # it work without modifying runtime system
@@ -241,6 +344,8 @@ class KeyboardSpoke(NormalSpoke):
         self._removeButton.set_sensitive(False)
         self._previewButton.set_sensitive(False)
 
+        self._refresh_switching_info()
+
     def _addLayout(self, store, name):
         store.append([name])
         if flags.can_touch_runtime_system("add runtime X layout"):
@@ -257,6 +362,16 @@ class KeyboardSpoke(NormalSpoke):
             self._xkl_wrapper.remove_layout(store[itr][0])
         store.remove(itr)
 
+    def _refresh_switching_info(self):
+        if self.data.keyboard.switch_options:
+            first_option = self.data.keyboard.switch_options[0]
+            desc = self._xkl_wrapper.switch_to_show_str[first_option]
+
+            self._layoutSwitchLabel.set_text(LAYOUT_SWITCHING_INFO % desc)
+        else:
+            self._layoutSwitchLabel.set_text(_("Layout switching not "
+                                               "configured."))
+
     # Signal handlers.
     def on_add_clicked(self, button):
         dialog = AddLayoutDialog(self.data)
@@ -389,6 +504,24 @@ class KeyboardSpoke(NormalSpoke):
             self._upButton.set_sensitive(True)
             self._downButton.set_sensitive(True)
 
+    def on_options_clicked(self, *args):
+        self._switching_dialog.refresh()
+
+        with enlightbox(self.window, self._switching_dialog.window):
+            response = self._switching_dialog.run()
+
+        if response != 1:
+            # Cancel clicked, dialog destroyed
+            return
+
+        # OK clicked, set and save switching options.
+        new_options = self._switching_dialog.checked_options
+        self._xkl_wrapper.set_switching_options(new_options)
+        self.data.keyboard.switch_options = new_options
+
+        # Refresh switching info label.
+        self._refresh_switching_info()
+
     def _add_data_layouts(self):
         if self.data.keyboard.x_layouts:
             for layout in self.data.keyboard.x_layouts:
-- 
1.7.11.7



More information about the anaconda-patches mailing list