[gtk+/multiroot-filechooser: 12/15] Show the roots in the sidebar.



commit 556d86fb5fb47d723837d13b8acc691dbbf99331
Author: Christian Hammond <chipx86 chipx86 com>
Date:   Mon Mar 22 17:47:26 2010 -0700

    Show the roots in the sidebar.
    
    Roots will be shown only if:
    
    1) They're not the user's Desktop or Home directories (which would already
       be listed otherwise).
    2) It's not the URI of an existing volume.
    3) The parent volume isn't already a root.
    4) The root actually does exist (preventing non-browseable roots, like "ftp:")

 gtk/gtkfilechooser.c        |   78 +++++++++++++++++++++++++++++++++++++++++++
 gtk/gtkfilechooserbutton.c  |   50 +++++++++++++++++++++++++++
 gtk/gtkfilechooserdefault.c |   55 ++++++++++++++++++++++++++++++
 gtk/gtkfilechooserprivate.h |    2 +
 4 files changed, 185 insertions(+), 0 deletions(-)
---
diff --git a/gtk/gtkfilechooser.c b/gtk/gtkfilechooser.c
index 4306151..2398ce2 100644
--- a/gtk/gtkfilechooser.c
+++ b/gtk/gtkfilechooser.c
@@ -2941,6 +2941,84 @@ _gtk_file_chooser_is_file_in_root (GtkFileChooser *chooser,
   return result;
 }
 
+GSList *
+_gtk_file_chooser_get_visible_roots (GtkFileChooser *chooser)
+{
+  GSList *l, *results = NULL;
+  GtkFileSystem *file_system = _gtk_file_chooser_get_file_system (chooser);
+
+  for (l = gtk_file_chooser_get_root_uris (chooser); l != NULL; l = l->next)
+    {
+      GFile *file = g_file_new_for_uri ((char *)l->data);
+      gboolean skip = FALSE;
+      GtkFileSystemVolume *volume;
+      GFileInfo *file_info;
+      char *file_path;
+
+      if (file == NULL)
+        continue;
+
+      file_path = g_file_get_path (file);
+
+      /*
+       * See if this is the Desktop directory or Home directory, which will
+       * already be listed.
+       */
+      if (!g_strcmp0 (file_path,
+                      g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP)) ||
+          !g_strcmp0 (file_path, g_get_home_dir()))
+        {
+          g_object_unref (file);
+          g_free (file_path);
+          continue;
+        }
+
+      /* Make sure the file exists in some form. */
+      file_info = g_file_query_info (file,
+                                     G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
+                                     G_FILE_QUERY_INFO_NONE,
+                                     NULL,
+                                     NULL);
+
+      if (file_info == NULL)
+        {
+          g_object_unref (file_info);
+          g_object_unref (file);
+          continue;
+        }
+
+      volume = _gtk_file_system_get_volume_for_file (file_system, file);
+
+      if (volume != NULL)
+        {
+          GFile *fs_root = _gtk_file_system_volume_get_root (volume);
+
+          if (fs_root != NULL)
+            {
+              if (_gtk_file_chooser_is_file_in_root (GTK_FILE_CHOOSER (chooser),
+                                                     fs_root))
+                {
+                  // This is going to be listed already. Ignore it for now.
+                  skip = TRUE;
+                }
+
+              g_object_unref (fs_root);
+            }
+        }
+
+      if (skip)
+        {
+          g_object_unref (file);
+          continue;
+        }
+
+      results = g_slist_append (results, file);
+    }
+
+  return results;
+}
+
+
 #define __GTK_FILE_CHOOSER_C__
 #include "gtkaliasdef.c"
 
diff --git a/gtk/gtkfilechooserbutton.c b/gtk/gtkfilechooserbutton.c
index ca4415e..1c79a75 100644
--- a/gtk/gtkfilechooserbutton.c
+++ b/gtk/gtkfilechooserbutton.c
@@ -106,6 +106,7 @@ enum
 typedef enum
 {
   ROW_TYPE_SPECIAL,
+  ROW_TYPE_ROOT,
   ROW_TYPE_VOLUME,
   ROW_TYPE_SHORTCUT,
   ROW_TYPE_BOOKMARK_SEPARATOR,
@@ -156,6 +157,7 @@ struct _GtkFileChooserButtonPrivate
   gint icon_size;
 
   guint8 n_special;
+  guint8 n_roots;
   guint8 n_volumes;
   guint8 n_shortcuts;
   guint8 n_bookmarks;
@@ -536,6 +538,47 @@ gtk_file_chooser_button_file_chooser_iface_init (GtkFileChooserIface *iface)
 }
 
 static void
+reload_roots (GtkFileChooserButton *button)
+{
+  GtkFileChooser *filechooser;
+  GtkFileChooserButtonPrivate *priv = button->priv;
+  GSList *l, *roots;
+  gint start_pos;
+
+  start_pos = model_get_type_position (button, ROW_TYPE_ROOT);
+  model_remove_rows (button, start_pos, priv->n_roots);
+  priv->n_roots = 0;
+
+  filechooser = GTK_FILE_CHOOSER (button->priv->dialog);
+  roots = _gtk_file_chooser_get_visible_roots (GTK_FILE_CHOOSER (filechooser));
+
+  for (l = roots; l != NULL; l = l->next)
+    {
+      GFile *file = (GFile *)l->data;
+      gint pos = start_pos + priv->n_roots;
+      GtkTreeIter iter;
+
+      gtk_list_store_insert (GTK_LIST_STORE (priv->model), &iter, pos);
+      gtk_list_store_set (GTK_LIST_STORE (priv->model), &iter,
+                          ICON_COLUMN, NULL,
+                          DISPLAY_NAME_COLUMN, _(FALLBACK_DISPLAY_NAME),
+                          TYPE_COLUMN, ROW_TYPE_ROOT,
+                          DATA_COLUMN, file,
+                          IS_FOLDER_COLUMN, FALSE,
+                          -1);
+      set_info_for_file_at_iter (button, file, &iter);
+      priv->n_roots++;
+    }
+
+  g_slist_free (roots);
+
+  gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter_model));
+
+  update_label_and_image (button);
+  update_combo_box (button);
+}
+
+static void
 add_shortcut_to_list (GtkFileChooserButton *button,
                       GFile                *shortcut)
 {
@@ -895,6 +938,7 @@ gtk_file_chooser_button_set_property (GObject      *object,
 
       fs_volumes_changed_cb (priv->fs, button);
       fs_bookmarks_changed_cb (priv->fs, button);
+      reload_roots (button);
       reload_shortcuts (button);
 
       break;
@@ -1605,6 +1649,11 @@ model_get_type_position (GtkFileChooserButton *button,
 
   retval += button->priv->n_special;
 
+  if (row_type == ROW_TYPE_ROOT)
+    return retval;
+
+  retval += button->priv->n_roots;
+
   if (row_type == ROW_TYPE_VOLUME)
     return retval;
 
@@ -2631,6 +2680,7 @@ combo_box_changed_cb (GtkComboBox *combo_box,
       switch (type)
 	{
 	case ROW_TYPE_SPECIAL:
+	case ROW_TYPE_ROOT:
 	case ROW_TYPE_SHORTCUT:
 	case ROW_TYPE_BOOKMARK:
 	case ROW_TYPE_CURRENT_FOLDER:
diff --git a/gtk/gtkfilechooserdefault.c b/gtk/gtkfilechooserdefault.c
index d4b94ed..335a666 100644
--- a/gtk/gtkfilechooserdefault.c
+++ b/gtk/gtkfilechooserdefault.c
@@ -244,6 +244,7 @@ typedef enum {
   SHORTCUTS_RECENT_SEPARATOR,
   SHORTCUTS_HOME,
   SHORTCUTS_DESKTOP,
+  SHORTCUTS_ROOTS,
   SHORTCUTS_VOLUMES,
   SHORTCUTS_SHORTCUTS,
   SHORTCUTS_BOOKMARKS_SEPARATOR,
@@ -1410,6 +1411,10 @@ shortcuts_update_count (GtkFileChooserDefault *impl,
 	  impl->has_desktop = TRUE;
 	break;
 
+      case SHORTCUTS_ROOTS:
+	impl->num_roots += value;
+	break;
+
       case SHORTCUTS_VOLUMES:
 	impl->num_volumes += value;
 	break;
@@ -1957,6 +1962,49 @@ shortcuts_append_desktop (GtkFileChooserDefault *impl)
   profile_end ("end", NULL);
 }
 
+static void
+shortcuts_append_roots (GtkFileChooserDefault *impl)
+{
+  GSList *l, *roots;
+  gboolean old_changing_folders;
+  int start_row;
+  int n = 0;
+
+  profile_start ("start", NULL);
+
+  old_changing_folders = impl->changing_folder;
+  impl->changing_folder = TRUE;
+
+  start_row = shortcuts_get_index (impl, SHORTCUTS_ROOTS);
+  shortcuts_remove_rows (impl, start_row, impl->num_roots);
+  impl->num_roots = 0;
+
+  roots = _gtk_file_chooser_get_visible_roots (GTK_FILE_CHOOSER (impl));
+
+  for (l = roots; l != NULL; l = l->next)
+    {
+      GFile *file = (GFile *)l->data;
+
+      shortcuts_insert_file (impl, start_row + n, SHORTCUT_TYPE_FILE,
+                             NULL, file, NULL, FALSE, SHORTCUTS_ROOTS);
+      n++;
+    }
+
+  g_slist_free (roots);
+
+  impl->num_roots = n;
+
+  if (impl->shortcuts_pane_filter_model)
+    gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->shortcuts_pane_filter_model));
+
+  if (impl->shortcuts_combo_filter_model)
+    gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->shortcuts_combo_filter_model));
+
+  impl->changing_folder = old_changing_folders;
+
+  profile_end ("end", NULL);
+}
+
 /* Appends a list of GFile to the shortcuts model; returns how many were inserted */
 static int
 shortcuts_append_bookmarks (GtkFileChooserDefault *impl,
@@ -2036,6 +2084,11 @@ shortcuts_get_index (GtkFileChooserDefault *impl,
 
   n += impl->has_desktop ? 1 : 0;
 
+  if (where == SHORTCUTS_ROOTS)
+    goto out;
+
+  n += impl->num_roots;
+
   if (where == SHORTCUTS_VOLUMES)
     goto out;
 
@@ -2426,6 +2479,7 @@ shortcuts_model_create (GtkFileChooserDefault *impl)
     {
       shortcuts_append_home (impl);
       shortcuts_append_desktop (impl);
+      shortcuts_append_roots (impl);
       shortcuts_add_volumes (impl);
     }
 
@@ -5553,6 +5607,7 @@ static void
 volumes_bookmarks_changed_cb (GtkFileSystem         *file_system,
 			      GtkFileChooserDefault *impl)
 {
+  shortcuts_append_roots (impl);
   shortcuts_add_volumes (impl);
   shortcuts_add_bookmarks (impl);
 
diff --git a/gtk/gtkfilechooserprivate.h b/gtk/gtkfilechooserprivate.h
index dc339c7..c02c3ee 100644
--- a/gtk/gtkfilechooserprivate.h
+++ b/gtk/gtkfilechooserprivate.h
@@ -110,6 +110,7 @@ gboolean       _gtk_file_chooser_is_uri_in_root (GtkFileChooser *chooser,
                                                  const char     *uri);
 gboolean       _gtk_file_chooser_is_file_in_root (GtkFileChooser *chooser,
                                                   GFile          *file);
+GSList *       _gtk_file_chooser_get_visible_roots (GtkFileChooser *chooser);
 
 gboolean       _gtk_file_chooser_uri_has_prefix (const char   *uri,
                                                  const GSList *prefixes);
@@ -262,6 +263,7 @@ struct _GtkFileChooserDefault
   GtkFileFilter *current_filter;
   GSList *filters;
 
+  int num_roots;
   int num_volumes;
   int num_shortcuts;
   int num_bookmarks;



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