[Xfce4-commits] <xfce4-panel:master> Panel: Work with a unique id for each panel.

Nick Schermer noreply at xfce.org
Thu Dec 29 17:36:02 CET 2011


Updating branch refs/heads/master
         to 1473206aa9771e110d5b5e80fd8f1b370f986638 (commit)
       from e835c3b533d7c15e4329d83a767660b6079f147d (commit)

commit 1473206aa9771e110d5b5e80fd8f1b370f986638
Author: Nick Schermer <nick at xfce.org>
Date:   Thu Dec 29 16:16:15 2011 +0100

    Panel: Work with a unique id for each panel.
    
    Give each panel a unique id that does not change over
    its lifetime. This should prevent most of the problems
    where panel configuration is lost or strange resets when
    a panel is removed from the preferences dialog.

 panel/main.c                         |    2 +-
 panel/panel-application.c            |  331 +++++++++++++++++++---------------
 panel/panel-application.h            |   10 +-
 panel/panel-dbus-service.c           |   12 +-
 panel/panel-dialogs.c                |   76 ++++++--
 panel/panel-item-dialog.c            |   14 ++
 panel/panel-item-dialog.h            |    8 +-
 panel/panel-preferences-dialog.c     |  156 +++++++++++------
 panel/panel-preferences-dialog.glade |    4 +-
 panel/panel-preferences-dialog.h     |    8 +-
 panel/panel-window.c                 |   34 ++++-
 panel/panel-window.h                 |    5 +-
 12 files changed, 421 insertions(+), 239 deletions(-)

diff --git a/panel/main.c b/panel/main.c
index 15600c8..a70a04f 100644
--- a/panel/main.c
+++ b/panel/main.c
@@ -355,7 +355,7 @@ main (gint argc, gchar **argv)
 
   /* open dialog if we started from launch_panel */
   if (opt_preferences >= 0)
-    panel_preferences_dialog_show (panel_application_get_nth_window (application, opt_preferences));
+    panel_preferences_dialog_show_from_id (opt_preferences);
 
   gtk_main ();
 
diff --git a/panel/panel-application.c b/panel/panel-application.c
index 3b304a0..143f489 100644
--- a/panel/panel-application.c
+++ b/panel/panel-application.c
@@ -302,11 +302,9 @@ panel_application_xfconf_window_bindings (PanelApplication *application,
   };
 
   panel_return_if_fail (XFCONF_IS_CHANNEL (application->xfconf));
-  panel_return_if_fail (g_slist_index (application->windows, window) > -1);
 
   /* create the property base */
-  property_base = g_strdup_printf ("/panels/panel-%d",
-      g_slist_index (application->windows, window));
+  property_base = g_strdup_printf ("/panels/panel-%d", panel_window_get_id (window));
 
   /* bind all the properties */
   panel_properties_bind (application->xfconf, G_OBJECT (window),
@@ -335,74 +333,109 @@ panel_application_load_real (PanelApplication *application)
   gchar        *output_name;
   gint          screen_num;
   GdkDisplay   *display;
+  GValue        val = { 0, };
+  GPtrArray    *panels;
+  gint          panel_id;
 
   panel_return_if_fail (PANEL_IS_APPLICATION (application));
   panel_return_if_fail (XFCONF_IS_CHANNEL (application->xfconf));
 
   display = gdk_display_get_default ();
 
-  /* walk all the panel in the configuration */
-  n_panels = xfconf_channel_get_uint (application->xfconf, "/panels", 0);
-  for (i = 0; i < n_panels; i++)
+  if (xfconf_channel_get_property (application->xfconf, "/panels", &val)
+      && (G_VALUE_HOLDS_UINT (&val)
+          || G_VALUE_HOLDS (&val, PANEL_PROPERTIES_TYPE_VALUE_ARRAY)))
     {
-      screen = NULL;
-
-      /* start the panel directly on the correct screen */
-      g_snprintf (buf, sizeof (buf), "/panels/panel-%u/output-name", i);
-      output_name = xfconf_channel_get_string (application->xfconf, buf, NULL);
-      if (output_name != NULL
-          && strncmp (output_name, "screen-", 7) == 0
-          && sscanf (output_name, "screen-%d", &screen_num) == 1)
+      if (G_VALUE_HOLDS_UINT (&val))
         {
-          if (screen_num < gdk_display_get_n_screens (display))
-            screen = gdk_display_get_screen (display, screen_num);
+          n_panels = g_value_get_uint (&val);
+          panels = NULL;
+        }
+      else
+        {
+          panels = g_value_get_boxed (&val);
+          n_panels = panels->len;
         }
-      g_free (output_name);
 
-      /* create a new window */
-      window = panel_application_new_window (application, screen, FALSE);
+      /* walk all the panel in the configuration */
+      for (i = 0; i < n_panels; i++)
+        {
+          screen = NULL;
 
-      /* walk all the plugins on the panel */
-      g_snprintf (buf, sizeof (buf), "/panels/panel-%u/plugin-ids", i);
-      array = xfconf_channel_get_arrayv (application->xfconf, buf);
-      if (array == NULL)
-        continue;
+          /* get the panel id */
+          if (panels != NULL)
+            {
+              /* get the id from the array */
+              value = g_ptr_array_index (panels, i);
+              panel_assert (value != NULL);
+              panel_id = g_value_get_int (value);
+            }
+          else
+            {
+              /* use the list position if /panels is an uint */
+              panel_id = i;
+            }
 
-      for (j = 0; j < array->len; j++)
-        {
-          /* get the plugin id */
-          value = g_ptr_array_index (array, j);
-          panel_assert (value != NULL);
-          unique_id = g_value_get_int (value);
-
-          /* get the plugin name */
-          g_snprintf (buf, sizeof (buf), "/plugins/plugin-%d", unique_id);
-          name = xfconf_channel_get_string (application->xfconf, buf, NULL);
-
-          /* append the plugin to the panel */
-          if (unique_id < 1 || name == NULL
-              || !panel_application_plugin_insert (application, window,
-                                                   name, unique_id, NULL, -1))
+          /* start the panel directly on the correct screen */
+          g_snprintf (buf, sizeof (buf), "/panels/panel-%d/output-name", panel_id);
+          output_name = xfconf_channel_get_string (application->xfconf, buf, NULL);
+          if (output_name != NULL
+              && strncmp (output_name, "screen-", 7) == 0
+              && sscanf (output_name, "screen-%d", &screen_num) == 1)
             {
-              /* plugin could not be loaded, remove it from the channel */
-              g_snprintf (buf, sizeof (buf), "/panels/plugin-%d", unique_id);
-              if (xfconf_channel_has_property (application->xfconf, buf))
-                xfconf_channel_reset_property (application->xfconf, buf, TRUE);
-
-              /* show warnings */
-              g_message ("Plugin \"%s-%d\" was not found and has been "
-                         "removed from the configuration", name, unique_id);
+              if (screen_num < gdk_display_get_n_screens (display))
+                screen = gdk_display_get_screen (display, screen_num);
             }
+          g_free (output_name);
 
-          g_free (name);
+          /* create a new window */
+          window = panel_application_new_window (application, screen, panel_id, FALSE);
+
+          /* walk all the plugins on the panel */
+          g_snprintf (buf, sizeof (buf), "/panels/panel-%d/plugin-ids", panel_id);
+          array = xfconf_channel_get_arrayv (application->xfconf, buf);
+          if (array == NULL)
+            continue;
+
+          for (j = 0; j < array->len; j++)
+            {
+              /* get the plugin id */
+              value = g_ptr_array_index (array, j);
+              panel_assert (value != NULL);
+              unique_id = g_value_get_int (value);
+
+              /* get the plugin name */
+              g_snprintf (buf, sizeof (buf), "/plugins/plugin-%d", unique_id);
+              name = xfconf_channel_get_string (application->xfconf, buf, NULL);
+
+              /* append the plugin to the panel */
+              if (unique_id < 1 || name == NULL
+                  || !panel_application_plugin_insert (application, window,
+                                                       name, unique_id, NULL, -1))
+                {
+                  /* plugin could not be loaded, remove it from the channel */
+                  g_snprintf (buf, sizeof (buf), "/panels/plugin-%d", unique_id);
+                  if (xfconf_channel_has_property (application->xfconf, buf))
+                    xfconf_channel_reset_property (application->xfconf, buf, TRUE);
+
+                  /* show warnings */
+                  g_message ("Plugin \"%s-%d\" was not found and has been "
+                             "removed from the configuration", name, unique_id);
+                }
+
+              g_free (name);
+            }
+
+          xfconf_array_free (array);
         }
 
-      xfconf_array_free (array);
+      /* free xfconf array or uint */
+      g_value_unset (&val);
     }
 
   /* create empty window if everything else failed */
   if (G_UNLIKELY (application->windows == NULL))
-    panel_application_new_window (application, NULL, TRUE);
+    panel_application_new_window (application, NULL, -1, TRUE);
 }
 
 
@@ -791,58 +824,37 @@ static void
 panel_application_window_destroyed (GtkWidget        *window,
                                     PanelApplication *application)
 {
-  guint      n;
   gchar     *property;
-  GSList    *li, *lnext;
-  gboolean   passed_destroyed_window = FALSE;
   GtkWidget *itembar;
+  gint       panel_id;
 
   panel_return_if_fail (PANEL_IS_WINDOW (window));
   panel_return_if_fail (PANEL_IS_APPLICATION (application));
   panel_return_if_fail (g_slist_find (application->windows, window) != NULL);
 
-  /* leave if the application is locked */
-  if (panel_application_get_locked (application))
+  /* leave if the application or window is locked */
+  if (panel_application_get_locked (application)
+      || panel_window_get_locked (PANEL_WINDOW (window)))
     return;
 
-  /* we need to update the bindings of all the panels... */
-  for (li = application->windows, n = 0; li != NULL; li = lnext, n++)
-    {
-      lnext = li->next;
+  panel_id = panel_window_get_id (PANEL_WINDOW (window));
+  panel_debug (PANEL_DEBUG_APPLICATION,
+               "removing configuration and plugins of panel %d",
+               panel_id);
 
-      /* TODO, this might go wrong when only 1 window is locked */
-      if (panel_window_get_locked (li->data))
-        continue;
+  /* remove from the internal list */
+  application->windows = g_slist_remove (application->windows, window);
 
-      if (passed_destroyed_window)
-        {
-          /* save this panel again at it's new position */
-          panel_properties_unbind (G_OBJECT (li->data));
-          panel_application_xfconf_window_bindings (application,
-                                                    PANEL_WINDOW (li->data),
-                                                    TRUE);
-        }
-      else if (li->data == window)
-        {
-          /* disconnect bindings from this panel */
-          panel_properties_unbind (G_OBJECT (window));
-
-          /* remove all the plugins from the itembar */
-          itembar = gtk_bin_get_child (GTK_BIN (window));
-          gtk_container_foreach (GTK_CONTAINER (itembar),
-              panel_application_plugin_remove, NULL);
-
-          /* remove from the internal list */
-          application->windows = g_slist_delete_link (application->windows, li);
+  /* disconnect bindings from this panel */
+  panel_properties_unbind (G_OBJECT (window));
 
-          /* keep updating the bindings for the remaining windows */
-          passed_destroyed_window = TRUE;
-        }
-    }
+  /* remove all the plugins from the itembar */
+  itembar = gtk_bin_get_child (GTK_BIN (window));
+  gtk_container_foreach (GTK_CONTAINER (itembar),
+      panel_application_plugin_remove, NULL);
 
-  /* remove the last property from the channel */
-  property = g_strdup_printf ("/panels/panel-%u", n - 1);
-  panel_assert (n - 1 == g_slist_length (application->windows));
+  /* remove the panel settings */
+  property = g_strdup_printf ("/panels/panel-%d", panel_id);
   xfconf_channel_reset_property (application->xfconf, property, TRUE);
   g_free (property);
 
@@ -1169,6 +1181,21 @@ panel_application_drag_leave (GtkWidget        *window,
 
 
 
+static gboolean
+panel_application_window_id_exists (PanelApplication *application,
+                                    gint              id)
+{
+  GSList *li;
+
+  for (li = application->windows; li != NULL; li = li->next)
+    if (panel_window_get_id (li->data) == id)
+      return TRUE;
+
+  return FALSE;
+}
+
+
+
 PanelApplication *
 panel_application_get (void)
 {
@@ -1251,19 +1278,30 @@ panel_application_save (PanelApplication *application,
   XfconfChannel           *channel = application->xfconf;
   GPtrArray               *array;
   GValue                  *value;
+  GPtrArray               *panels;
+  gint                     panel_id;
 
   panel_return_if_fail (PANEL_IS_APPLICATION (application));
   panel_return_if_fail (XFCONF_IS_CHANNEL (channel));
 
+  panels = g_ptr_array_new ();
+
   for (li = application->windows, i = 0; li != NULL; li = li->next, i++)
     {
+      /* store the panel id */
+      value = g_new0 (GValue, 1);
+      panel_id = panel_window_get_id (li->data);
+      g_value_init (value, G_TYPE_INT);
+      g_value_set_int (value, panel_id);
+      g_ptr_array_add (panels, value);
+
       /* skip this window if it is locked */
       if (panel_window_get_locked (li->data))
         continue;
 
       panel_debug (PANEL_DEBUG_APPLICATION,
-                   "saving /panels/panel-%u, save-plugins=%s",
-                   i, PANEL_DEBUG_BOOL (save_plugin_providers));
+                   "saving /panels/panel-%d, save-plugins=%s",
+                   panel_id, PANEL_DEBUG_BOOL (save_plugin_providers));
 
       /* get the itembar children */
       itembar = gtk_bin_get_child (GTK_BIN (li->data));
@@ -1272,7 +1310,7 @@ panel_application_save (PanelApplication *application,
       /* only cleanup and continue if there are no children */
       if (G_UNLIKELY (children == NULL))
         {
-          g_snprintf (buf, sizeof (buf), "/panels/panel-%u/plugin-ids", i);
+          g_snprintf (buf, sizeof (buf), "/panels/panel-%d/plugin-ids", panel_id);
           if (xfconf_channel_has_property (channel, buf))
             xfconf_channel_reset_property (channel, buf, FALSE);
           continue;
@@ -1303,16 +1341,21 @@ panel_application_save (PanelApplication *application,
         }
 
       /* store the plugins for this panel */
-      g_snprintf (buf, sizeof (buf), "/panels/panel-%u/plugin-ids", i);
+      g_snprintf (buf, sizeof (buf), "/panels/panel-%d/plugin-ids", panel_id);
       xfconf_channel_set_arrayv (channel, buf, array);
 
       g_list_free (children);
       xfconf_array_free (array);
     }
 
-  /* store the number of panels */
+  /* store the panel ids */
   if (!xfconf_channel_is_property_locked (channel, "/panels"))
-    xfconf_channel_set_uint (channel, "/panels", i);
+    {
+      if (!xfconf_channel_set_arrayv (channel, "/panels", panels))
+        g_warning ("Failed to store the number of panels");
+    }
+
+  xfconf_array_free (panels);
 }
 
 
@@ -1360,14 +1403,12 @@ panel_application_add_new_item (PanelApplication  *application,
                                 const gchar       *plugin_name,
                                 gchar            **arguments)
 {
-  gint         nth = 0;
-  GSList      *li;
-  gboolean     active;
-  PanelWindow *window;
+  PanelWindow *window = NULL;
+  gint         panel_id;
 
   panel_return_if_fail (PANEL_IS_APPLICATION (application));
   panel_return_if_fail (plugin_name != NULL);
-  panel_return_if_fail (g_slist_length (application->windows) > 0);
+  panel_return_if_fail (application->windows != NULL);
 
   /* leave if the config is locked */
   if (panel_application_get_locked (application))
@@ -1375,30 +1416,34 @@ panel_application_add_new_item (PanelApplication  *application,
 
   if (panel_module_factory_has_module (application->factory, plugin_name))
     {
-      /* find a suitable window if there are 2 or more windows */
+      /* find a suitable panel if there are 2 or more panel */
       if (LIST_HAS_TWO_OR_MORE_ENTRIES (application->windows))
         {
-          /* try to find an avtive panel */
-          for (li = application->windows, nth = 0; li != NULL; li = li->next, nth++)
+          /* ask the user to select a panel */
+          panel_id = panel_dialogs_choose_panel (application);
+          if (panel_id == -1)
             {
-              g_object_get (G_OBJECT (li->data), "active", &active, NULL);
-              if (active)
-                break;
+              /* cancel was clicked */
+              return;
+            }
+          else
+            {
+              /* get panel from the id */
+              window = panel_application_get_window (application, panel_id);
             }
-
-          /* no active panel found, ask user to select a panel, leave when
-           * the cancel button is pressed */
-          if (li == NULL
-              && (nth = panel_dialogs_choose_panel (application)) == -1)
-            return;
+        }
+      else
+        {
+          /* get the first (and only) window */
+          window = g_slist_nth_data (application->windows, 0);
         }
 
-      /* add the plugin to the end of the choosen window */
-      window = g_slist_nth_data (application->windows, nth);
-      if (!panel_window_get_locked (window))
+      if (window != NULL && !panel_window_get_locked (window))
         {
+          /* insert plugin at the end of the panel */
           panel_application_plugin_insert (application, window,
-                                           plugin_name, -1, arguments, -1);
+                                           plugin_name, -1,
+                                           arguments, -1);
         }
     }
   else
@@ -1413,6 +1458,7 @@ panel_application_add_new_item (PanelApplication  *application,
 PanelWindow *
 panel_application_new_window (PanelApplication *application,
                               GdkScreen        *screen,
+                              gint              panel_id,
                               gboolean          new_window)
 {
   GtkWidget          *window;
@@ -1422,13 +1468,23 @@ panel_application_new_window (PanelApplication *application,
   static const gchar *props[] = { "mode", "size", "nrows" };
   guint               i;
   gchar              *position;
+  static gint         unqiue_id_counter = 1;
 
   panel_return_val_if_fail (PANEL_IS_APPLICATION (application), NULL);
   panel_return_val_if_fail (screen == NULL || GDK_IS_SCREEN (screen), NULL);
   panel_return_val_if_fail (XFCONF_IS_CHANNEL (application->xfconf), NULL);
+  panel_return_val_if_fail (new_window || !panel_application_window_id_exists (application, panel_id), NULL);
+
+  if (new_window)
+    {
+      /* get a new unique id */
+      panel_id = unqiue_id_counter;
+      while (panel_application_window_id_exists (application, panel_id))
+        panel_id = ++unqiue_id_counter;
+    }
 
   /* create panel window */
-  window = panel_window_new (screen);
+  window = panel_window_new (screen, panel_id);
 
   /* monitor window destruction */
   g_signal_connect (G_OBJECT (window), "destroy",
@@ -1437,12 +1493,10 @@ panel_application_new_window (PanelApplication *application,
   /* add the window to internal list */
   application->windows = g_slist_append (application->windows, window);
 
-  /* flush the window properties */
   if (new_window)
     {
-      /* remove the xfconf properties */
-      idx = g_slist_index (application->windows, window);
-      property = g_strdup_printf ("/panels/panel-%d", idx);
+      /* remove the old xfconf properties to be sure */
+      property = g_strdup_printf ("/panels/panel-%d", panel_id);
       xfconf_channel_reset_property (application->xfconf, property, TRUE);
       g_free (property);
     }
@@ -1480,7 +1534,7 @@ panel_application_new_window (PanelApplication *application,
 
       /* create a position so not all panels overlap */
       idx = g_slist_index (application->windows, window);
-      position = g_strdup_printf ("p=0;x=100;y=%d", 100 + (idx * 48 * 2));
+      position = g_strdup_printf ("p=0;x=100;y=%d", 100 + (idx * 48) + 10);
       g_object_set (G_OBJECT (window), "position", position, NULL);
       g_free (position);
     }
@@ -1490,35 +1544,28 @@ panel_application_new_window (PanelApplication *application,
 
 
 
-guint
-panel_application_get_n_windows (PanelApplication *application)
+GSList *
+panel_application_get_windows (PanelApplication *application)
 {
-  panel_return_val_if_fail (PANEL_IS_APPLICATION (application), 0);
-
-  return g_slist_length (application->windows);
+  panel_return_val_if_fail (PANEL_IS_APPLICATION (application), NULL);
+  return application->windows;
 }
 
 
 
-gint
-panel_application_get_window_index (PanelApplication *application,
-                                    PanelWindow      *window)
+PanelWindow *
+panel_application_get_window (PanelApplication  *application,
+                              gint               panel_id)
 {
-  panel_return_val_if_fail (PANEL_IS_APPLICATION (application), 0);
-  panel_return_val_if_fail (PANEL_IS_WINDOW (window), 0);
-
-  return g_slist_index (application->windows, window);
-}
-
+  GSList *li;
 
+  panel_return_val_if_fail (PANEL_IS_APPLICATION (application), NULL);
 
-PanelWindow *
-panel_application_get_nth_window (PanelApplication *application,
-                                  guint             idx)
-{
-  panel_return_val_if_fail (PANEL_IS_APPLICATION (application), 0);
+  for (li = application->windows; li != NULL; li = li->next)
+    if (panel_window_get_id (li->data) == panel_id)
+      return li->data;
 
-  return g_slist_nth_data (application->windows, idx);
+  return NULL;
 }
 
 
diff --git a/panel/panel-application.h b/panel/panel-application.h
index 5073821..ee1d719 100644
--- a/panel/panel-application.h
+++ b/panel/panel-application.h
@@ -55,15 +55,13 @@ void              panel_application_add_new_item      (PanelApplication  *applic
 
 PanelWindow      *panel_application_new_window        (PanelApplication  *application,
                                                        GdkScreen         *screen,
+                                                       gint               id,
                                                        gboolean           new_window);
 
-guint             panel_application_get_n_windows     (PanelApplication  *application);
+GSList           *panel_application_get_windows       (PanelApplication  *application);
 
-gint              panel_application_get_window_index  (PanelApplication  *application,
-                                                       PanelWindow       *window);
-
-PanelWindow      *panel_application_get_nth_window    (PanelApplication  *application,
-                                                       guint              idx);
+PanelWindow      *panel_application_get_window        (PanelApplication  *application,
+                                                       gint               panel_id);
 
 void              panel_application_window_select     (PanelApplication  *application,
                                                        PanelWindow       *window);
diff --git a/panel/panel-dbus-service.c b/panel/panel-dbus-service.c
index 42382b6..955e466 100644
--- a/panel/panel-dbus-service.c
+++ b/panel/panel-dbus-service.c
@@ -192,15 +192,11 @@ panel_dbus_service_display_preferences_dialog (PanelDBusService  *service,
                                                guint              active,
                                                GError           **error)
 {
-  PanelApplication *application;
-
   panel_return_val_if_fail (PANEL_IS_DBUS_SERVICE (service), FALSE);
   panel_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
   /* show the preferences dialog */
-  application = panel_application_get ();
-  panel_preferences_dialog_show (panel_application_get_nth_window (application, active));
-  g_object_unref (G_OBJECT (application));
+  panel_preferences_dialog_show_from_id (active);
 
   return TRUE;
 }
@@ -212,15 +208,11 @@ panel_dbus_service_display_items_dialog (PanelDBusService  *service,
                                          guint              active,
                                          GError           **error)
 {
-  PanelApplication *application;
-
   panel_return_val_if_fail (PANEL_IS_DBUS_SERVICE (service), FALSE);
   panel_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
   /* show the items dialog */
-  application = panel_application_get ();
-  panel_item_dialog_show (panel_application_get_nth_window (application, active));
-  g_object_unref (G_OBJECT (application));
+  panel_preferences_dialog_show_from_id (active);
 
   return TRUE;
 }
diff --git a/panel/panel-dialogs.c b/panel/panel-dialogs.c
index d7fd918..f268ba6 100644
--- a/panel/panel-dialogs.c
+++ b/panel/panel-dialogs.c
@@ -89,19 +89,45 @@ panel_dialogs_show_about (void)
 
 
 
+enum
+{
+  CHOOSER_COLUMN_ID,
+  CHOOSER_COLUMN_TEXT,
+  N_CHOOSER_COLUMNS
+};
+
+
+
+static gint
+panel_dialogs_choose_panel_combo_get_id (GtkComboBox *combo)
+{
+  gint          panel_id = -1;
+  GtkTreeIter   iter;
+  GtkTreeModel *model;
+
+  if (gtk_combo_box_get_active_iter (combo, &iter))
+    {
+      model = gtk_combo_box_get_model (combo);
+      gtk_tree_model_get (model, &iter, CHOOSER_COLUMN_ID, &panel_id, -1);
+    }
+
+  return panel_id;
+}
+
+
+
 static void
 panel_dialogs_choose_panel_combo_changed (GtkComboBox      *combo,
                                           PanelApplication *application)
 {
-  gint idx;
+  gint panel_id;
 
   panel_return_if_fail (PANEL_IS_APPLICATION (application));
   panel_return_if_fail (GTK_IS_COMBO_BOX (combo));
 
-  /* select active panel */
-  idx = gtk_combo_box_get_active (combo);
+  panel_id = panel_dialogs_choose_panel_combo_get_id (combo);
   panel_application_window_select (application,
-      panel_application_get_nth_window (application, idx));
+      panel_application_get_window (application, panel_id));
 }
 
 
@@ -109,13 +135,16 @@ panel_dialogs_choose_panel_combo_changed (GtkComboBox      *combo,
 gint
 panel_dialogs_choose_panel (PanelApplication *application)
 {
-  GtkWidget *dialog;
-  GtkWidget *vbox;
-  GtkWidget *label;
-  GtkWidget *combo;
-  guint      i;
-  gint       response = -1;
-  gchar     *name;
+  GtkWidget       *dialog;
+  GtkWidget       *vbox;
+  GtkWidget       *label;
+  GtkWidget       *combo;
+  gchar           *name;
+  GtkListStore    *store;
+  GtkCellRenderer *renderer;
+  GSList          *windows, *li;
+  gint             i;
+  gint             panel_id;
 
   panel_return_val_if_fail (PANEL_IS_APPLICATION (application), -1);
 
@@ -138,15 +167,26 @@ panel_dialogs_choose_panel (PanelApplication *application)
   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
   gtk_widget_show (label);
 
-  combo = gtk_combo_box_new_text ();
+  store = gtk_list_store_new (N_CHOOSER_COLUMNS, G_TYPE_INT, G_TYPE_STRING);
+  combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store));
   gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0);
   gtk_widget_show (combo);
+  g_object_unref (G_OBJECT (store));
+
+  renderer = gtk_cell_renderer_text_new ();
+  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
+  gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), renderer,
+                                  "text", CHOOSER_COLUMN_TEXT, NULL);
 
   /* insert the panels */
-  for (i = 0; i < panel_application_get_n_windows (application); i++)
+  windows = panel_application_get_windows (application);
+  for (li = windows, i = 0; li != NULL; li = li->next, i++)
     {
-      name = g_strdup_printf (_("Panel %d"), i + 1);
-      gtk_combo_box_append_text (GTK_COMBO_BOX (combo), name);
+      panel_id = panel_window_get_id (li->data);
+      name = g_strdup_printf (_("Panel %d"), panel_id);
+      gtk_list_store_insert_with_values (store, NULL, i,
+                                         CHOOSER_COLUMN_ID, panel_id,
+                                         CHOOSER_COLUMN_TEXT, name, -1);
       g_free (name);
     }
 
@@ -157,13 +197,15 @@ panel_dialogs_choose_panel (PanelApplication *application)
 
   /* run the dialog */
   if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
-    response = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
+    panel_id = panel_dialogs_choose_panel_combo_get_id (GTK_COMBO_BOX (combo));
+  else
+    panel_id = -1;
   gtk_widget_destroy (dialog);
 
   /* unset panel selections */
   panel_application_window_select (application, NULL);
 
-  return response;
+  return panel_id;
 }
 
 
diff --git a/panel/panel-item-dialog.c b/panel/panel-item-dialog.c
index 06a5d2e..e9a6fc7 100644
--- a/panel/panel-item-dialog.c
+++ b/panel/panel-item-dialog.c
@@ -814,6 +814,20 @@ panel_item_dialog_show (PanelWindow *window)
 
 
 
+void
+panel_item_dialog_show_from_id (gint panel_id)
+{
+  PanelApplication *application;
+  PanelWindow      *window;
+
+  application = panel_application_get ();
+  window = panel_application_get_window (application, panel_id);
+  panel_item_dialog_show (window);
+  g_object_unref (G_OBJECT (application));
+}
+
+
+
 gboolean
 panel_item_dialog_visible (void)
 {
diff --git a/panel/panel-item-dialog.h b/panel/panel-item-dialog.h
index d0a276a..aee1e2a 100644
--- a/panel/panel-item-dialog.h
+++ b/panel/panel-item-dialog.h
@@ -33,11 +33,13 @@ typedef struct _PanelItemDialog      PanelItemDialog;
 #define PANEL_IS_ITEM_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANEL_TYPE_ITEM_DIALOG))
 #define PANEL_ITEM_DIALOG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), PANEL_TYPE_ITEM_DIALOG, PanelItemDialogClass))
 
-GType      panel_item_dialog_get_type (void) G_GNUC_CONST;
+GType      panel_item_dialog_get_type     (void) G_GNUC_CONST;
 
-void       panel_item_dialog_show     (PanelWindow *window);
+void       panel_item_dialog_show         (PanelWindow *active);
 
-gboolean   panel_item_dialog_visible  (void);
+void       panel_item_dialog_show_from_id (gint         panel_id);
+
+gboolean   panel_item_dialog_visible      (void);
 
 G_END_DECLS
 
diff --git a/panel/panel-preferences-dialog.c b/panel/panel-preferences-dialog.c
index 6e89eca..f05c603 100644
--- a/panel/panel-preferences-dialog.c
+++ b/panel/panel-preferences-dialog.c
@@ -61,7 +61,8 @@ static void                     panel_preferences_dialog_bg_image_file_set
 static void                     panel_preferences_dialog_bg_image_notified      (PanelPreferencesDialog *dialog);
 static void                     panel_preferences_dialog_panel_combobox_changed (GtkComboBox            *combobox,
                                                                                  PanelPreferencesDialog *dialog);
-static void                     panel_preferences_dialog_panel_combobox_rebuild (PanelPreferencesDialog *dialog);
+static gboolean                 panel_preferences_dialog_panel_combobox_rebuild (PanelPreferencesDialog *dialog,
+                                                                                 gint                    panel_id);
 static void                     panel_preferences_dialog_panel_add              (GtkWidget              *widget,
                                                                                  PanelPreferencesDialog *dialog);
 static void                     panel_preferences_dialog_panel_remove           (GtkWidget              *widget,
@@ -270,9 +271,6 @@ panel_preferences_dialog_init (PanelPreferencesDialog *dialog)
                         G_CALLBACK (panel_preferences_dialog_output_changed),
                         dialog);
 
-  /* rebuild the panel combobox */
-  panel_preferences_dialog_panel_combobox_rebuild (dialog);
-
   /* show the dialog */
   gtk_widget_show (GTK_WIDGET (window));
 }
@@ -673,9 +671,9 @@ static void
 panel_preferences_dialog_panel_sensitive (PanelPreferencesDialog *dialog)
 {
 
-  GObject   *object;
-  gboolean   locked = TRUE;
-  gint       n_windows;
+  GObject  *object;
+  gboolean  locked = TRUE;
+  GSList   *windows;
 
   panel_return_if_fail (PANEL_IS_PREFERENCES_DIALOG (dialog));
 
@@ -684,8 +682,9 @@ panel_preferences_dialog_panel_sensitive (PanelPreferencesDialog *dialog)
 
   object = gtk_builder_get_object (GTK_BUILDER (dialog), "panel-remove");
   panel_return_if_fail (GTK_IS_WIDGET (object));
-  n_windows = panel_application_get_n_windows (dialog->application);
-  gtk_widget_set_sensitive (GTK_WIDGET (object), !locked && n_windows > 1);
+  windows = panel_application_get_windows (dialog->application);
+  gtk_widget_set_sensitive (GTK_WIDGET (object),
+      !locked && g_slist_length (windows) > 1);
 
   object = gtk_builder_get_object (GTK_BUILDER (dialog), "panel-add");
   panel_return_if_fail (GTK_IS_WIDGET (object));
@@ -707,8 +706,10 @@ static void
 panel_preferences_dialog_panel_combobox_changed (GtkComboBox            *combobox,
                                                  PanelPreferencesDialog *dialog)
 {
-  gint       nth;
-  GtkWidget *itembar;
+  gint          panel_id;
+  GtkWidget    *itembar;
+  GtkTreeModel *model;
+  GtkTreeIter   iter;
 
   panel_return_if_fail (GTK_IS_COMBO_BOX (combobox));
   panel_return_if_fail (PANEL_IS_PREFERENCES_DIALOG (dialog));
@@ -724,8 +725,18 @@ panel_preferences_dialog_panel_combobox_changed (GtkComboBox            *combobo
   panel_preferences_dialog_bindings_unbind (dialog);
 
   /* set the selected window */
-  nth = gtk_combo_box_get_active (combobox);
-  dialog->active = panel_application_get_nth_window (dialog->application, nth);
+  if (gtk_combo_box_get_active_iter (combobox, &iter))
+    {
+      model = gtk_combo_box_get_model (combobox);
+      gtk_tree_model_get (model, &iter, 0, &panel_id, -1);
+
+      dialog->active = panel_application_get_window (dialog->application, panel_id);
+    }
+  else
+    {
+      dialog->active = NULL;
+    }
+
   panel_application_window_select (dialog->application, dialog->active);
 
   if (G_LIKELY (dialog->active != NULL))
@@ -748,18 +759,23 @@ panel_preferences_dialog_panel_combobox_changed (GtkComboBox            *combobo
 
 
 
-static void
-panel_preferences_dialog_panel_combobox_rebuild (PanelPreferencesDialog *dialog)
+static gboolean
+panel_preferences_dialog_panel_combobox_rebuild (PanelPreferencesDialog *dialog,
+                                                 gint                    panel_id)
 {
-  GObject *store, *combo;
-  gint     n, n_items;
-  gchar   *name;
+  GObject     *store, *combo;
+  gint         i;
+  GSList      *windows, *li;
+  gchar       *name;
+  gint         id;
+  GtkTreeIter  iter;
+  gboolean     selected = FALSE;
 
   /* get the combo box and model */
   store = gtk_builder_get_object (GTK_BUILDER (dialog), "panel-store");
-  panel_return_if_fail (GTK_IS_LIST_STORE (store));
+  panel_return_val_if_fail (GTK_IS_LIST_STORE (store), FALSE);
   combo = gtk_builder_get_object (GTK_BUILDER (dialog), "panel-combobox");
-  panel_return_if_fail (GTK_IS_COMBO_BOX (combo));
+  panel_return_val_if_fail (GTK_IS_COMBO_BOX (combo), FALSE);
 
   /* block signal */
   g_signal_handlers_block_by_func (combo,
@@ -769,20 +785,34 @@ panel_preferences_dialog_panel_combobox_rebuild (PanelPreferencesDialog *dialog)
   gtk_list_store_clear (GTK_LIST_STORE (store));
 
   /* add new names */
-  n_items = panel_application_get_n_windows (dialog->application);
-  for (n = 0; n < n_items; n++)
+  windows = panel_application_get_windows (dialog->application);
+  for (li = windows, i = 0; li != NULL; li = li->next, i++)
     {
       /* I18N: panel combo box in the preferences dialog */
-      name = g_strdup_printf (_("Panel %d"), n + 1);
-      gtk_list_store_insert_with_values (GTK_LIST_STORE (store), NULL, n, 0, name, -1);
+      id = panel_window_get_id (li->data);
+      name = g_strdup_printf (_("Panel %d"), id);
+      gtk_list_store_insert_with_values (GTK_LIST_STORE (store), &iter, i,
+                                         0, id, 1, name, -1);
       g_free (name);
+
+      if (id == panel_id)
+        {
+          /* select panel id */
+          gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combo), &iter);
+          selected = TRUE;
+        }
     }
 
   /* unblock signal */
   g_signal_handlers_unblock_by_func (combo,
       panel_preferences_dialog_panel_combobox_changed, dialog);
 
+  if (selected)
+    panel_preferences_dialog_panel_combobox_changed (GTK_COMBO_BOX (combo), dialog);
+
   panel_preferences_dialog_panel_sensitive (dialog);
+
+  return selected;
 }
 
 
@@ -791,28 +821,22 @@ static void
 panel_preferences_dialog_panel_add (GtkWidget              *widget,
                                     PanelPreferencesDialog *dialog)
 {
-  gint         active;
   PanelWindow *window;
-  GObject     *object;
+  gint         panel_id;
 
   /* create new window */
   window = panel_application_new_window (dialog->application,
-      gtk_widget_get_screen (widget), TRUE);
+      gtk_widget_get_screen (widget), -1, TRUE);
 
   /* block autohide */
   panel_window_freeze_autohide (window);
 
-  /* rebuild the selector */
-  panel_preferences_dialog_panel_combobox_rebuild (dialog);
-
   /* show window */
   gtk_widget_show (GTK_WIDGET (window));
 
-  /* select new panel (new window is appended) */
-  object = gtk_builder_get_object (GTK_BUILDER (dialog), "panel-combobox");
-  panel_return_if_fail (GTK_IS_WIDGET (object));
-  active = panel_application_get_n_windows (dialog->application) - 1;
-  gtk_combo_box_set_active (GTK_COMBO_BOX (object), active);
+  /* rebuild the selector */
+  panel_id = panel_window_get_id (window);
+  panel_preferences_dialog_panel_combobox_rebuild (dialog, panel_id);
 }
 
 
@@ -821,36 +845,41 @@ static void
 panel_preferences_dialog_panel_remove (GtkWidget              *widget,
                                        PanelPreferencesDialog *dialog)
 {
-  gint       nth;
+  gint       idx;
   GObject   *combo;
   GtkWidget *toplevel;
+  GSList    *windows;
+  gint       n_windows;
 
   /* leave if the window is locked */
   if (panel_window_get_locked (dialog->active))
     return;
 
-  /* get active panel */
-  nth = panel_application_get_window_index (dialog->application, dialog->active);
-
   toplevel = gtk_widget_get_toplevel (widget);
   if (xfce_dialog_confirm (GTK_WINDOW (toplevel), GTK_STOCK_REMOVE, NULL,
           _("The panel and plugin configurations will be permanently removed"),
-          _("Are you sure you want to remove panel %d?"), nth + 1))
+          _("Are you sure you want to remove panel %d?"),
+          panel_window_get_id (dialog->active)))
     {
       /* release the bindings */
       panel_preferences_dialog_bindings_unbind (dialog);
 
+      /* get position of the panel */
+      windows = panel_application_get_windows (dialog->application);
+      idx = g_slist_index (windows, dialog->active);
+      n_windows = g_slist_length (windows) - 2;
+
       /* destroy the panel */
       gtk_widget_destroy (GTK_WIDGET (dialog->active));
       dialog->active = NULL;
 
       /* rebuild the selector */
-      panel_preferences_dialog_panel_combobox_rebuild (dialog);
+      panel_preferences_dialog_panel_combobox_rebuild (dialog, -1);
 
-      /* select new active window */
+      /* select window after this window */
       combo = gtk_builder_get_object (GTK_BUILDER (dialog), "panel-combobox");
       panel_return_if_fail (GTK_IS_WIDGET (combo));
-      gtk_combo_box_set_active (GTK_COMBO_BOX (combo), MAX (0, nth - 1));
+      gtk_combo_box_set_active (GTK_COMBO_BOX (combo), CLAMP (idx, 0, n_windows));
     }
 }
 
@@ -1248,9 +1277,10 @@ panel_preferences_dialog_item_selection_changed (GtkTreeSelection       *selecti
 void
 panel_preferences_dialog_show (PanelWindow *active)
 {
-  gint       idx = 0;
-  GObject   *window, *combo;
-  GdkScreen *screen;
+  gint         panel_id = 0;
+  GObject     *window, *combo;
+  GdkScreen   *screen;
+  GSList      *windows;
 
   panel_return_if_fail (active == NULL || PANEL_IS_WINDOW (active));
 
@@ -1258,21 +1288,23 @@ panel_preferences_dialog_show (PanelWindow *active)
   if (panel_dialogs_kiosk_warning ())
     return;
 
-  if (G_LIKELY (dialog_singleton == NULL))
+  if (dialog_singleton == NULL)
     {
       /* create new dialog singleton */
       dialog_singleton = g_object_new (PANEL_TYPE_PREFERENCES_DIALOG, NULL);
       g_object_add_weak_pointer (G_OBJECT (dialog_singleton), (gpointer) &dialog_singleton);
     }
 
-  /* get the active window index */
-  if (G_LIKELY (active))
-    idx = panel_application_get_window_index (dialog_singleton->application, active);
-  else
-    active = panel_application_get_nth_window (dialog_singleton->application, idx);
+  if (active == NULL)
+    {
+      /* select first window */
+      windows = panel_application_get_windows (dialog_singleton->application);
+      if (windows != NULL)
+        active = g_slist_nth_data (windows, 0);
+    }
 
   /* get the active screen */
-  if (active != NULL)
+  if (G_LIKELY (active != NULL))
     screen = gtk_widget_get_screen (GTK_WIDGET (active));
   else
     screen = gdk_screen_get_default ();
@@ -1286,7 +1318,23 @@ panel_preferences_dialog_show (PanelWindow *active)
   /* select the active window in the dialog */
   combo = gtk_builder_get_object (GTK_BUILDER (dialog_singleton), "panel-combobox");
   panel_return_if_fail (GTK_IS_WIDGET (combo));
-  gtk_combo_box_set_active (GTK_COMBO_BOX (combo), idx);
+  panel_id = panel_window_get_id (active);
+  if (!panel_preferences_dialog_panel_combobox_rebuild (dialog_singleton, panel_id))
+    gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
+}
+
+
+
+void
+panel_preferences_dialog_show_from_id (gint panel_id)
+{
+  PanelApplication *application;
+  PanelWindow      *window;
+
+  application = panel_application_get ();
+  window = panel_application_get_window (application, panel_id);
+  panel_preferences_dialog_show (window);
+  g_object_unref (G_OBJECT (application));
 }
 
 
diff --git a/panel/panel-preferences-dialog.glade b/panel/panel-preferences-dialog.glade
index 92d7dc8..062cbed 100644
--- a/panel/panel-preferences-dialog.glade
+++ b/panel/panel-preferences-dialog.glade
@@ -22,6 +22,8 @@
   </object>
   <object class="GtkListStore" id="panel-store">
     <columns>
+      <!-- column-name id -->
+      <column type="gint"/>
       <!-- column-name title -->
       <column type="gchararray"/>
     </columns>
@@ -132,7 +134,7 @@
                     <child>
                       <object class="GtkCellRendererText" id="cellrenderertext2"/>
                       <attributes>
-                        <attribute name="text">0</attribute>
+                        <attribute name="text">1</attribute>
                       </attributes>
                     </child>
                   </object>
diff --git a/panel/panel-preferences-dialog.h b/panel/panel-preferences-dialog.h
index c60ac5f..89d73f3 100644
--- a/panel/panel-preferences-dialog.h
+++ b/panel/panel-preferences-dialog.h
@@ -35,11 +35,13 @@ typedef struct _PanelPreferencesDialog      PanelPreferencesDialog;
 #define PANEL_IS_PREFERENCES_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANEL_TYPE_PREFERENCES_DIALOG))
 #define PANEL_PREFERENCES_DIALOG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), PANEL_TYPE_PREFERENCES_DIALOG, PanelPreferencesDialogClass))
 
-GType      panel_preferences_dialog_get_type (void) G_GNUC_CONST;
+GType      panel_preferences_dialog_get_type     (void) G_GNUC_CONST;
 
-void       panel_preferences_dialog_show     (PanelWindow *active);
+void       panel_preferences_dialog_show         (PanelWindow *active);
 
-gboolean   panel_preferences_dialog_visible  (void);
+void       panel_preferences_dialog_show_from_id (gint         panel_id);
+
+gboolean   panel_preferences_dialog_visible      (void);
 
 G_END_DECLS
 
diff --git a/panel/panel-window.c b/panel/panel-window.c
index f2e3ac0..d84189a 100644
--- a/panel/panel-window.c
+++ b/panel/panel-window.c
@@ -146,6 +146,7 @@ static void         panel_window_plugin_set_screen_position (GtkWidget        *w
 enum
 {
   PROP_0,
+  PROP_ID,
   PROP_MODE,
   PROP_SIZE,
   PROP_NROWS,
@@ -245,6 +246,9 @@ struct _PanelWindow
 {
   PanelBaseWindow      __parent__;
 
+  /* unique id of this panel */
+  gint                 id;
+
   /* whether the user is allowed to make
    * changes to this window */
   guint                locked : 1;
@@ -342,6 +346,13 @@ panel_window_class_init (PanelWindowClass *klass)
   gtkwidget_class->realize = panel_window_realize;
 
   g_object_class_install_property (gobject_class,
+                                   PROP_ID,
+                                   g_param_spec_int ("id", NULL, NULL,
+                                                     0, G_MAXINT, 0,
+                                                     EXO_PARAM_READWRITE
+                                                     | G_PARAM_CONSTRUCT_ONLY));
+
+  g_object_class_install_property (gobject_class,
                                    PROP_MODE,
                                    g_param_spec_enum ("mode", NULL, NULL,
                                                       XFCE_TYPE_PANEL_PLUGIN_MODE,
@@ -445,6 +456,7 @@ panel_window_class_init (PanelWindowClass *klass)
 static void
 panel_window_init (PanelWindow *window)
 {
+  window->id = -1;
   window->locked = TRUE;
   window->screen = NULL;
   window->struts_edge = STRUTS_EDGE_NONE;
@@ -496,6 +508,10 @@ panel_window_get_property (GObject    *object,
 
   switch (prop_id)
     {
+    case PROP_ID:
+      g_value_set_int (value, window->id);
+      break;
+
     case PROP_MODE:
       g_value_set_enum (value, window->mode);
       break;
@@ -569,6 +585,10 @@ panel_window_set_property (GObject      *object,
 
   switch (prop_id)
     {
+    case PROP_ID:
+      window->id = g_value_get_int (value);
+      break;
+
     case PROP_MODE:
       val_mode = g_value_get_enum (value);
       if (window->mode != val_mode)
@@ -2531,12 +2551,14 @@ panel_window_plugin_set_screen_position (GtkWidget *widget,
 
 
 GtkWidget *
-panel_window_new (GdkScreen *screen)
+panel_window_new (GdkScreen *screen,
+                  gint       id)
 {
   if (screen == NULL)
     screen = gdk_screen_get_default ();
 
   return g_object_new (PANEL_TYPE_WINDOW,
+                       "id", id,
                        "type", GTK_WINDOW_TOPLEVEL,
                        "decorated", FALSE,
                        "resizable", FALSE,
@@ -2550,6 +2572,16 @@ panel_window_new (GdkScreen *screen)
 
 
 
+gint
+panel_window_get_id (PanelWindow *window)
+{
+  panel_return_val_if_fail (PANEL_IS_WINDOW (window), -1);
+  panel_return_val_if_fail (window->id > -1, -1);
+  return window->id;
+}
+
+
+
 gboolean
 panel_window_has_position (PanelWindow *window)
 {
diff --git a/panel/panel-window.h b/panel/panel-window.h
index b745c48..e31d2b6 100644
--- a/panel/panel-window.h
+++ b/panel/panel-window.h
@@ -35,7 +35,10 @@ typedef struct _PanelWindow      PanelWindow;
 
 GType      panel_window_get_type         (void) G_GNUC_CONST;
 
-GtkWidget *panel_window_new              (GdkScreen   *screen) G_GNUC_MALLOC;
+GtkWidget *panel_window_new              (GdkScreen   *screen,
+                                          gint         id) G_GNUC_MALLOC;
+
+gint       panel_window_get_id           (PanelWindow *window);
 
 gboolean   panel_window_has_position     (PanelWindow *window);
 


More information about the Xfce4-commits mailing list