[gnome-control-center/wip/new-keybindings-ui: 16/20] keyboard: Display sections in a separate treeview



commit b71ebbab231a475fbd129defbff72ac88bb2dcc3
Author: Rodrigo Moya <rodrigo gnome-db org>
Date:   Thu Dec 9 10:42:33 2010 +0100

    keyboard: Display sections in a separate treeview

 panels/keyboard/gnome-keyboard-panel.c  |  732 +-----------------------------
 panels/keyboard/gnome-keyboard-panel.ui |    5 +-
 panels/keyboard/keyboard-shortcuts.c    |  772 ++++++++++++++++++++++++++++++-
 3 files changed, 773 insertions(+), 736 deletions(-)
---
diff --git a/panels/keyboard/gnome-keyboard-panel.c b/panels/keyboard/gnome-keyboard-panel.c
index e6f4d9e..97a2153 100644
--- a/panels/keyboard/gnome-keyboard-panel.c
+++ b/panels/keyboard/gnome-keyboard-panel.c
@@ -7,85 +7,21 @@
 #include <stdlib.h>
 #include <string.h>
 #include <gtk/gtk.h>
-#include <gconf/gconf-client.h>
 #include <gdk/gdkx.h>
 #include <X11/Xatom.h>
-#include <glib/gi18n.h>
 #include <gdk/gdkkeysyms.h>
 #include <libgnome-control-center/cc-shell.h>
 
-#include "wm-common.h"
 #include "gnome-keyboard-panel.h"
-#include "eggcellrendererkeys.h"
 
-#define GCONF_BINDING_DIR "/desktop/gnome/keybindings"
 #define MAX_ELEMENTS_BEFORE_SCROLLING 10
 #define MAX_CUSTOM_SHORTCUTS 1000
 #define RESPONSE_ADD 0
 #define RESPONSE_REMOVE 1
 
-typedef struct {
-  char *name;
-  /* The gettext package to use to translate the section title */
-  char *package;
-  /* Name of the window manager the keys would apply to */
-  char *wm_name;
-  /* an array of KeyListEntry */
-  GArray *entries;
-} KeyList;
-
-typedef enum {
-  COMPARISON_NONE = 0,
-  COMPARISON_GT,
-  COMPARISON_LT,
-  COMPARISON_EQ
-} Comparison;
-
-typedef struct
-{
-  char *name;
-  int value;
-  char *key;
-  char *description_name;
-  char *cmd_name;
-  Comparison comparison;
-} KeyListEntry;
-
-enum
-{
-  DESCRIPTION_COLUMN,
-  KEYENTRY_COLUMN,
-  N_COLUMNS
-};
-
-typedef struct
-{
-  char *gconf_key;
-  guint keyval;
-  guint keycode;
-  EggVirtualModifierType mask;
-  gboolean editable;
-  GtkTreeModel *model;
-  char *description;
-  char *desc_gconf_key;
-  gboolean desc_editable;
-  char *command;
-  char *cmd_gconf_key;
-  gboolean cmd_editable;
-  guint gconf_cnxn;
-  guint gconf_cnxn_desc;
-  guint gconf_cnxn_cmd;
-} KeyEntry;
-
-static guint maybe_block_accels_id = 0;
 static gboolean block_accels = FALSE;
-static GtkWidget *custom_shortcut_dialog = NULL;
-static GtkWidget *custom_shortcut_name_entry = NULL;
-static GtkWidget *custom_shortcut_command_entry = NULL;
 static GHashTable *keyb_sections = NULL;
 
-#define WID(builder, name) (GTK_WIDGET (gtk_builder_get_object (builder, name)))
-
 static char*
 binding_name (guint                   keyval,
 	      guint		      keycode,
@@ -101,91 +37,6 @@ binding_name (guint                   keyval,
 }
 
 static gboolean
-binding_from_string (const char             *str,
-                     guint                  *accelerator_key,
-		     guint		    *keycode,
-                     EggVirtualModifierType *accelerator_mods)
-{
-  g_return_val_if_fail (accelerator_key != NULL, FALSE);
-
-  if (str == NULL || strcmp (str, "disabled") == 0)
-    {
-      *accelerator_key = 0;
-      *keycode = 0;
-      *accelerator_mods = 0;
-      return TRUE;
-    }
-
-  egg_accelerator_parse_virtual (str, accelerator_key, keycode, accelerator_mods);
-
-  if (*accelerator_key == 0)
-    return FALSE;
-  else
-    return TRUE;
-}
-
-static void
-accel_set_func (GtkTreeViewColumn *tree_column,
-                GtkCellRenderer   *cell,
-                GtkTreeModel      *model,
-                GtkTreeIter       *iter,
-                gpointer           data)
-{
-  KeyEntry *key_entry;
-
-  gtk_tree_model_get (model, iter,
-                      KEYENTRY_COLUMN, &key_entry,
-                      -1);
-
-  if (key_entry == NULL)
-    g_object_set (cell,
-		  "visible", FALSE,
-		  NULL);
-  else if (! key_entry->editable)
-    g_object_set (cell,
-		  "visible", TRUE,
-		  "editable", FALSE,
-		  "accel_key", key_entry->keyval,
-		  "accel_mask", key_entry->mask,
-		  "keycode", key_entry->keycode,
-		  "style", PANGO_STYLE_ITALIC,
-		  NULL);
-  else
-    g_object_set (cell,
-		  "visible", TRUE,
-		  "editable", TRUE,
-		  "accel_key", key_entry->keyval,
-		  "accel_mask", key_entry->mask,
-		  "keycode", key_entry->keycode,
-		  "style", PANGO_STYLE_NORMAL,
-		  NULL);
-}
-
-static void
-description_set_func (GtkTreeViewColumn *tree_column,
-                      GtkCellRenderer   *cell,
-                      GtkTreeModel      *model,
-                      GtkTreeIter       *iter,
-                      gpointer           data)
-{
-  KeyEntry *key_entry;
-
-  gtk_tree_model_get (model, iter,
-                      KEYENTRY_COLUMN, &key_entry,
-                      -1);
-
-  if (key_entry != NULL)
-    g_object_set (cell,
-		  "editable", FALSE,
-		  "text", key_entry->description != NULL ?
-			  key_entry->description : _("<Unknown Action>"),
-		  NULL);
-  else
-    g_object_set (cell,
-		  "editable", FALSE, NULL);
-}
-
-static gboolean
 keybinding_key_changed_foreach (GtkTreeModel *model,
 				GtkTreePath  *path,
 				GtkTreeIter  *iter,
@@ -434,43 +285,6 @@ key_is_already_shown (GtkTreeModel *model, const KeyListEntry *entry)
 }
 
 static gboolean
-should_show_key (const KeyListEntry *entry)
-{
-  int value;
-  GConfClient *client;
-
-  if (entry->comparison == COMPARISON_NONE)
-    return TRUE;
-
-  g_return_val_if_fail (entry->key != NULL, FALSE);
-
-  client = gconf_client_get_default();
-  value = gconf_client_get_int (client, entry->key, NULL);
-  g_object_unref (client);
-
-  switch (entry->comparison) {
-  case COMPARISON_NONE:
-    /* For compiler warnings */
-    g_assert_not_reached ();
-    return FALSE;
-  case COMPARISON_GT:
-    if (value > entry->value)
-      return TRUE;
-    break;
-  case COMPARISON_LT:
-    if (value < entry->value)
-      return TRUE;
-    break;
-  case COMPARISON_EQ:
-    if (value == entry->value)
-      return TRUE;
-    break;
-  }
-
-  return FALSE;
-}
-
-static gboolean
 count_rows_foreach (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
 {
   gint *rows = data;
@@ -530,14 +344,10 @@ append_keys_to_tree (GtkBuilder         *builder,
 		     const gchar        *title,
 		     const KeyListEntry *keys_list)
 {
-  GConfClient *client;
   GtkTreeIter parent_iter, iter;
   GtkTreeModel *model;
   gint i, j;
 
-  client = gconf_client_get_default ();
-  model = gtk_tree_view_get_model (GTK_TREE_VIEW (gtk_builder_get_object (builder, "shortcut_treeview")));
-
   /* Try to find a section parent iter, if it already exists */
   find_section (model, &iter, title);
   parent_iter = iter;
@@ -549,121 +359,7 @@ append_keys_to_tree (GtkBuilder         *builder,
    * then we need to scroll now */
   ensure_scrollbar (builder, i - 1);
 
-  for (j = 0; keys_list[j].name != NULL; j++)
-    {
-      GConfEntry *entry;
-      KeyEntry *key_entry;
-      const gchar *key_string;
-      gchar *key_value;
-      gchar *description;
-      gchar *command;
-
-      if (!should_show_key (&keys_list[j]))
-	continue;
-
-      if (key_is_already_shown (model, &keys_list[j]))
-	continue;
-
-      key_string = keys_list[j].name;
-
-      entry = gconf_client_get_entry (client,
-                                      key_string,
-				      NULL,
-				      TRUE,
-				      NULL);
-      if (entry == NULL)
-	{
-	  /* We don't actually want to popup a dialog - just skip this one */
-	  continue;
-	}
-
-      if (keys_list[j].description_name != NULL)
-        {
-          description = gconf_client_get_string (client, keys_list[j].description_name, NULL);
-        }
-      else
-        {
-          description = NULL;
-
-          if (gconf_entry_get_schema_name (entry))
-            {
-              GConfSchema *schema;
-
-              schema = gconf_client_get_schema (client,
-                                                gconf_entry_get_schema_name (entry),
-                                                NULL);
-              if (schema != NULL)
-                {
-                  description = g_strdup (gconf_schema_get_short_desc (schema));
-                  gconf_schema_free (schema);
-                }
-            }
-        }
-
-      if (description == NULL)
-        {
-	  /* Only print a warning for keys that should have a schema */
-	  if (keys_list[j].description_name == NULL)
-	    g_warning ("No description for key '%s'", key_string);
-	}
-
-      if (keys_list[j].cmd_name != NULL)
-        {
-          command = gconf_client_get_string (client, keys_list[j].cmd_name, NULL);
-        }
-      else
-        {
-          command = NULL;
-        }
-
-      key_entry = g_new0 (KeyEntry, 1);
-      key_entry->gconf_key = g_strdup (key_string);
-      key_entry->editable = gconf_entry_get_is_writable (entry);
-      key_entry->model = model;
-      key_entry->description = description;
-      key_entry->command = command;
-      if (keys_list[j].description_name != NULL)
-        {
-          key_entry->desc_gconf_key =  g_strdup (keys_list[j].description_name);
-          key_entry->desc_editable = gconf_client_key_is_writable (client, key_entry->desc_gconf_key, NULL);
-          key_entry->gconf_cnxn_desc = gconf_client_notify_add (client,
-								key_entry->desc_gconf_key,
-								(GConfClientNotifyFunc) &keybinding_description_changed,
-								key_entry, NULL, NULL);
-        }
-      if (keys_list[j].cmd_name != NULL)
-        {
-          key_entry->cmd_gconf_key =  g_strdup (keys_list[j].cmd_name);
-          key_entry->cmd_editable = gconf_client_key_is_writable (client, key_entry->cmd_gconf_key, NULL);
-          key_entry->gconf_cnxn_cmd = gconf_client_notify_add (client,
-							       key_entry->cmd_gconf_key,
-								(GConfClientNotifyFunc) &keybinding_command_changed,
-								key_entry, NULL, NULL);
-        }
-
-      gconf_client_add_dir (client, key_string, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
-      key_entry->gconf_cnxn = gconf_client_notify_add (client,
-						       key_string,
-						       (GConfClientNotifyFunc) &keybinding_key_changed,
-						       key_entry, NULL, NULL);
-
-      key_value = gconf_client_get_string (client, key_string, NULL);
-      binding_from_string (key_value, &key_entry->keyval, &key_entry->keycode, &key_entry->mask);
-      g_free (key_value);
-
-      gconf_entry_free (entry);
-      ensure_scrollbar (builder, i);
-
-      ++i;
-      gtk_tree_store_append (GTK_TREE_STORE (model), &iter, &parent_iter);
-      /* we use the DESCRIPTION_COLUMN only for the section headers */
-      gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
-			  KEYENTRY_COLUMN, key_entry,
-			  -1);
-      gtk_tree_view_expand_all (GTK_TREE_VIEW (gtk_builder_get_object (builder, "shortcut_treeview")));
-    }
-
-  g_object_unref (client);
+===============================================================
 
   /* Don't show an empty section */
   if (gtk_tree_model_iter_n_children (model, &parent_iter) == 0)
@@ -676,318 +372,6 @@ append_keys_to_tree (GtkBuilder         *builder,
 }
 
 static void
-parse_start_tag (GMarkupParseContext *ctx,
-		 const gchar         *element_name,
-		 const gchar        **attr_names,
-		 const gchar        **attr_values,
-		 gpointer             user_data,
-		 GError             **error)
-{
-  KeyList *keylist = (KeyList *) user_data;
-  KeyListEntry key;
-  const char *name, *gconf_key;
-  int value;
-  Comparison comparison;
-
-  name = NULL;
-
-  /* The top-level element, names the section in the tree */
-  if (g_str_equal (element_name, "KeyListEntries"))
-    {
-      const char *wm_name = NULL;
-      const char *package = NULL;
-
-      while (*attr_names && *attr_values)
-        {
-	  if (g_str_equal (*attr_names, "name"))
-	    {
-	      if (**attr_values)
-		name = *attr_values;
-	    } else if (g_str_equal (*attr_names, "wm_name")) {
-	      if (**attr_values)
-		wm_name = *attr_values;
-	    } else if (g_str_equal (*attr_names, "package")) {
-	      if (**attr_values)
-		package = *attr_values;
-	    }
-	  ++attr_names;
-	  ++attr_values;
-	}
-
-      if (name)
-        {
-	  if (keylist->name)
-	    g_warning ("Duplicate section name");
-	  g_free (keylist->name);
-	  keylist->name = g_strdup (name);
-	}
-      if (wm_name)
-        {
-	  if (keylist->wm_name)
-	    g_warning ("Duplicate window manager name");
-	  g_free (keylist->wm_name);
-	  keylist->wm_name = g_strdup (wm_name);
-	}
-      if (package)
-        {
-	  if (keylist->package)
-	    g_warning ("Duplicate gettext package name");
-	  g_free (keylist->package);
-	  keylist->package = g_strdup (package);
-	}
-      return;
-    }
-
-  if (!g_str_equal (element_name, "KeyListEntry")
-      || attr_names == NULL
-      || attr_values == NULL)
-    return;
-
-  value = 0;
-  comparison = COMPARISON_NONE;
-  gconf_key = NULL;
-
-  while (*attr_names && *attr_values)
-    {
-      if (g_str_equal (*attr_names, "name"))
-        {
-	  /* skip if empty */
-	  if (**attr_values)
-	    name = *attr_values;
-	} else if (g_str_equal (*attr_names, "value")) {
-	  if (**attr_values) {
-	    value = (int) g_ascii_strtoull (*attr_values, NULL, 0);
-	  }
-	} else if (g_str_equal (*attr_names, "key")) {
-	  if (**attr_values) {
-	    gconf_key = *attr_values;
-	  }
-	} else if (g_str_equal (*attr_names, "comparison")) {
-	  if (**attr_values) {
-	    if (g_str_equal (*attr_values, "gt")) {
-	      comparison = COMPARISON_GT;
-	    } else if (g_str_equal (*attr_values, "lt")) {
-	      comparison = COMPARISON_LT;
-	    } else if (g_str_equal (*attr_values, "eq")) {
-	      comparison = COMPARISON_EQ;
-	    }
-	  }
-	}
-
-      ++attr_names;
-      ++attr_values;
-    }
-
-  if (name == NULL)
-    return;
-
-  key.name = g_strdup (name);
-  key.description_name = NULL;
-  key.value = value;
-  if (gconf_key)
-    key.key = g_strdup (gconf_key);
-  else
-    key.key = NULL;
-  key.comparison = comparison;
-  key.cmd_name = NULL;
-  g_array_append_val (keylist->entries, key);
-}
-
-static gboolean
-strv_contains (char **strv,
-	       char  *str)
-{
-  char **p = strv;
-  for (p = strv; *p; p++)
-    if (strcmp (*p, str) == 0)
-      return TRUE;
-
-  return FALSE;
-}
-
-static void
-append_keys_to_tree_from_file (GtkBuilder *builder,
-			       const char *filename,
-			       char      **wm_keybindings)
-{
-  GMarkupParseContext *ctx;
-  GMarkupParser parser = { parse_start_tag, NULL, NULL, NULL, NULL };
-  KeyList *keylist;
-  KeyListEntry key, *keys;
-  GError *err = NULL;
-  char *buf;
-  const char *title;
-  gsize buf_len;
-  guint i;
-
-  if (!g_file_get_contents (filename, &buf, &buf_len, &err))
-    return;
-
-  keylist = g_new0 (KeyList, 1);
-  keylist->entries = g_array_new (FALSE, TRUE, sizeof (KeyListEntry));
-  ctx = g_markup_parse_context_new (&parser, 0, keylist, NULL);
-
-  if (!g_markup_parse_context_parse (ctx, buf, buf_len, &err))
-    {
-      g_warning ("Failed to parse '%s': '%s'", filename, err->message);
-      g_error_free (err);
-      g_free (keylist->name);
-      g_free (keylist->package);
-      g_free (keylist->wm_name);
-      for (i = 0; i < keylist->entries->len; i++)
-	g_free (((KeyListEntry *) &(keylist->entries->data[i]))->name);
-      g_array_free (keylist->entries, TRUE);
-      g_free (keylist);
-      keylist = NULL;
-    }
-  g_markup_parse_context_free (ctx);
-  g_free (buf);
-
-  if (keylist == NULL)
-    return;
-
-  /* If there's no keys to add, or the settings apply to a window manager
-   * that's not the one we're running */
-  if (keylist->entries->len == 0
-      || (keylist->wm_name != NULL && !strv_contains (wm_keybindings, keylist->wm_name))
-      || keylist->name == NULL)
-    {
-      g_free (keylist->name);
-      g_free (keylist->package);
-      g_free (keylist->wm_name);
-      g_array_free (keylist->entries, TRUE);
-      g_free (keylist);
-      return;
-    }
-
-  /* Empty KeyListEntry to end the array */
-  key.name = NULL;
-  key.description_name = NULL;
-  key.key = NULL;
-  key.value = 0;
-  key.comparison = COMPARISON_NONE;
-  g_array_append_val (keylist->entries, key);
-
-  keys = (KeyListEntry *) g_array_free (keylist->entries, FALSE);
-  if (keylist->package)
-    {
-      bind_textdomain_codeset (keylist->package, "UTF-8");
-      title = dgettext (keylist->package, keylist->name);
-    } else {
-      title = _(keylist->name);
-    }
-
-  append_keys_to_tree (builder, title, keys);
-
-  g_free (keylist->name);
-  g_free (keylist->package);
-  for (i = 0; keys[i].name != NULL; i++)
-    g_free (keys[i].name);
-  g_free (keylist);
-}
-
-static void
-append_keys_to_tree_from_gconf (GtkBuilder *builder, const gchar *gconf_path)
-{
-  GConfClient *client;
-  GSList *custom_list, *l;
-  GArray *entries;
-  KeyListEntry key;
-
-  /* load custom shortcuts from GConf */
-  entries = g_array_new (FALSE, TRUE, sizeof (KeyListEntry));
-
-  key.key = NULL;
-  key.value = 0;
-  key.comparison = COMPARISON_NONE;
-
-  client = gconf_client_get_default ();
-  custom_list = gconf_client_all_dirs (client, gconf_path, NULL);
-
-  for (l = custom_list; l != NULL; l = l->next)
-    {
-      key.name = g_strconcat (l->data, "/binding", NULL);
-      key.cmd_name = g_strconcat (l->data, "/action", NULL);
-      key.description_name = g_strconcat (l->data, "/name", NULL);
-      g_array_append_val (entries, key);
-
-      g_free (l->data);
-    }
-
-  g_slist_free (custom_list);
-  g_object_unref (client);
-
-  if (entries->len > 0)
-    {
-      KeyListEntry *keys;
-      int i;
-
-      /* Empty KeyListEntry to end the array */
-      key.name = NULL;
-      key.description_name = NULL;
-      g_array_append_val (entries, key);
-
-      keys = (KeyListEntry *) entries->data;
-      append_keys_to_tree (builder, _("Custom Shortcuts"), keys);
-      for (i = 0; i < entries->len; ++i)
-        {
-          g_free (keys[i].name);
-          g_free (keys[i].description_name);
-        }
-    }
-
-  g_array_free (entries, TRUE);
-}
-
-static void
-reload_key_entries (GtkBuilder *builder)
-{
-  gchar **wm_keybindings;
-  GDir *dir;
-  const char *name;
-  GList *list, *l;
-
-  wm_keybindings = wm_common_get_current_keybindings();
-
-  clear_old_model (builder);
-
-  dir = g_dir_open (GNOMECC_KEYBINDINGS_DIR, 0, NULL);
-  if (!dir)
-      return;
-
-  list = NULL;
-  for (name = g_dir_read_name (dir) ; name ; name = g_dir_read_name (dir))
-    {
-      if (g_str_has_suffix (name, ".xml"))
-        {
-	  list = g_list_insert_sorted (list, g_strdup (name),
-				       (GCompareFunc) g_ascii_strcasecmp);
-	}
-    }
-  g_dir_close (dir);
-
-  for (l = list; l != NULL; l = l->next)
-    {
-        gchar *path;
-
-	path = g_build_filename (GNOMECC_KEYBINDINGS_DIR, l->data, NULL);
-        append_keys_to_tree_from_file (builder, path, wm_keybindings);
-	g_free (l->data);
-	g_free (path);
-    }
-  g_list_free (list);
-
-  /* Load custom shortcuts _after_ system-provided ones,
-   * since some of the custom shortcuts may also be listed
-   * in a file. Loading the custom shortcuts last makes
-   * such keys not show up in the custom section.
-   */
-  append_keys_to_tree_from_gconf (builder, GCONF_BINDING_DIR);
-
-  g_strfreev (wm_keybindings);
-}
-
-static void
 key_entry_controlling_key_changed (GConfClient *client,
 				   guint        cnxn_id,
 				   GConfEntry  *entry,
@@ -1820,117 +1204,6 @@ remove_button_clicked (GtkWidget  *button,
 }
 
 static void
-setup_dialog (CcPanel *panel, GtkBuilder *builder)
-{
-  GConfClient *client;
-  GtkCellRenderer *renderer;
-  GtkTreeViewColumn *column;
-  GtkWidget *widget;
-  GtkTreeView *treeview;
-  GtkTreeSelection *selection;
-  GSList *allowed_keys;
-  CcShell *shell;
-
-  treeview = GTK_TREE_VIEW (gtk_builder_get_object (builder,
-                                                    "shortcut_treeview"));
-
-  client = gconf_client_get_default ();
-
-  g_signal_connect (treeview, "button_press_event",
-		    G_CALLBACK (start_editing_cb), builder);
-  g_signal_connect (treeview, "row-activated",
-		    G_CALLBACK (start_editing_kb_cb), NULL);
-
-  renderer = gtk_cell_renderer_text_new ();
-
-  g_signal_connect (renderer, "edited",
-                    G_CALLBACK (description_edited_callback),
-                    treeview);
-
-  column = gtk_tree_view_column_new_with_attributes (_("Action"),
-						     renderer,
-						     "text", DESCRIPTION_COLUMN,
-						     NULL);
-  gtk_tree_view_column_set_cell_data_func (column, renderer, description_set_func, NULL, NULL);
-  gtk_tree_view_column_set_resizable (column, FALSE);
-
-  gtk_tree_view_append_column (treeview, column);
-  gtk_tree_view_column_set_sort_column_id (column, DESCRIPTION_COLUMN);
-
-  renderer = (GtkCellRenderer *) g_object_new (EGG_TYPE_CELL_RENDERER_KEYS,
-					       "accel_mode", EGG_CELL_RENDERER_KEYS_MODE_X,
-					       NULL);
-
-  g_signal_connect (renderer, "accel_edited",
-                    G_CALLBACK (accel_edited_callback),
-                    treeview);
-
-  g_signal_connect (renderer, "accel_cleared",
-                    G_CALLBACK (accel_cleared_callback),
-                    treeview);
-
-  column = gtk_tree_view_column_new_with_attributes (_("Shortcut"), renderer, NULL);
-  gtk_tree_view_column_set_cell_data_func (column, renderer, accel_set_func, NULL, NULL);
-  gtk_tree_view_column_set_resizable (column, FALSE);
-
-  gtk_tree_view_append_column (treeview, column);
-  gtk_tree_view_column_set_sort_column_id (column, KEYENTRY_COLUMN);
-
-  gconf_client_add_dir (client, GCONF_BINDING_DIR, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
-  gconf_client_add_dir (client, "/apps/metacity/general", GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
-  gconf_client_notify_add (client,
-			   "/apps/metacity/general/num_workspaces",
-			   (GConfClientNotifyFunc) key_entry_controlling_key_changed,
-			   builder, NULL, NULL);
-
-  /* set up the dialog */
-  reload_key_entries (builder);
-
-  shell = cc_panel_get_shell (CC_PANEL (panel));
-  widget = cc_shell_get_toplevel (shell);
-
-  maybe_block_accels_id = g_signal_connect (widget, "key_press_event",
-					    G_CALLBACK (maybe_block_accels), NULL);
-
-  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
-  g_signal_connect (selection, "changed",
-                    G_CALLBACK (selection_changed),
-		    WID (builder, "remove-button"));
-
-  allowed_keys = gconf_client_get_list (client,
-                                        GCONF_BINDING_DIR "/allowed_keys",
-                                        GCONF_VALUE_STRING,
-                                        NULL);
-  if (allowed_keys != NULL)
-    {
-      g_slist_foreach (allowed_keys, (GFunc)g_free, NULL);
-      g_slist_free (allowed_keys);
-      gtk_widget_set_sensitive (WID (builder, "add-button"),
-                                FALSE);
-    }
-
-  g_object_unref (client);
-
-  /* setup the custom shortcut dialog */
-  custom_shortcut_dialog = WID (builder,
-                                                    "custom-shortcut-dialog");
-  custom_shortcut_name_entry = WID (builder,
-                                                        "custom-shortcut-name-entry");
-  custom_shortcut_command_entry = WID (builder,
-                                                           "custom-shortcut-command-entry");
-  g_signal_connect (WID (builder, "add-button"),
-                    "clicked", G_CALLBACK (add_button_clicked), builder);
-  g_signal_connect (WID (builder, "remove-button"),
-                    "clicked", G_CALLBACK (remove_button_clicked), builder);
-
-  gtk_dialog_set_default_response (GTK_DIALOG (custom_shortcut_dialog),
-				   GTK_RESPONSE_OK);
-
-  gtk_window_set_transient_for (GTK_WINDOW (custom_shortcut_dialog),
-                                GTK_WINDOW (widget));
-}
-
-static void
 on_window_manager_change (const char *wm_name, GtkBuilder *builder)
 {
   reload_key_entries (builder);
@@ -1942,9 +1215,6 @@ gnome_keybinding_properties_init (CcPanel *panel, GtkBuilder *builder)
   wm_common_register_window_manager_change ((GFunc) on_window_manager_change,
                                             builder);
 
-  keyb_sections = g_hash_table_new_full (g_str_hash, g_str_equal,
-					 g_free, free_key_list);
-  setup_dialog (panel, builder);
 }
 
 void
diff --git a/panels/keyboard/gnome-keyboard-panel.ui b/panels/keyboard/gnome-keyboard-panel.ui
index e7d5322..1732920 100644
--- a/panels/keyboard/gnome-keyboard-panel.ui
+++ b/panels/keyboard/gnome-keyboard-panel.ui
@@ -552,6 +552,7 @@
                               <object class="GtkTreeView" id="section_treeview">
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
+                                <property name="headers_visible">False</property>
                               </object>
                             </child>
                           </object>
@@ -565,8 +566,8 @@
                           <object class="GtkScrolledWindow" id="actions_swindow">
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
-                            <property name="hscrollbar_policy">never</property>
-                            <property name="vscrollbar_policy">never</property>
+                            <property name="hscrollbar_policy">automatic</property>
+                            <property name="vscrollbar_policy">automatic</property>
                             <property name="shadow_type">in</property>
                             <child>
                               <object class="GtkTreeView" id="shortcut_treeview">
diff --git a/panels/keyboard/keyboard-shortcuts.c b/panels/keyboard/keyboard-shortcuts.c
index 490025f..2496c47 100644
--- a/panels/keyboard/keyboard-shortcuts.c
+++ b/panels/keyboard/keyboard-shortcuts.c
@@ -19,25 +19,791 @@
  *          Rodrigo Moya <rodrigo gnome org>
  */
 
+#include <glib/gi18n.h>
+#include <gconf/gconf-client.h>
+#include "eggcellrendererkeys.h"
 #include "keyboard-shortcuts.h"
+#include "wm-common.h"
 
-GHashTable *kb_sections = NULL;
+#define GCONF_BINDING_DIR "/desktop/gnome/keybindings"
+#define WID(builder, name) (GTK_WIDGET (gtk_builder_get_object (builder, name)))
+
+typedef struct {
+  char *name;
+  /* The gettext package to use to translate the section title */
+  char *package;
+  /* Name of the window manager the keys would apply to */
+  char *wm_name;
+  /* an array of KeyListEntry */
+  GArray *entries;
+} KeyList;
+
+typedef enum {
+  COMPARISON_NONE = 0,
+  COMPARISON_GT,
+  COMPARISON_LT,
+  COMPARISON_EQ
+} Comparison;
+
+typedef struct
+{
+  char *name;
+  int value;
+  char *key;
+  char *description_name;
+  char *cmd_name;
+  Comparison comparison;
+} KeyListEntry;
+
+typedef struct
+{
+  char *gconf_key;
+  guint keyval;
+  guint keycode;
+  EggVirtualModifierType mask;
+  gboolean editable;
+  GtkTreeModel *model;
+  char *description;
+  char *desc_gconf_key;
+  gboolean desc_editable;
+  char *command;
+  char *cmd_gconf_key;
+  gboolean cmd_editable;
+  guint gconf_cnxn;
+  guint gconf_cnxn_desc;
+  guint gconf_cnxn_cmd;
+} KeyEntry;
+
+enum
+{
+  DESCRIPTION_COLUMN,
+  KEYENTRY_COLUMN,
+  N_COLUMNS
+};
+
+static guint maybe_block_accels_id = 0;
+static GtkWidget *custom_shortcut_dialog = NULL;
+static GtkWidget *custom_shortcut_name_entry = NULL;
+static GtkWidget *custom_shortcut_command_entry = NULL;
+static GHashTable *kb_sections = NULL;
 
 static void
-free_key_list (gpointer list)
+free_key_array (KeyEntry **keys)
 {
+  if (keys != NULL)
+    {
+      gint i;
+
+      for (i = 0; i < G_N_ELEMENTS (keys); i++)
+        {
+	  g_free (keys[i]->gconf_key);
+	  g_free (keys[i]->description);
+	  g_free (keys[i]->desc_gconf_key);
+	  g_free (keys[i]->command);
+	  g_free (keys[i]->cmd_gconf_key);
+	}
+
+      g_free (keys);
+    }
+}
+
+static gboolean
+should_show_key (const KeyListEntry *entry)
+{
+  int value;
+  GConfClient *client;
+
+  if (entry->comparison == COMPARISON_NONE)
+    return TRUE;
+
+  g_return_val_if_fail (entry->key != NULL, FALSE);
+
+  client = gconf_client_get_default();
+  value = gconf_client_get_int (client, entry->key, NULL);
+  g_object_unref (client);
+
+  switch (entry->comparison) {
+  case COMPARISON_NONE:
+    /* For compiler warnings */
+    g_assert_not_reached ();
+    return FALSE;
+  case COMPARISON_GT:
+    if (value > entry->value)
+      return TRUE;
+    break;
+  case COMPARISON_LT:
+    if (value < entry->value)
+      return TRUE;
+    break;
+  case COMPARISON_EQ:
+    if (value == entry->value)
+      return TRUE;
+    break;
+  }
+
+  return FALSE;
+}
+
+static gboolean
+binding_from_string (const char             *str,
+                     guint                  *accelerator_key,
+		     guint		    *keycode,
+                     EggVirtualModifierType *accelerator_mods)
+{
+  g_return_val_if_fail (accelerator_key != NULL, FALSE);
+
+  if (str == NULL || strcmp (str, "disabled") == 0)
+    {
+      *accelerator_key = 0;
+      *keycode = 0;
+      *accelerator_mods = 0;
+      return TRUE;
+    }
+
+  egg_accelerator_parse_virtual (str, accelerator_key, keycode, accelerator_mods);
+
+  if (*accelerator_key == 0)
+    return FALSE;
+  else
+    return TRUE;
+}
+
+static void
+append_section (GtkBuilder *builder, const gchar *title, const KeyListEntry *keys_list)
+{
+  GArray *keys_array;
+  GtkTreeModel *model;
+  GConfClient *client;
+  GtkTreeIter iter;
+  gint i;
+
+  client = gconf_client_get_default ();
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (gtk_builder_get_object (builder, "section_treeview")));
+
+  g_print ("Appending section %s\n", title);
+
+  /* Append the section to the left tree view */
+  gtk_list_store_append (GTK_LIST_STORE (model), &iter);
+  gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+		      DESCRIPTION_COLUMN, title,
+		      -1);
+
+  /* Add all KeyEntry's for this section */
+  keys_array = g_array_new (TRUE, FALSE, sizeof (KeyEntry));
+
+  for (i = 0; keys_list[i].name != NULL; i++)
+    {
+      GConfEntry *entry;
+      const gchar *key_string;
+      gchar *description, *command, *key_value;
+      KeyEntry *key_entry;
+
+      if (!should_show_key (&keys_list[i]))
+	continue;
+
+      key_string = keys_list[i].name;
+
+      entry = gconf_client_get_entry (client,
+                                      key_string,
+				      NULL,
+				      TRUE,
+				      NULL);
+      if (entry == NULL)
+	{
+	  /* We don't actually want to popup a dialog - just skip this one */
+	  continue;
+	}
+
+      if (keys_list[i].description_name != NULL)
+        {
+          description = gconf_client_get_string (client, keys_list[i].description_name, NULL);
+        }
+      else
+        {
+          description = NULL;
+
+          if (gconf_entry_get_schema_name (entry))
+            {
+              GConfSchema *schema;
+
+              schema = gconf_client_get_schema (client,
+                                                gconf_entry_get_schema_name (entry),
+                                                NULL);
+              if (schema != NULL)
+                {
+                  description = g_strdup (gconf_schema_get_short_desc (schema));
+                  gconf_schema_free (schema);
+                }
+            }
+        }
+
+      if (description == NULL)
+        {
+	  /* Only print a warning for keys that should have a schema */
+	  if (keys_list[i].description_name == NULL)
+	    g_warning ("No description for key '%s'", key_string);
+	}
+
+      if (keys_list[i].cmd_name != NULL)
+        {
+          command = gconf_client_get_string (client, keys_list[i].cmd_name, NULL);
+        }
+      else
+        {
+          command = NULL;
+        }
+
+      key_entry = g_new0 (KeyEntry, 1);
+      key_entry->gconf_key = g_strdup (key_string);
+      key_entry->editable = gconf_entry_get_is_writable (entry);
+      key_entry->model = model;
+      key_entry->description = description;
+      key_entry->command = command;
+      if (keys_list[i].description_name != NULL)
+        {
+          key_entry->desc_gconf_key =  g_strdup (keys_list[i].description_name);
+          key_entry->desc_editable = gconf_client_key_is_writable (client, key_entry->desc_gconf_key, NULL);
+          /* key_entry->gconf_cnxn_desc = gconf_client_notify_add (client, */
+	  /* 							key_entry->desc_gconf_key, */
+	  /* 							(GConfClientNotifyFunc) &keybinding_description_changed, */
+	  /* 							key_entry, NULL, NULL); */
+        }
+      if (keys_list[i].cmd_name != NULL)
+        {
+          /* key_entry->cmd_gconf_key =  g_strdup (keys_list[i].cmd_name); */
+          /* key_entry->cmd_editable = gconf_client_key_is_writable (client, key_entry->cmd_gconf_key, NULL); */
+          /* key_entry->gconf_cnxn_cmd = gconf_client_notify_add (client, */
+	  /* 						       key_entry->cmd_gconf_key, */
+	  /* 							(GConfClientNotifyFunc) &keybinding_command_changed, */
+	  /* 							key_entry, NULL, NULL); */
+        }
+
+      gconf_client_add_dir (client, key_string, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+      /* key_entry->gconf_cnxn = gconf_client_notify_add (client, */
+      /* 						       key_string, */
+      /* 						       (GConfClientNotifyFunc) &keybinding_key_changed, */
+      /* 						       key_entry, NULL, NULL); */
+
+      key_value = gconf_client_get_string (client, key_string, NULL);
+      binding_from_string (key_value, &key_entry->keyval, &key_entry->keycode, &key_entry->mask);
+      g_free (key_value);
+
+      gconf_entry_free (entry);
+
+      g_array_append_val (keys_array, key_entry);
+    }
+
+  g_object_unref (client);
+
+  /* Add the keys to the hash table */
+  if (keys_array->len > 0)
+    {
+      g_hash_table_insert (kb_sections, g_strdup (title), keys_array->data);
+    }
+
+  g_array_free (keys_array, FALSE);
+}
+
+static void
+parse_start_tag (GMarkupParseContext *ctx,
+		 const gchar         *element_name,
+		 const gchar        **attr_names,
+		 const gchar        **attr_values,
+		 gpointer             user_data,
+		 GError             **error)
+{
+  KeyList *keylist = (KeyList *) user_data;
+  KeyListEntry key;
+  const char *name, *gconf_key;
+  int value;
+  Comparison comparison;
+
+  name = NULL;
+
+  /* The top-level element, names the section in the tree */
+  if (g_str_equal (element_name, "KeyListEntries"))
+    {
+      const char *wm_name = NULL;
+      const char *package = NULL;
+
+      while (*attr_names && *attr_values)
+        {
+	  if (g_str_equal (*attr_names, "name"))
+	    {
+	      if (**attr_values)
+		name = *attr_values;
+	    } else if (g_str_equal (*attr_names, "wm_name")) {
+	      if (**attr_values)
+		wm_name = *attr_values;
+	    } else if (g_str_equal (*attr_names, "package")) {
+	      if (**attr_values)
+		package = *attr_values;
+	    }
+	  ++attr_names;
+	  ++attr_values;
+	}
+
+      if (name)
+        {
+	  if (keylist->name)
+	    g_warning ("Duplicate section name");
+	  g_free (keylist->name);
+	  keylist->name = g_strdup (name);
+	}
+      if (wm_name)
+        {
+	  if (keylist->wm_name)
+	    g_warning ("Duplicate window manager name");
+	  g_free (keylist->wm_name);
+	  keylist->wm_name = g_strdup (wm_name);
+	}
+      if (package)
+        {
+	  if (keylist->package)
+	    g_warning ("Duplicate gettext package name");
+	  g_free (keylist->package);
+	  keylist->package = g_strdup (package);
+	}
+      return;
+    }
+
+  if (!g_str_equal (element_name, "KeyListEntry")
+      || attr_names == NULL
+      || attr_values == NULL)
+    return;
+
+  value = 0;
+  comparison = COMPARISON_NONE;
+  gconf_key = NULL;
+
+  while (*attr_names && *attr_values)
+    {
+      if (g_str_equal (*attr_names, "name"))
+        {
+	  /* skip if empty */
+	  if (**attr_values)
+	    name = *attr_values;
+	} else if (g_str_equal (*attr_names, "value")) {
+	  if (**attr_values) {
+	    value = (int) g_ascii_strtoull (*attr_values, NULL, 0);
+	  }
+	} else if (g_str_equal (*attr_names, "key")) {
+	  if (**attr_values) {
+	    gconf_key = *attr_values;
+	  }
+	} else if (g_str_equal (*attr_names, "comparison")) {
+	  if (**attr_values) {
+	    if (g_str_equal (*attr_values, "gt")) {
+	      comparison = COMPARISON_GT;
+	    } else if (g_str_equal (*attr_values, "lt")) {
+	      comparison = COMPARISON_LT;
+	    } else if (g_str_equal (*attr_values, "eq")) {
+	      comparison = COMPARISON_EQ;
+	    }
+	  }
+	}
+
+      ++attr_names;
+      ++attr_values;
+    }
+
+  if (name == NULL)
+    return;
+
+  key.name = g_strdup (name);
+  key.description_name = NULL;
+  key.value = value;
+  if (gconf_key)
+    key.key = g_strdup (gconf_key);
+  else
+    key.key = NULL;
+  key.comparison = comparison;
+  key.cmd_name = NULL;
+  g_array_append_val (keylist->entries, key);
+}
+
+static gboolean
+strv_contains (char **strv,
+	       char  *str)
+{
+  char **p = strv;
+  for (p = strv; *p; p++)
+    if (strcmp (*p, str) == 0)
+      return TRUE;
+
+  return FALSE;
+}
+
+static void
+append_sections_from_file (GtkBuilder *builder, const gchar *path, gchar **wm_keybindings)
+{
+  GError *err = NULL;
+  char *buf;
+  gsize buf_len;
+  KeyList *keylist;
+  KeyListEntry key, *keys;
+  const char *title;
+  guint i;
+  GMarkupParseContext *ctx;
+  GMarkupParser parser = { parse_start_tag, NULL, NULL, NULL, NULL };
+
+  /* Parse file */
+  if (!g_file_get_contents (path, &buf, &buf_len, &err))
+    return;
+
+  keylist = g_new0 (KeyList, 1);
+  keylist->entries = g_array_new (FALSE, TRUE, sizeof (KeyListEntry));
+  ctx = g_markup_parse_context_new (&parser, 0, keylist, NULL);
+
+  if (!g_markup_parse_context_parse (ctx, buf, buf_len, &err))
+    {
+      g_warning ("Failed to parse '%s': '%s'", path, err->message);
+      g_error_free (err);
+      g_free (keylist->name);
+      g_free (keylist->package);
+      g_free (keylist->wm_name);
+      for (i = 0; i < keylist->entries->len; i++)
+	g_free (((KeyListEntry *) &(keylist->entries->data[i]))->name);
+      g_array_free (keylist->entries, TRUE);
+      g_free (keylist);
+      keylist = NULL;
+    }
+  g_markup_parse_context_free (ctx);
+  g_free (buf);
+
+  if (keylist == NULL)
+    return;
+
+  /* If there's no keys to add, or the settings apply to a window manager
+   * that's not the one we're running */
+  if (keylist->entries->len == 0
+      || (keylist->wm_name != NULL && !strv_contains (wm_keybindings, keylist->wm_name))
+      || keylist->name == NULL)
+    {
+      g_free (keylist->name);
+      g_free (keylist->package);
+      g_free (keylist->wm_name);
+      g_array_free (keylist->entries, TRUE);
+      g_free (keylist);
+      return;
+    }
+
+  /* Empty KeyListEntry to end the array */
+  key.name = NULL;
+  key.description_name = NULL;
+  key.key = NULL;
+  key.value = 0;
+  key.comparison = COMPARISON_NONE;
+  g_array_append_val (keylist->entries, key);
+
+  keys = (KeyListEntry *) g_array_free (keylist->entries, FALSE);
+  if (keylist->package)
+    {
+      bind_textdomain_codeset (keylist->package, "UTF-8");
+      title = dgettext (keylist->package, keylist->name);
+    } else {
+      title = _(keylist->name);
+    }
+
+  append_section (builder, title, keys);
+
+  g_free (keylist->name);
+  g_free (keylist->package);
+
+  for (i = 0; keys[i].name != NULL; i++)
+    g_free (keys[i].name);
+
+  g_free (keylist);
+}
+
+static void
+append_sections_from_gconf (GtkBuilder *builder, const gchar *gconf_path)
+{
+  GConfClient *client;
+  GSList *custom_list, *l;
+  GArray *entries;
+  KeyListEntry key;
+
+  /* load custom shortcuts from GConf */
+  entries = g_array_new (FALSE, TRUE, sizeof (KeyListEntry));
+
+  key.key = NULL;
+  key.value = 0;
+  key.comparison = COMPARISON_NONE;
+
+  client = gconf_client_get_default ();
+  custom_list = gconf_client_all_dirs (client, gconf_path, NULL);
+
+  for (l = custom_list; l != NULL; l = l->next)
+    {
+      key.name = g_strconcat (l->data, "/binding", NULL);
+      key.cmd_name = g_strconcat (l->data, "/action", NULL);
+      key.description_name = g_strconcat (l->data, "/name", NULL);
+      g_array_append_val (entries, key);
+
+      g_free (l->data);
+    }
+
+  g_slist_free (custom_list);
+  g_object_unref (client);
+
+  if (entries->len > 0)
+    {
+      KeyListEntry *keys;
+      int i;
+
+      /* Empty KeyListEntry to end the array */
+      key.name = NULL;
+      key.description_name = NULL;
+      g_array_append_val (entries, key);
+
+      keys = (KeyListEntry *) entries->data;
+      append_section (builder, _("Custom Shortcuts"), keys);
+      for (i = 0; i < entries->len; ++i)
+        {
+          g_free (keys[i].name);
+          g_free (keys[i].description_name);
+        }
+    }
+
+  g_array_free (entries, TRUE);
+}
+
+static void
+reload_sections (GtkBuilder *builder)
+{
+  gchar **wm_keybindings;
+  GDir *dir;
+  const gchar *name;
+  GtkTreeModel *section_model, *shortcut_model;
+
+  section_model = gtk_tree_view_get_model (GTK_TREE_VIEW (gtk_builder_get_object (builder, "section_treeview")));
+  shortcut_model = gtk_tree_view_get_model (GTK_TREE_VIEW (gtk_builder_get_object (builder, "shortcut_treeview")));
+  /* FIXME: get current selection and keep it after refreshing */
+
+  /* Clear previous models */
+  gtk_list_store_clear (GTK_LIST_STORE (section_model));
+  gtk_list_store_clear (GTK_LIST_STORE (shortcut_model));
+
+  /* Load WM keybindings */
+  wm_keybindings = wm_common_get_current_keybindings ();
+
+  dir = g_dir_open (GNOMECC_KEYBINDINGS_DIR, 0, NULL);
+  if (!dir)
+      return;
+
+  for (name = g_dir_read_name (dir) ; name ; name = g_dir_read_name (dir))
+    {
+      if (g_str_has_suffix (name, ".xml"))
+        {
+	  gchar *path;
+
+	  path = g_build_filename (GNOMECC_KEYBINDINGS_DIR, name, NULL);
+	  append_sections_from_file (builder, path, wm_keybindings);
+
+	  g_free (path);
+	}
+    }
+
+  g_dir_close (dir);
+  g_strfreev (wm_keybindings);
+
+  /* Load custom keybindings */
+  append_sections_from_gconf (builder, GCONF_BINDING_DIR);
+}
+
+static void
+accel_set_func (GtkTreeViewColumn *tree_column,
+                GtkCellRenderer   *cell,
+                GtkTreeModel      *model,
+                GtkTreeIter       *iter,
+                gpointer           data)
+{
+  KeyEntry *key_entry;
+
+  gtk_tree_model_get (model, iter,
+                      KEYENTRY_COLUMN, &key_entry,
+                      -1);
+
+  if (key_entry == NULL)
+    g_object_set (cell,
+		  "visible", FALSE,
+		  NULL);
+  else if (! key_entry->editable)
+    g_object_set (cell,
+		  "visible", TRUE,
+		  "editable", FALSE,
+		  "accel_key", key_entry->keyval,
+		  "accel_mask", key_entry->mask,
+		  "keycode", key_entry->keycode,
+		  "style", PANGO_STYLE_ITALIC,
+		  NULL);
+  else
+    g_object_set (cell,
+		  "visible", TRUE,
+		  "editable", TRUE,
+		  "accel_key", key_entry->keyval,
+		  "accel_mask", key_entry->mask,
+		  "keycode", key_entry->keycode,
+		  "style", PANGO_STYLE_NORMAL,
+		  NULL);
+}
+
+static void
+description_set_func (GtkTreeViewColumn *tree_column,
+                      GtkCellRenderer   *cell,
+                      GtkTreeModel      *model,
+                      GtkTreeIter       *iter,
+                      gpointer           data)
+{
+  KeyEntry *key_entry;
+
+  gtk_tree_model_get (model, iter,
+                      KEYENTRY_COLUMN, &key_entry,
+                      -1);
+
+  if (key_entry != NULL)
+    g_object_set (cell,
+		  "editable", FALSE,
+		  "text", key_entry->description != NULL ?
+			  key_entry->description : _("<Unknown Action>"),
+		  NULL);
+  else
+    g_object_set (cell,
+		  "editable", FALSE, NULL);
 }
 
 static void
 setup_dialog (CcPanel *panel, GtkBuilder *builder)
 {
+  GConfClient *client;
+  GtkCellRenderer *renderer;
+  GtkTreeViewColumn *column;
+  GtkWidget *widget;
+  GtkTreeView *treeview;
+  GtkTreeSelection *selection;
+  GSList *allowed_keys;
+  CcShell *shell;
+  GtkListStore *model;
+
+  /* Setup the section treeview */
+  treeview = GTK_TREE_VIEW (gtk_builder_get_object (builder, "section_treeview"));
+
+  renderer = gtk_cell_renderer_text_new ();
+  column = gtk_tree_view_column_new_with_attributes (_("Section"),
+						     renderer,
+						     "text", DESCRIPTION_COLUMN,
+						     NULL);
+  gtk_tree_view_append_column (treeview, column);
+
+  model = gtk_list_store_new (1, G_TYPE_STRING);
+  gtk_tree_view_set_model (treeview, GTK_TREE_MODEL (model));
+  
+  /* Setup the shortcut treeview */
+  treeview = GTK_TREE_VIEW (gtk_builder_get_object (builder,
+                                                    "shortcut_treeview"));
+
+  client = gconf_client_get_default ();
+
+  /* g_signal_connect (treeview, "button_press_event", */
+  /* 		    G_CALLBACK (start_editing_cb), builder); */
+  /* g_signal_connect (treeview, "row-activated", */
+  /* 		    G_CALLBACK (start_editing_kb_cb), NULL); */
+
+  renderer = gtk_cell_renderer_text_new ();
+
+  /* g_signal_connect (renderer, "edited", */
+  /*                   G_CALLBACK (description_edited_callback), */
+  /*                   treeview); */
+
+  column = gtk_tree_view_column_new_with_attributes (_("Action"),
+						     renderer,
+						     "text", DESCRIPTION_COLUMN,
+						     NULL);
+  gtk_tree_view_column_set_cell_data_func (column, renderer, description_set_func, NULL, NULL);
+  gtk_tree_view_column_set_resizable (column, FALSE);
+
+  gtk_tree_view_append_column (treeview, column);
+  gtk_tree_view_column_set_sort_column_id (column, DESCRIPTION_COLUMN);
+
+  renderer = (GtkCellRenderer *) g_object_new (EGG_TYPE_CELL_RENDERER_KEYS,
+					       "accel_mode", EGG_CELL_RENDERER_KEYS_MODE_X,
+					       NULL);
+
+  /* g_signal_connect (renderer, "accel_edited", */
+  /*                   G_CALLBACK (accel_edited_callback), */
+  /*                   treeview); */
+
+  /* g_signal_connect (renderer, "accel_cleared", */
+  /*                   G_CALLBACK (accel_cleared_callback), */
+  /*                   treeview); */
+
+  column = gtk_tree_view_column_new_with_attributes (_("Shortcut"), renderer, NULL);
+  gtk_tree_view_column_set_cell_data_func (column, renderer, accel_set_func, NULL, NULL);
+  gtk_tree_view_column_set_resizable (column, FALSE);
+
+  gtk_tree_view_append_column (treeview, column);
+  gtk_tree_view_column_set_sort_column_id (column, KEYENTRY_COLUMN);
+
+  gconf_client_add_dir (client, GCONF_BINDING_DIR, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+  gconf_client_add_dir (client, "/apps/metacity/general", GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+  /* gconf_client_notify_add (client, */
+  /* 			   "/apps/metacity/general/num_workspaces", */
+  /* 			   (GConfClientNotifyFunc) key_entry_controlling_key_changed, */
+  /* 			   builder, NULL, NULL); */
+
+  /* set up the dialog */
+  shell = cc_panel_get_shell (CC_PANEL (panel));
+  widget = cc_shell_get_toplevel (shell);
+
+  /* maybe_block_accels_id = g_signal_connect (widget, "key_press_event", */
+  /* 					    G_CALLBACK (maybe_block_accels), NULL); */
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+  /* g_signal_connect (selection, "changed", */
+  /*                   G_CALLBACK (selection_changed), */
+  /* 		    WID (builder, "remove-button")); */
+
+  allowed_keys = gconf_client_get_list (client,
+                                        GCONF_BINDING_DIR "/allowed_keys",
+                                        GCONF_VALUE_STRING,
+                                        NULL);
+  if (allowed_keys != NULL)
+    {
+      g_slist_foreach (allowed_keys, (GFunc)g_free, NULL);
+      g_slist_free (allowed_keys);
+      gtk_widget_set_sensitive (WID (builder, "add-button"),
+                                FALSE);
+    }
+
+  g_object_unref (client);
+
+  /* setup the custom shortcut dialog */
+  custom_shortcut_dialog = WID (builder,
+				"custom-shortcut-dialog");
+  custom_shortcut_name_entry = WID (builder,
+				    "custom-shortcut-name-entry");
+  custom_shortcut_command_entry = WID (builder,
+				       "custom-shortcut-command-entry");
+  /* g_signal_connect (WID (builder, "add-button"), */
+  /*                   "clicked", G_CALLBACK (add_button_clicked), builder); */
+  /* g_signal_connect (WID (builder, "remove-button"), */
+  /*                   "clicked", G_CALLBACK (remove_button_clicked), builder); */
+
+  gtk_dialog_set_default_response (GTK_DIALOG (custom_shortcut_dialog),
+				   GTK_RESPONSE_OK);
+
+  gtk_window_set_transient_for (GTK_WINDOW (custom_shortcut_dialog),
+                                GTK_WINDOW (widget));
 }
 
 void
 keyboard_shortcuts_init (CcPanel *panel, GtkBuilder *builder)
 {
-  kb_sections = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, free_key_list);
+  kb_sections = g_hash_table_new_full (g_str_hash, g_str_equal,
+				       g_free, (GDestroyNotify) free_key_array);
   setup_dialog (panel, builder);
+  reload_sections (builder);
 }
 
 void



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