[gnome-disk-utility/udisks2-port] Factor tree code into a GduTreeModel class



commit fb6ace316e49dc212dac1e48508315564ea0a950
Author: David Zeuthen <davidz redhat com>
Date:   Tue Mar 8 13:12:47 2011 -0500

    Factor tree code into a GduTreeModel class
    
    Signed-off-by: David Zeuthen <davidz redhat com>

 src/palimpsest/Makefile.am      |    1 +
 src/palimpsest/gduapplication.c |  265 ++-------------------
 src/palimpsest/gdutreemodel.c   |  498 +++++++++++++++++++++++++++++++++++++++
 src/palimpsest/gdutreemodel.h   |   53 ++++
 src/palimpsest/gdutypes.h       |    3 +
 5 files changed, 573 insertions(+), 247 deletions(-)
---
diff --git a/src/palimpsest/Makefile.am b/src/palimpsest/Makefile.am
index f00db04..443a384 100644
--- a/src/palimpsest/Makefile.am
+++ b/src/palimpsest/Makefile.am
@@ -7,6 +7,7 @@ palimpsest_SOURCES = 					\
 				main.c			\
 	gdu.h						\
 	gduapplication.h	gduapplication.c	\
+	gdutreemodel.h		gdutreemodel.c		\
 	gdutypes.h					\
 	$(NULL)
 
diff --git a/src/palimpsest/gduapplication.c b/src/palimpsest/gduapplication.c
index 6b65c91..13e054d 100644
--- a/src/palimpsest/gduapplication.c
+++ b/src/palimpsest/gduapplication.c
@@ -24,6 +24,7 @@
 #include <glib/gi18n.h>
 
 #include "gduapplication.h"
+#include "gdutreemodel.h"
 
 struct _GduApplication
 {
@@ -33,13 +34,9 @@ struct _GduApplication
   GtkWindow *window;
   gboolean running_from_source_tree;
 
-  GDBusProxyManager *proxy_manager;
+  UDisksClient *client;
 
-  GtkTreeStore *lun_tree_store;
-
-  GtkTreeIter das_iter;
-  GtkTreeIter remote_iter;
-  GtkTreeIter other_iter;
+  GduTreeModel *model;
 };
 
 typedef struct
@@ -47,17 +44,6 @@ typedef struct
   GtkApplicationClass parent_class;
 } GduApplicationClass;
 
-enum
-{
-  LUN_TREE_COLUMN_SORT_KEY,
-  LUN_TREE_COLUMN_IS_HEADING,
-  LUN_TREE_COLUMN_HEADING_TEXT,
-  LUN_TREE_COLUMN_ICON,
-  LUN_TREE_COLUMN_NAME,
-  LUN_TREE_COLUMN_OBJECT_PROXY,
-  LUN_TREE_N_COLUMNS
-};
-
 G_DEFINE_TYPE (GduApplication, gdu_application, GTK_TYPE_APPLICATION);
 
 static void
@@ -73,9 +59,7 @@ gdu_application_finalize (GObject *object)
   if (app->builder != NULL)
     goto out;
 
-  g_object_unref (app->lun_tree_store);
-  g_object_unref (app->proxy_manager);
-  g_object_unref (app->builder);
+  g_object_unref (app->model);
 
  out:
   G_OBJECT_CLASS (gdu_application_parent_class)->finalize (object);
@@ -113,157 +97,13 @@ dont_select_headings (GtkTreeSelection *selection,
                            path);
   gtk_tree_model_get (model,
                       &iter,
-                      LUN_TREE_COLUMN_IS_HEADING,
+                      GDU_TREE_MODEL_COLUMN_IS_HEADING,
                       &is_heading,
                       -1);
 
   return !is_heading;
 }
 
-typedef struct
-{
-  GDBusObjectProxy *object;
-  GtkTreeIter iter;
-  gboolean found;
-} FindIterData;
-
-static gboolean
-find_iter_for_object_proxy_cb (GtkTreeModel  *model,
-                               GtkTreePath   *path,
-                               GtkTreeIter   *iter,
-                               gpointer       user_data)
-{
-  FindIterData *data = user_data;
-  GDBusObjectProxy *iter_object;
-
-  iter_object = NULL;
-
-  gtk_tree_model_get (model,
-                      iter,
-                      LUN_TREE_COLUMN_OBJECT_PROXY, &iter_object,
-                      -1);
-  if (iter_object == NULL)
-    goto out;
-
-  if (iter_object == data->object)
-    {
-      data->iter = *iter;
-      data->found = TRUE;
-      goto out;
-    }
-
- out:
-  if (iter_object != NULL)
-    g_object_unref (iter_object);
-  return data->found;
-}
-
-static gboolean
-find_iter_for_object_proxy (GduApplication   *app,
-                            GDBusObjectProxy *object,
-                            GtkTreeIter      *out_iter)
-{
-  FindIterData data;
-
-  memset (&data, 0, sizeof (data));
-  data.object = object;
-  data.found = FALSE;
-  gtk_tree_model_foreach (GTK_TREE_MODEL (app->lun_tree_store),
-                          find_iter_for_object_proxy_cb,
-                          &data);
-  if (data.found)
-    {
-      if (out_iter != NULL)
-        *out_iter = data.iter;
-    }
-
-  return data.found;
-}
-
-static void
-add_lun (GduApplication   *app,
-         GDBusObjectProxy *object)
-{
-  UDisksLun *lun;
-  gchar *name;
-  gchar *sort_key;
-  GIcon *icon;
-  const gchar *model;
-  const gchar *vendor;
-
-  g_debug ("add %s", g_dbus_object_proxy_get_object_path (object));
-
-  lun = UDISKS_PEEK_LUN (object);
-
-  model = udisks_lun_get_model (lun);
-  vendor = udisks_lun_get_vendor (lun);
-  if (strlen (vendor) == 0)
-    name = g_strdup (model);
-  else if (strlen (model) == 0)
-    name = g_strdup (vendor);
-  else
-    name = g_strconcat (vendor, " ", model, NULL);
-
-  icon = g_themed_icon_new ("drive-harddisk"); /* for now */
-  sort_key = g_strdup (name); /* for now */
-
-  gtk_tree_store_insert_with_values (app->lun_tree_store,
-                                     NULL,
-                                     &app->das_iter,
-                                     0,
-                                     LUN_TREE_COLUMN_ICON, icon,
-                                     LUN_TREE_COLUMN_NAME, name,
-                                     LUN_TREE_COLUMN_SORT_KEY, sort_key,
-                                     LUN_TREE_COLUMN_OBJECT_PROXY, object,
-                                     -1);
-  g_object_unref (icon);
-  g_free (sort_key);
-  g_free (name);
-}
-
-static void
-remove_lun (GduApplication   *app,
-            GDBusObjectProxy *object)
-{
-  GtkTreeIter iter;
-
-  g_debug ("remove %s", g_dbus_object_proxy_get_object_path (object));
-
-  if (!find_iter_for_object_proxy (app,
-                                   object,
-                                   &iter))
-    {
-      g_warning ("Unable to find iter for %s",
-                 g_dbus_object_proxy_get_object_path (object));
-      goto out;
-    }
-
-  gtk_tree_store_remove (app->lun_tree_store, &iter);
-
- out:
-  ;
-}
-
-static void
-on_object_proxy_added (GDBusProxyManager *manager,
-                       GDBusObjectProxy  *object,
-                       gpointer           user_data)
-{
-  GduApplication *app = GDU_APPLICATION (user_data);
-  if (UDISKS_PEEK_LUN (object) != NULL)
-    add_lun (app, object);
-}
-
-static void
-on_object_proxy_removed (GDBusProxyManager *manager,
-                         GDBusObjectProxy  *object,
-                         gpointer           user_data)
-{
-  GduApplication *app = GDU_APPLICATION (user_data);
-  if (UDISKS_PEEK_LUN (object) != NULL)
-    remove_lun (app, object);
-}
-
 static void
 on_row_inserted (GtkTreeModel *tree_model,
                  GtkTreePath  *path,
@@ -285,23 +125,16 @@ gdu_application_activate (GApplication *_app)
   GtkCellRenderer *renderer;
   GtkTreeSelection *selection;
   const gchar *path;
-  gchar *s;
-  GList *objects;
-  GList *l;
 
   if (app->builder != NULL)
     return;
 
   error = NULL;
-  app->proxy_manager = udisks_proxy_manager_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
-                                                              G_DBUS_PROXY_MANAGER_FLAGS_NONE,
-                                                              "org.freedesktop.UDisks2",
-                                                              "/org/freedesktop/UDisks2",
-                                                              NULL, /* GCancellable* */
-                                                              &error);
-  if (app->proxy_manager == NULL)
+  app->client = udisks_client_new_sync (NULL, /* GCancellable* */
+                                        &error);
+  if (app->client == NULL)
     {
-      g_error ("Error getting objects from udisks: %s", error->message);
+      g_error ("Error getting udisks client: %s", error->message);
       g_error_free (error);
     }
 
@@ -331,58 +164,17 @@ gdu_application_activate (GApplication *_app)
   context = gtk_widget_get_style_context (gdu_application_get_widget (app, "lunlist-add-remove-toolbar"));
   gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);
 
-  app->lun_tree_store = gtk_tree_store_new (6,
-                                            G_TYPE_STRING,
-                                            G_TYPE_BOOLEAN,
-                                            G_TYPE_STRING,
-                                            G_TYPE_ICON,
-                                            G_TYPE_STRING,
-                                            G_TYPE_DBUS_OBJECT_PROXY);
-  G_STATIC_ASSERT (6 == LUN_TREE_N_COLUMNS);
+  app->model = gdu_tree_model_new (app->client);
 
   tree_view = GTK_TREE_VIEW (gdu_application_get_widget (app, "lunlist-treeview"));
-  gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (app->lun_tree_store));
-  gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (app->lun_tree_store),
-                                        LUN_TREE_COLUMN_SORT_KEY,
+  gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (app->model));
+  gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (app->model),
+                                        GDU_TREE_MODEL_COLUMN_SORT_KEY,
                                         GTK_SORT_ASCENDING);
 
   selection = gtk_tree_view_get_selection (tree_view);
   gtk_tree_selection_set_select_function (selection, dont_select_headings, NULL, NULL);
 
-  s = g_strdup_printf ("<small><span foreground=\"#555555\">%s</span></small>",
-                       _("Direct-Attached Storage"));
-  gtk_tree_store_insert_with_values (app->lun_tree_store,
-                                     &app->das_iter,
-                                     NULL,
-                                     0,
-                                     LUN_TREE_COLUMN_IS_HEADING, TRUE,
-                                     LUN_TREE_COLUMN_HEADING_TEXT, s,
-                                     LUN_TREE_COLUMN_SORT_KEY, "0_das",
-                                     -1);
-  g_free (s);
-  s = g_strdup_printf ("<small><span foreground=\"#555555\">%s</span></small>",
-                       _("Remote Storage"));
-  gtk_tree_store_insert_with_values (app->lun_tree_store,
-                                     &app->remote_iter,
-                                     NULL,
-                                     0,
-                                     LUN_TREE_COLUMN_IS_HEADING, TRUE,
-                                     LUN_TREE_COLUMN_HEADING_TEXT, s,
-                                     LUN_TREE_COLUMN_SORT_KEY, "1_remote",
-                                     -1);
-  g_free (s);
-  s = g_strdup_printf ("<small><span foreground=\"#555555\">%s</span></small>",
-                       _("Other Devices"));
-  gtk_tree_store_insert_with_values (app->lun_tree_store,
-                                     &app->other_iter,
-                                     NULL,
-                                     0,
-                                     LUN_TREE_COLUMN_IS_HEADING, TRUE,
-                                     LUN_TREE_COLUMN_HEADING_TEXT, s,
-                                     LUN_TREE_COLUMN_SORT_KEY, "2_other",
-                                     -1);
-  g_free (s);
-
   column = gtk_tree_view_column_new ();
   gtk_tree_view_append_column (tree_view, column);
 
@@ -390,8 +182,8 @@ gdu_application_activate (GApplication *_app)
   gtk_tree_view_column_pack_start (column, renderer, FALSE);
   gtk_tree_view_column_set_attributes (column,
                                        renderer,
-                                       "markup", LUN_TREE_COLUMN_HEADING_TEXT,
-                                       "visible", LUN_TREE_COLUMN_IS_HEADING,
+                                       "markup", GDU_TREE_MODEL_COLUMN_HEADING_TEXT,
+                                       "visible", GDU_TREE_MODEL_COLUMN_IS_HEADING,
                                        NULL);
 
   renderer = gtk_cell_renderer_pixbuf_new ();
@@ -401,37 +193,17 @@ gdu_application_activate (GApplication *_app)
   gtk_tree_view_column_pack_start (column, renderer, FALSE);
   gtk_tree_view_column_set_attributes (column,
                                        renderer,
-                                       "gicon", LUN_TREE_COLUMN_ICON,
+                                       "gicon", GDU_TREE_MODEL_COLUMN_ICON,
                                        NULL);
   renderer = gtk_cell_renderer_text_new ();
   gtk_tree_view_column_pack_start (column, renderer, FALSE);
   gtk_tree_view_column_set_attributes (column,
                                        renderer,
-                                       "text", LUN_TREE_COLUMN_NAME,
+                                       "text", GDU_TREE_MODEL_COLUMN_NAME,
                                        NULL);
 
-  /* coldplug */
-  objects = g_dbus_proxy_manager_get_all (app->proxy_manager);
-  for (l = objects; l != NULL; l = l->next)
-    {
-      GDBusObjectProxy *object = G_DBUS_OBJECT_PROXY (l->data);
-      on_object_proxy_added (app->proxy_manager, object, app);
-    }
-  g_list_foreach (objects, (GFunc) g_object_unref, NULL);
-  g_list_free (objects);
-
-  g_signal_connect (app->proxy_manager,
-                    "object-proxy-added",
-                    G_CALLBACK (on_object_proxy_added),
-                    app);
-
-  g_signal_connect (app->proxy_manager,
-                    "object-proxy-removed",
-                    G_CALLBACK (on_object_proxy_removed),
-                    app);
-
   /* expand on insertion - hmm, I wonder if there's an easier way to do this */
-  g_signal_connect (app->lun_tree_store,
+  g_signal_connect (app->model,
                     "row-inserted",
                     G_CALLBACK (on_row_inserted),
                     app);
@@ -470,4 +242,3 @@ gdu_application_get_widget (GduApplication *app,
   g_return_val_if_fail (name != NULL, NULL);
   return GTK_WIDGET (gtk_builder_get_object (app->builder, name));
 }
-
diff --git a/src/palimpsest/gdutreemodel.c b/src/palimpsest/gdutreemodel.c
new file mode 100644
index 0000000..1672708
--- /dev/null
+++ b/src/palimpsest/gdutreemodel.c
@@ -0,0 +1,498 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2008-2011 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#include "config.h"
+#include <glib/gi18n.h>
+
+#include "gdutreemodel.h"
+
+struct _GduTreeModel
+{
+  GtkTreeStore parent_instance;
+
+  UDisksClient *client;
+
+  GList *current_luns;
+  GtkTreeIter direct_attached_storage_iter;
+};
+
+typedef struct
+{
+  GtkTreeStoreClass parent_class;
+} GduTreeModelClass;
+
+enum
+{
+  PROP_0,
+  PROP_CLIENT
+};
+
+G_DEFINE_TYPE (GduTreeModel, gdu_tree_model, GTK_TYPE_TREE_STORE);
+
+static void coldplug (GduTreeModel *model);
+static void on_object_proxy_added (GDBusProxyManager   *manager,
+                                   GDBusObjectProxy    *object_proxy,
+                                   gpointer             user_data);
+
+static void on_object_proxy_removed (GDBusProxyManager   *manager,
+                                     GDBusObjectProxy    *object_proxy,
+                                     gpointer             user_data);
+
+static void
+gdu_tree_model_finalize (GObject *object)
+{
+  GduTreeModel *model = GDU_TREE_MODEL (object);
+  GDBusProxyManager *proxy_manager;
+
+  proxy_manager = udisks_client_get_proxy_manager (model->client);
+  g_signal_handlers_disconnect_by_func (proxy_manager,
+                                        G_CALLBACK (on_object_proxy_added),
+                                        model);
+  g_signal_handlers_disconnect_by_func (proxy_manager,
+                                        G_CALLBACK (on_object_proxy_removed),
+                                        model);
+
+  g_list_foreach (model->current_luns, (GFunc) g_object_unref, NULL);
+  g_list_free (model->current_luns);
+  g_object_unref (model->client);
+
+  G_OBJECT_CLASS (gdu_tree_model_parent_class)->finalize (object);
+}
+
+static void
+gdu_tree_model_init (GduTreeModel *model)
+{
+}
+
+static void
+gdu_tree_model_get_property (GObject    *object,
+                             guint       prop_id,
+                             GValue     *value,
+                             GParamSpec *pspec)
+{
+  GduTreeModel *model = GDU_TREE_MODEL (object);
+
+  switch (prop_id)
+    {
+    case PROP_CLIENT:
+      g_value_set_object (value, gdu_tree_model_get_client (model));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gdu_tree_model_set_property (GObject      *object,
+                             guint         prop_id,
+                             const GValue *value,
+                             GParamSpec   *pspec)
+{
+  GduTreeModel *model = GDU_TREE_MODEL (object);
+
+  switch (prop_id)
+    {
+    case PROP_CLIENT:
+      model->client = g_value_dup_object (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+typedef struct
+{
+  GDBusObjectProxy *object;
+  GtkTreeIter iter;
+  gboolean found;
+} FindIterData;
+
+static gboolean
+find_iter_for_object_proxy_cb (GtkTreeModel  *model,
+                               GtkTreePath   *path,
+                               GtkTreeIter   *iter,
+                               gpointer       user_data)
+{
+  FindIterData *data = user_data;
+  GDBusObjectProxy *iter_object;
+
+  iter_object = NULL;
+
+  gtk_tree_model_get (model,
+                      iter,
+                      GDU_TREE_MODEL_COLUMN_OBJECT_PROXY, &iter_object,
+                      -1);
+  if (iter_object == NULL)
+    goto out;
+
+  if (iter_object == data->object)
+    {
+      data->iter = *iter;
+      data->found = TRUE;
+      goto out;
+    }
+
+ out:
+  if (iter_object != NULL)
+    g_object_unref (iter_object);
+  return data->found;
+}
+
+static gboolean
+find_iter_for_object_proxy (GduTreeModel     *model,
+                            GDBusObjectProxy *object,
+                            GtkTreeIter      *out_iter)
+{
+  FindIterData data;
+
+  memset (&data, 0, sizeof (data));
+  data.object = object;
+  data.found = FALSE;
+  gtk_tree_model_foreach (GTK_TREE_MODEL (model),
+                          find_iter_for_object_proxy_cb,
+                          &data);
+  if (data.found)
+    {
+      if (out_iter != NULL)
+        *out_iter = data.iter;
+    }
+
+  return data.found;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+diff_sorted_lists (GList         *list1,
+                   GList         *list2,
+                   GCompareFunc   compare,
+                   GList        **added,
+                   GList        **removed)
+{
+  gint order;
+
+  *added = *removed = NULL;
+
+  while (list1 != NULL &&
+         list2 != NULL)
+    {
+      order = (*compare) (list1->data, list2->data);
+      if (order < 0)
+        {
+          *removed = g_list_prepend (*removed, list1->data);
+          list1 = list1->next;
+        }
+      else if (order > 0)
+        {
+          *added = g_list_prepend (*added, list2->data);
+          list2 = list2->next;
+        }
+      else
+        { /* same item */
+          list1 = list1->next;
+          list2 = list2->next;
+        }
+    }
+
+  while (list1 != NULL)
+    {
+      *removed = g_list_prepend (*removed, list1->data);
+      list1 = list1->next;
+    }
+  while (list2 != NULL)
+    {
+      *added = g_list_prepend (*added, list2->data);
+      list2 = list2->next;
+    }
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gint
+_g_dbus_object_proxy_compare (GDBusObjectProxy *a,
+                              GDBusObjectProxy *b)
+{
+  return g_strcmp0 (g_dbus_object_proxy_get_object_path (a),
+                    g_dbus_object_proxy_get_object_path (b));
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+gdu_tree_model_constructed (GObject *object)
+{
+  GduTreeModel *model = GDU_TREE_MODEL (object);
+  GType types[GDU_TREE_MODEL_N_COLUMNS];
+  GDBusProxyManager *proxy_manager;
+  gchar *s;
+
+  types[0] = G_TYPE_STRING;
+  types[1] = G_TYPE_BOOLEAN;
+  types[2] = G_TYPE_STRING;
+  types[3] = G_TYPE_ICON;
+  types[4] = G_TYPE_STRING;
+  types[5] = G_TYPE_DBUS_OBJECT_PROXY;
+  G_STATIC_ASSERT (6 == GDU_TREE_MODEL_N_COLUMNS);
+  gtk_tree_store_set_column_types (GTK_TREE_STORE (model),
+                                   GDU_TREE_MODEL_N_COLUMNS,
+                                   types);
+
+  g_assert (gtk_tree_model_get_flags (GTK_TREE_MODEL (model)) & GTK_TREE_MODEL_ITERS_PERSIST);
+
+  s = g_strdup_printf ("<small><span foreground=\"#555555\">%s</span></small>",
+                       _("Direct-Attached Storage"));
+  gtk_tree_store_insert_with_values (GTK_TREE_STORE (model),
+                                     &model->direct_attached_storage_iter,
+                                     NULL, /* GtkTreeIter *parent */
+                                     0,
+                                     GDU_TREE_MODEL_COLUMN_IS_HEADING, TRUE,
+                                     GDU_TREE_MODEL_COLUMN_HEADING_TEXT, s,
+                                     GDU_TREE_MODEL_COLUMN_SORT_KEY, "00_direct_attached_storage",
+                                     -1);
+  g_free (s);
+
+  proxy_manager = udisks_client_get_proxy_manager (model->client);
+  g_signal_connect (proxy_manager,
+                    "object-proxy-added",
+                    G_CALLBACK (on_object_proxy_added),
+                    model);
+  g_signal_connect (proxy_manager,
+                    "object-proxy-removed",
+                    G_CALLBACK (on_object_proxy_removed),
+                    model);
+  coldplug (model);
+
+  if (G_OBJECT_CLASS (gdu_tree_model_parent_class)->constructed != NULL)
+    G_OBJECT_CLASS (gdu_tree_model_parent_class)->constructed (object);
+}
+
+static void
+gdu_tree_model_class_init (GduTreeModelClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize     = gdu_tree_model_finalize;
+  gobject_class->constructed  = gdu_tree_model_constructed;
+  gobject_class->get_property = gdu_tree_model_get_property;
+  gobject_class->set_property = gdu_tree_model_set_property;
+
+  /**
+   * GduTreeModel:client:
+   *
+   * The #UDisksClient used by the #GduTreeModel instance.
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_CLIENT,
+                                   g_param_spec_object ("client",
+                                                        "Client",
+                                                        "The client used by the tree model",
+                                                        UDISKS_TYPE_CLIENT,
+                                                        G_PARAM_READABLE |
+                                                        G_PARAM_WRITABLE |
+                                                        G_PARAM_CONSTRUCT_ONLY |
+                                                        G_PARAM_STATIC_STRINGS));
+}
+
+/**
+ * gdu_tree_model_new:
+ * @client: A #UDisksClient.
+ *
+ * Creates a new #GduTreeModel for viewing the devices belonging to
+ * @client.
+ *
+ * Returns: A #GduTreeModel. Free with g_object_unref().
+ */
+GduTreeModel *
+gdu_tree_model_new (UDisksClient *client)
+{
+  return GDU_TREE_MODEL (g_object_new (GDU_TYPE_TREE_MODEL,
+                                       "client", client,
+                                       NULL));
+}
+
+/**
+ * gdu_tree_model_get_client:
+ * @model: A #GduTreeModel.
+ *
+ * Gets the #UDisksClient used by @model.
+ *
+ * Returns: (transfer none): A #UDisksClient. Do not free, the object
+ * belongs to @model.
+ */
+UDisksClient *
+gdu_tree_model_get_client (GduTreeModel *model)
+{
+  g_return_val_if_fail (GDU_IS_TREE_MODEL (model), NULL);
+  return model->client;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+add_lun (GduTreeModel     *model,
+         GDBusObjectProxy *object_proxy,
+         GtkTreeIter      *parent)
+{
+  const gchar *lun_vendor;
+  const gchar *lun_model;
+  UDisksLun *lun;
+  GIcon *icon;
+  gchar *name;
+  gchar *sort_key;
+  GtkTreeIter iter;
+
+  lun = UDISKS_PEEK_LUN (object_proxy);
+  lun_vendor = udisks_lun_get_vendor (lun);
+  lun_model = udisks_lun_get_model (lun);
+
+  if (strlen (lun_vendor) == 0)
+    name = g_strdup (lun_model);
+  else if (strlen (lun_model) == 0)
+    name = g_strdup (lun_vendor);
+  else
+    name = g_strconcat (lun_vendor, " ", lun_model, NULL);
+
+  icon = g_themed_icon_new ("drive-harddisk"); /* for now */
+  sort_key = g_strdup (g_dbus_object_proxy_get_object_path (object_proxy)); /* for now */
+  gtk_tree_store_insert_with_values (GTK_TREE_STORE (model),
+                                     &iter,
+                                     parent,
+                                     0,
+                                     GDU_TREE_MODEL_COLUMN_ICON, icon,
+                                     GDU_TREE_MODEL_COLUMN_NAME, name,
+                                     GDU_TREE_MODEL_COLUMN_SORT_KEY, sort_key,
+                                     GDU_TREE_MODEL_COLUMN_OBJECT_PROXY, object_proxy,
+                                     -1);
+  g_object_unref (icon);
+  g_free (sort_key);
+  g_free (name);
+}
+
+static void
+remove_lun (GduTreeModel *model,
+            GDBusObjectProxy *object_proxy)
+{
+  GtkTreeIter iter;
+
+  if (!find_iter_for_object_proxy (model,
+                                   object_proxy,
+                                   &iter))
+    {
+      g_warning ("Error finding iter for object proxy at %s",
+                 g_dbus_object_proxy_get_object_path (object_proxy));
+      goto out;
+    }
+
+  gtk_tree_store_remove (GTK_TREE_STORE (model), &iter);
+
+ out:
+  ;
+}
+
+static void
+update_das (GduTreeModel *model)
+{
+  GDBusProxyManager *proxy_manager;
+  GList *object_proxies;
+  GList *luns;
+  GList *added_luns;
+  GList *removed_luns;
+  GList *l;
+
+  proxy_manager = udisks_client_get_proxy_manager (model->client);
+  object_proxies = g_dbus_proxy_manager_get_all (proxy_manager);
+
+  /* update Direct-Attached Storage */
+  luns = NULL;
+  for (l = object_proxies; l != NULL; l = l->next)
+    {
+      GDBusObjectProxy *object_proxy = G_DBUS_OBJECT_PROXY (l->data);
+      UDisksLun *lun;
+
+      lun = UDISKS_PEEK_LUN (object_proxy);
+      if (lun == NULL)
+        continue;
+
+      luns = g_list_prepend (luns, g_object_ref (object_proxy));
+    }
+  luns = g_list_sort (luns, (GCompareFunc) _g_dbus_object_proxy_compare);
+
+  diff_sorted_lists (model->current_luns,
+                     luns,
+                     (GCompareFunc) _g_dbus_object_proxy_compare,
+                     &added_luns,
+                     &removed_luns);
+
+  for (l = removed_luns; l != NULL; l = l->next)
+    {
+      GDBusObjectProxy *object_proxy = G_DBUS_OBJECT_PROXY (l->data);
+
+      g_assert (g_list_find (model->current_luns, object_proxy) != NULL);
+
+      model->current_luns = g_list_remove (model->current_luns, object_proxy);
+      remove_lun (model, object_proxy);
+      g_object_unref (object_proxy);
+    }
+  for (l = added_luns; l != NULL; l = l->next)
+    {
+      GDBusObjectProxy *object_proxy = G_DBUS_OBJECT_PROXY (l->data);
+      model->current_luns = g_list_prepend (model->current_luns, g_object_ref (object_proxy));
+      add_lun (model, object_proxy, &model->direct_attached_storage_iter);
+    }
+
+  g_list_free (added_luns);
+  g_list_free (removed_luns);
+  g_list_foreach (luns, (GFunc) g_object_unref, NULL);
+  g_list_free (luns);
+
+  g_list_foreach (object_proxies, (GFunc) g_object_unref, NULL);
+  g_list_free (object_proxies);
+}
+
+static void
+coldplug (GduTreeModel *model)
+{
+  update_das (model);
+}
+
+static void
+on_object_proxy_added (GDBusProxyManager   *manager,
+                       GDBusObjectProxy    *object_proxy,
+                       gpointer             user_data)
+{
+  GduTreeModel *model = GDU_TREE_MODEL (user_data);
+  update_das (model);
+}
+
+static void
+on_object_proxy_removed (GDBusProxyManager   *manager,
+                         GDBusObjectProxy    *object_proxy,
+                         gpointer             user_data)
+{
+  GduTreeModel *model = GDU_TREE_MODEL (user_data);
+  update_das (model);
+}
diff --git a/src/palimpsest/gdutreemodel.h b/src/palimpsest/gdutreemodel.h
new file mode 100644
index 0000000..bbc4f4b
--- /dev/null
+++ b/src/palimpsest/gdutreemodel.h
@@ -0,0 +1,53 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2008-2011 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#ifndef __GDU_TREE_MODEL_H__
+#define __GDU_TREE_MODEL_H__
+
+#include <gtk/gtk.h>
+#include "gdutypes.h"
+
+G_BEGIN_DECLS
+
+#define GDU_TYPE_TREE_MODEL         (gdu_tree_model_get_type ())
+#define GDU_TREE_MODEL(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GDU_TYPE_TREE_MODEL, GduTreeModel))
+#define GDU_IS_TREE_MODEL(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDU_TYPE_TREE_MODEL))
+
+enum
+{
+  GDU_TREE_MODEL_COLUMN_SORT_KEY,
+  GDU_TREE_MODEL_COLUMN_IS_HEADING,
+  GDU_TREE_MODEL_COLUMN_HEADING_TEXT,
+  GDU_TREE_MODEL_COLUMN_ICON,
+  GDU_TREE_MODEL_COLUMN_NAME,
+  GDU_TREE_MODEL_COLUMN_OBJECT_PROXY,
+  GDU_TREE_MODEL_N_COLUMNS
+};
+
+GType         gdu_tree_model_get_type   (void) G_GNUC_CONST;
+GduTreeModel *gdu_tree_model_new        (UDisksClient *client);
+UDisksClient *gdu_tree_model_get_client (GduTreeModel *model);
+
+
+G_END_DECLS
+
+#endif /* __GDU_TREE_MODEL_H__ */
diff --git a/src/palimpsest/gdutypes.h b/src/palimpsest/gdutypes.h
index 21da58c..e821cc1 100644
--- a/src/palimpsest/gdutypes.h
+++ b/src/palimpsest/gdutypes.h
@@ -32,6 +32,9 @@ G_BEGIN_DECLS
 struct _GduApplication;
 typedef struct _GduApplication GduApplication;
 
+struct _GduTreeModel;
+typedef struct _GduTreeModel GduTreeModel;
+
 G_END_DECLS
 
 #endif /* __GDU_TYPES_H__ */



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