[gnome-control-center/wip/gbsneto/new-keyboard-panel: 6/16] keyboard: show shortcuts in a listbox



commit 9313203761d008b742b4cb5d9551c7bd5e54e1b1
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Fri Jul 22 16:10:15 2016 -0300

    keyboard: show shortcuts in a listbox
    
    Replace the current treeview with the new listbox. This
    patch simply adds the listbox, and does not remove the
    treeview yet.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=769063

 panels/keyboard/cc-keyboard-panel.c     |  276 ++++++++++++++++++++++++++++++-
 panels/keyboard/gnome-keyboard-panel.ui |   43 +++++
 2 files changed, 310 insertions(+), 9 deletions(-)
---
diff --git a/panels/keyboard/cc-keyboard-panel.c b/panels/keyboard/cc-keyboard-panel.c
index 2d44882..dd41349 100644
--- a/panels/keyboard/cc-keyboard-panel.c
+++ b/panels/keyboard/cc-keyboard-panel.c
@@ -37,6 +37,12 @@
 #define BINDINGS_SCHEMA       "org.gnome.settings-daemon.plugins.media-keys"
 #define CUSTOM_SHORTCUTS_ID   "custom"
 
+typedef struct {
+  CcKeyboardItem *item;
+  gchar          *section_title;
+  gchar          *section_id;
+} RowData;
+
 struct _CcKeyboardPanel
 {
   CcPanel             parent;
@@ -45,6 +51,9 @@ struct _CcKeyboardPanel
   GtkListStore       *sections_store;
   GtkTreeModel       *sections_model;
   GtkWidget          *shortcut_treeview;
+  GtkWidget          *listbox;
+  GtkListBoxRow      *add_shortcut_row;
+  GtkSizeGroup       *accelerator_sizegroup;
 
   /* Toolbar widgets */
   GtkWidget          *add_toolbutton;
@@ -75,6 +84,239 @@ enum {
   PROP_PARAMETERS
 };
 
+/* RowData functions */
+static RowData *
+row_data_new (CcKeyboardItem *item,
+              const gchar    *section_id,
+              const gchar    *section_title)
+{
+  RowData *data;
+
+  data = g_new0 (RowData, 1);
+  data->item = g_object_ref (item);
+  data->section_id = g_strdup (section_id);
+  data->section_title = g_strdup (section_title);
+
+  return data;
+}
+
+static void
+row_data_free (RowData *data)
+{
+  g_object_unref (data->item);
+  g_free (data->section_id);
+  g_free (data->section_title);
+  g_free (data);
+}
+
+/*
+ * Listbox-related functions
+ */
+static gboolean
+transform_binding_to_accel (GBinding     *binding,
+                            const GValue *from_value,
+                            GValue       *to_value,
+                            gpointer      user_data)
+{
+  CcKeyboardItem *item;
+  gchar *accelerator;
+
+  item = CC_KEYBOARD_ITEM (g_binding_get_source (binding));
+
+  accelerator = convert_keysym_state_to_string (item->keyval, item->mask, item->keycode);
+
+  g_value_take_string (to_value, accelerator);
+
+  return TRUE;
+}
+
+static void
+add_item (CcKeyboardPanel *self,
+          CcKeyboardItem  *item,
+          const gchar     *section_id,
+          const gchar     *section_title)
+{
+  GtkWidget *row, *box, *label;
+
+  /* Horizontal box */
+  box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
+  gtk_container_set_border_width (GTK_CONTAINER (box), 6);
+
+  /* Shortcut title */
+  label = gtk_label_new (item->description);
+  gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+  gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+  gtk_label_set_line_wrap_mode (GTK_LABEL (label), PANGO_WRAP_WORD_CHAR);
+  gtk_widget_set_hexpand (label, TRUE);
+
+  g_object_bind_property (item,
+                          "description",
+                          label,
+                          "label",
+                          G_BINDING_DEFAULT);
+
+  gtk_container_add (GTK_CONTAINER (box), label);
+
+  /* Shortcut accelerator */
+  label = gtk_label_new ("");
+  gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+
+  gtk_size_group_add_widget (self->accelerator_sizegroup, label);
+
+  g_object_bind_property_full (item,
+                               "binding",
+                               label,
+                              "label",
+                               G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE,
+                               transform_binding_to_accel,
+                               NULL, NULL, NULL);
+
+  gtk_container_add (GTK_CONTAINER (box), label);
+
+  gtk_style_context_add_class (gtk_widget_get_style_context (label), "dim-label");
+
+  /* The row */
+  row = gtk_list_box_row_new ();
+  gtk_container_add (GTK_CONTAINER (row), box);
+
+  gtk_widget_show_all (row);
+
+  g_object_set_data_full (G_OBJECT (row),
+                          "data",
+                          row_data_new (item, section_id, section_title),
+                          (GDestroyNotify) row_data_free);
+
+  gtk_container_add (GTK_CONTAINER (self->listbox), row);
+}
+
+static void
+remove_item (CcKeyboardPanel *self,
+             CcKeyboardItem  *item)
+{
+  GList *children, *l;
+
+  children = gtk_container_get_children (GTK_CONTAINER (self->listbox));
+
+  for (l = children; l != NULL; l = l->next)
+    {
+      RowData *row_data;
+
+      row_data = g_object_get_data (l->data, "data");
+
+      if (row_data->item == item)
+        {
+          gtk_container_remove (GTK_CONTAINER (self->listbox), l->data);
+          break;
+        }
+    }
+
+  g_list_free (children);
+}
+
+static gint
+sort_function (GtkListBoxRow *a,
+               GtkListBoxRow *b,
+               gpointer       user_data)
+{
+  CcKeyboardPanel *self;
+  RowData *a_data, *b_data;
+  gint retval;
+
+  self = user_data;
+
+  if (a == self->add_shortcut_row)
+    return 1;
+
+  if (b == self->add_shortcut_row)
+    return -1;
+
+  a_data = g_object_get_data (G_OBJECT (a), "data");
+  b_data = g_object_get_data (G_OBJECT (b), "data");
+
+  /* Put custom shortcuts below everything else */
+  if (a_data->item->type == CC_KEYBOARD_ITEM_TYPE_GSETTINGS_PATH)
+    return 1;
+  else if (b_data->item->type == CC_KEYBOARD_ITEM_TYPE_GSETTINGS_PATH)
+    return -1;
+
+  retval = g_strcmp0 (a_data->section_title, b_data->section_title);
+
+  if (retval != 0)
+    return retval;
+
+  return g_strcmp0 (a_data->item->description, b_data->item->description);
+}
+
+static void
+header_function (GtkListBoxRow *row,
+                 GtkListBoxRow *before,
+                 gpointer       user_data)
+{
+  CcKeyboardPanel *self;
+  gboolean add_header;
+  RowData *data;
+
+  self = user_data;
+  add_header = FALSE;
+
+  /* The + row always has a separator */
+  if (row == self->add_shortcut_row)
+    {
+      GtkWidget *separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
+      gtk_widget_show (separator);
+
+      gtk_list_box_row_set_header (row, separator);
+
+      return;
+    }
+
+  data = g_object_get_data (G_OBJECT (row), "data");
+
+  if (before)
+    {
+      RowData *before_data = g_object_get_data (G_OBJECT (before), "data");
+
+      if (before_data)
+        add_header = g_strcmp0 (before_data->section_id, data->section_id) != 0;
+    }
+  else
+    {
+      add_header = TRUE;
+    }
+
+  if (add_header)
+    {
+      GtkWidget *box, *label;
+      gchar *markup;
+
+      box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+      gtk_widget_set_margin_top (box, before ? 18 : 6);
+
+      markup = g_strdup_printf ("<b>%s</b>", _(data->section_title));
+      label = g_object_new (GTK_TYPE_LABEL,
+                            "label", markup,
+                            "use-markup", TRUE,
+                            "xalign", 0.0,
+                            "margin-start", 6,
+                            NULL);
+
+      gtk_style_context_add_class (gtk_widget_get_style_context (label), "dim-label");
+
+      gtk_container_add (GTK_CONTAINER (box), label);
+      gtk_container_add (GTK_CONTAINER (box), gtk_separator_new (GTK_ORIENTATION_HORIZONTAL));
+
+      gtk_list_box_row_set_header (row, box);
+
+      gtk_widget_show_all (box);
+
+      g_free (markup);
+    }
+  else
+    {
+      gtk_list_box_row_set_header (row, NULL);
+    }
+}
+
 static GHashTable*
 get_hash_for_group (CcKeyboardPanel  *self,
                     BindingGroupType  group)
@@ -474,7 +716,6 @@ static void
 reload_sections (CcKeyboardPanel *self)
 {
   GtkTreeModel *shortcut_model;
-  GtkTreeIter iter;
   GHashTable *loaded_files;
   GDir *dir;
   gchar *default_wm_keybindings[] = { "Mutter", "GNOME Shell", NULL };
@@ -557,14 +798,6 @@ reload_sections (CcKeyboardPanel *self)
   g_hash_table_destroy (loaded_files);
   g_strfreev (wm_keybindings);
 
-  /* Add a separator */
-  gtk_list_store_append (GTK_LIST_STORE (self->sections_store), &iter);
-  gtk_list_store_set (GTK_LIST_STORE (self->sections_store),
-                      &iter,
-                      SECTION_DESCRIPTION_COLUMN, NULL,
-                      SECTION_GROUP_COLUMN, BINDING_GROUP_SEPARATOR,
-                      -1);
-
   /* Load custom keybindings */
   append_sections_from_gsettings (self);
 }
@@ -649,10 +882,15 @@ add_shortcuts (CcKeyboardPanel *self)
                                   DETAIL_KEYENTRY_COLUMN, item,
                                   DETAIL_TYPE_COLUMN, SHORTCUT_TYPE_KEY_ENTRY,
                                   -1);
+
+              add_item (self, item, id, title);
             }
         }
 
       can_continue = gtk_tree_model_iter_next (self->sections_model, &sections_iter);
+
+      g_free (title);
+      g_free (id);
     }
 }
 
@@ -849,6 +1087,8 @@ remove_custom_shortcut (CcKeyboardPanel *self,
   /* not a custom shortcut */
   g_assert (item->type == CC_KEYBOARD_ITEM_TYPE_GSETTINGS_PATH);
 
+  remove_item (self, item);
+
   g_settings_delay (item->settings);
   g_settings_reset (item->settings, "name");
   g_settings_reset (item->settings, "command");
@@ -931,6 +1171,8 @@ add_custom_shortcut (CcKeyboardPanel *self,
       gtk_tree_view_expand_to_path (tree_view, path);
       gtk_tree_view_scroll_to_cell (tree_view, path, NULL, FALSE, 0, 0);
       gtk_tree_path_free (path);
+
+      add_item (self, item, CUSTOM_SHORTCUTS_ID, _("Custom Shortcuts"));
     }
   else
     {
@@ -1688,6 +1930,7 @@ cc_keyboard_panel_finalize (GObject *object)
   g_clear_pointer (&self->pictures_regex, g_regex_unref);
   g_clear_pointer (&self->wm_changed_id, wm_common_unregister_window_manager_change);
 
+  g_clear_object (&self->accelerator_sizegroup);
   g_clear_object (&self->custom_shortcut_dialog);
   g_clear_object (&self->binding_settings);
   g_clear_object (&self->sections_store);
@@ -1741,11 +1984,13 @@ cc_keyboard_panel_class_init (CcKeyboardPanelClass *klass)
 
   gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/control-center/keyboard/gnome-keyboard-panel.ui");
 
+  gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, add_shortcut_row);
   gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, add_toolbutton);
   gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, custom_shortcut_command_entry);
   gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, custom_shortcut_dialog);
   gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, custom_shortcut_name_entry);
   gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, custom_shortcut_ok_button);
+  gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, listbox);
   gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, remove_toolbutton);
   gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, shortcut_toolbar);
   gtk_widget_class_bind_template_child (widget_class, CcKeyboardPanel, shortcut_treeview);
@@ -1764,4 +2009,17 @@ cc_keyboard_panel_init (CcKeyboardPanel *self)
   gtk_widget_init_template (GTK_WIDGET (self));
 
   self->binding_settings = g_settings_new (BINDINGS_SCHEMA);
+
+  /* Use a sizegroup to make the accelerator labels the same width */
+  self->accelerator_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+
+  gtk_list_box_set_sort_func (GTK_LIST_BOX (self->listbox),
+                              sort_function,
+                              self,
+                              NULL);
+
+  gtk_list_box_set_header_func (GTK_LIST_BOX (self->listbox),
+                                header_function,
+                                self,
+                                NULL);
 }
diff --git a/panels/keyboard/gnome-keyboard-panel.ui b/panels/keyboard/gnome-keyboard-panel.ui
index 5a95dd4..99bf463 100644
--- a/panels/keyboard/gnome-keyboard-panel.ui
+++ b/panels/keyboard/gnome-keyboard-panel.ui
@@ -202,6 +202,49 @@
                   </packing>
                 </child>
                 <child>
+                  <object class="GtkScrolledWindow">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="hexpand">True</property>
+                    <property name="vexpand">True</property>
+                    <property name="hscrollbar_policy">never</property>
+                    <property name="shadow_type">in</property>
+                    <child>
+                      <object class="GtkListBox" id="listbox">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="selection-mode">none</property>
+                        <property name="width-request">100</property>
+                        <child>
+                          <object class="GtkListBoxRow" id="add_shortcut_row">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <child>
+                              <object class="GtkBox">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="hexpand">True</property>
+                                <property name="border_width">6</property>
+                                <child type="center">
+                                  <object class="GtkImage">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="icon_name">list-add-symbolic</property>
+                                  </object>
+                                </child>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left_attach">2</property>
+                    <property name="top_attach">0</property>
+                  </packing>
+                </child>
+                <child>
                   <object class="GtkToolbar" id="shortcut_toolbar">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]