[Xfce4-commits] <thunar:master> Modify the history to release ThunarFiles and store GFiles.

Nick Schermer noreply at xfce.org
Mon Oct 22 17:48:02 CEST 2012


Updating branch refs/heads/master
         to fbcf575855e46cd018f63a2c76dfea3d33f8982a (commit)
       from edf2e8c4b5f770376d73a38b5f1c96032312d07b (commit)

commit fbcf575855e46cd018f63a2c76dfea3d33f8982a
Author: Nick Schermer <nick at xfce.org>
Date:   Sun Oct 21 18:38:08 2012 +0200

    Modify the history to release ThunarFiles and store GFiles.
    
    This makes remote mount easier and drops memory usage for
    history items. Also handle removed location properly.

 thunar/thunar-history.c |  307 +++++++++++++++++++++++++++++++++++++----------
 thunar/thunar-window.c  |    9 ++-
 2 files changed, 250 insertions(+), 66 deletions(-)

diff --git a/thunar/thunar-history.c b/thunar/thunar-history.c
index ce16db5..57298c5 100644
--- a/thunar/thunar-history.c
+++ b/thunar/thunar-history.c
@@ -27,6 +27,7 @@
 #include <thunar/thunar-icon-factory.h>
 #include <thunar/thunar-navigator.h>
 #include <thunar/thunar-private.h>
+#include <thunar/thunar-dialogs.h>
 
 
 
@@ -55,9 +56,9 @@ static ThunarFile     *thunar_history_get_current_directory  (ThunarNavigator
 static void            thunar_history_set_current_directory  (ThunarNavigator      *navigator,
                                                               ThunarFile           *current_directory);
 static void            thunar_history_go_back                (ThunarHistory        *history,
-                                                              guint                 n);
+                                                              GFile                *goto_file);
 static void            thunar_history_go_forward             (ThunarHistory        *history,
-                                                              guint                 n);
+                                                              GFile                *goto_file);
 static void            thunar_history_action_back            (GtkAction            *action,
                                                               ThunarHistory        *history);
 static void            thunar_history_action_back_nth        (GtkWidget            *item,
@@ -90,8 +91,8 @@ struct _ThunarHistory
   GtkAction      *action_back;
   GtkAction      *action_forward;
 
-  GList          *back_list;
-  GList          *forward_list;
+  GSList         *back_list;
+  GSList         *forward_list;
 };
 
 
@@ -101,6 +102,11 @@ G_DEFINE_TYPE_WITH_CODE (ThunarHistory, thunar_history, G_TYPE_OBJECT,
 
 
 
+static GQuark thunar_history_display_name_quark;
+static GQuark thunar_history_gfile_quark;
+
+
+
 static void
 thunar_history_class_init (ThunarHistoryClass *klass)
 {
@@ -112,6 +118,9 @@ thunar_history_class_init (ThunarHistoryClass *klass)
   gobject_class->get_property = thunar_history_get_property;
   gobject_class->set_property = thunar_history_set_property;
 
+  thunar_history_display_name_quark = g_quark_from_static_string ("thunar-history-display-name");
+  thunar_history_gfile_quark = g_quark_from_static_string ("thunar-history-gfile");
+
   /**
    * ThunarHistory::action-group:
    *
@@ -195,8 +204,8 @@ thunar_history_finalize (GObject *object)
   g_object_unref (G_OBJECT (history->action_back));
 
   /* release the "forward" and "back" lists */
-  thunar_file_list_free (history->forward_list);
-  thunar_file_list_free (history->back_list);
+  g_slist_free_full (history->forward_list, g_object_unref);
+  g_slist_free_full (history->back_list, g_object_unref);
 
   (*G_OBJECT_CLASS (thunar_history_parent_class)->finalize) (object);
 }
@@ -263,11 +272,31 @@ thunar_history_get_current_directory (ThunarNavigator *navigator)
 
 
 
+static GFile *
+thunar_history_get_gfile (ThunarFile *file)
+{
+  GFile       *gfile;
+  const gchar *display_name;
+
+  _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL);
+
+  gfile = thunar_file_get_file (file);
+
+  display_name = thunar_file_get_display_name (file);
+  g_object_set_qdata_full (G_OBJECT (gfile), thunar_history_display_name_quark,
+                           g_strdup (display_name), g_free);
+
+  return g_object_ref (gfile);
+}
+
+
+
 static void
 thunar_history_set_current_directory (ThunarNavigator *navigator,
                                       ThunarFile      *current_directory)
 {
   ThunarHistory *history = THUNAR_HISTORY (navigator);
+  GFile         *gfile;
 
   /* verify that we don't already use that directory */
   if (G_UNLIKELY (current_directory == history->current_directory))
@@ -276,20 +305,27 @@ thunar_history_set_current_directory (ThunarNavigator *navigator,
   /* if the new directory is the first one in the forward history, we
    * just move forward one step instead of clearing the whole forward
    * history */
-  if (history->forward_list != NULL && history->forward_list->data == current_directory)
-    thunar_history_go_forward (history, 1);
+  if (current_directory != NULL
+      && history->forward_list != NULL
+      && g_file_equal (thunar_file_get_file (current_directory), history->forward_list->data))
+    {
+      thunar_history_go_forward (history, history->forward_list->data);
+    }
   else
     {
       /* clear the "forward" list */
       gtk_action_set_sensitive (history->action_forward, FALSE);
-      thunar_file_list_free (history->forward_list);
+      g_slist_free_full (history->forward_list, g_object_unref);
       history->forward_list = NULL;
 
       /* prepend the previous current directory to the "back" list */
       if (G_LIKELY (history->current_directory != NULL))
         {
-          history->back_list = g_list_prepend (history->back_list, history->current_directory);
+          gfile = thunar_history_get_gfile (history->current_directory);
+          history->back_list = g_slist_prepend (history->back_list, gfile);
           gtk_action_set_sensitive (history->action_back, TRUE);
+
+          g_object_unref (history->current_directory);
         }
 
       /* activate the new current directory */
@@ -307,28 +343,97 @@ thunar_history_set_current_directory (ThunarNavigator *navigator,
 
 
 static void
-thunar_history_go_back (ThunarHistory *history,
-                        guint          n)
+thunar_history_error_not_found (GFile    *goto_file,
+                                gpointer  parent)
+{
+  gchar  *parse_name;
+  GError *error;
+
+  g_set_error_literal (&error, G_FILE_ERROR, G_FILE_ERROR_EXIST, _("The item will be removed from the history"));
+
+  parse_name = g_file_get_parse_name (goto_file);
+  thunar_dialogs_show_error (parent, error, _("Could not find \"%s\""), parse_name);
+  g_free (parse_name);
+
+  g_error_free (error);
+}
+
+
+
+static void
+thunar_history_go_back (ThunarHistory  *history,
+                        GFile          *goto_file)
 {
+  GFile      *gfile;
+  GSList     *lp;
+  GSList     *lnext;
+  ThunarFile *directory;
+
   _thunar_return_if_fail (THUNAR_IS_HISTORY (history));
-  _thunar_return_if_fail (n > 0);
+  _thunar_return_if_fail (G_IS_FILE (goto_file));
 
-  /* go back up to n steps */
-  for (; n > 0 && history->back_list != NULL; --n)
+  /* check if the directory still exists */
+  directory = thunar_file_get (goto_file, NULL);
+  if (directory == NULL)
     {
-      /* prepend the previous current directory to the "forward" list */
-      if (G_LIKELY (history->current_directory != NULL))
-        history->forward_list = g_list_prepend (history->forward_list, history->current_directory);
+      thunar_history_error_not_found (goto_file, NULL);
+
+      /* delete item from the history */
+      lp = g_slist_find (history->back_list, goto_file);
+      if (lp != NULL)
+        {
+          g_object_unref (lp->data);
+          history->back_list = g_slist_delete_link (history->back_list, lp);
+        }
+
+      goto update_actions;
+    }
+
+  /* prepend the previous current directory to the "forward" list */
+  if (G_LIKELY (history->current_directory != NULL))
+    {
+      gfile = thunar_history_get_gfile (history->current_directory);
+      history->forward_list = g_slist_prepend (history->forward_list, gfile);
+
+      g_object_unref (history->current_directory);
+      history->current_directory = NULL;
+    }
+
+  /* add all the items of the back list to the "forward" list until
+   * the atarget file is reached  */
+  for (lp = history->back_list; lp != NULL; lp = lnext)
+    {
+      lnext = lp->next;
+
+      if (g_file_equal (goto_file, G_FILE (lp->data)))
+        {
+          if (directory != NULL)
+            history->current_directory = g_object_ref (directory);
+
+          /* remove the new dirctory from the list */
+          g_object_unref (lp->data);
+          history->back_list = g_slist_delete_link (history->back_list, lp);
+
+          break;
+        }
+
+      /* remove item from the list */
+      history->back_list = g_slist_remove_link (history->back_list, lp);
 
-      /* remove the first directory from the "back" list and make it the current directory */
-      history->current_directory = history->back_list->data;
-      history->back_list = g_list_delete_link (history->back_list, history->back_list);
+      /* prepend element to the other list */
+      lp->next = history->forward_list;
+      history->forward_list = lp;
     }
 
+  if (directory != NULL)
+    g_object_unref (directory);
+
   /* tell the other modules to change the current directory */
   if (G_LIKELY (history->current_directory != NULL))
     thunar_navigator_change_directory (THUNAR_NAVIGATOR (history), history->current_directory);
 
+  update_actions:
+
   /* update the sensitivity of the actions */
   gtk_action_set_sensitive (history->action_back, (history->back_list != NULL));
   gtk_action_set_sensitive (history->action_forward, (history->forward_list != NULL));
@@ -337,28 +442,77 @@ thunar_history_go_back (ThunarHistory *history,
 
 
 static void
-thunar_history_go_forward (ThunarHistory *history,
-                           guint          n)
+thunar_history_go_forward (ThunarHistory  *history,
+                           GFile          *goto_file)
 {
+  GFile      *gfile;
+  GSList     *lnext;
+  GSList     *lp;
+  ThunarFile *directory;
+
   _thunar_return_if_fail (THUNAR_IS_HISTORY (history));
-  _thunar_return_if_fail (n > 0);
+  _thunar_return_if_fail (G_IS_FILE (goto_file));
 
-  /* go forward up to n steps */
-  for (; n > 0 && history->forward_list != NULL; --n)
+  /* check if the directory still exists */
+  directory = thunar_file_get (goto_file, NULL);
+  if (directory == NULL)
     {
-      /* prepend the previous current directory to the "back" list */
-      if (G_LIKELY (history->current_directory != NULL))
-        history->back_list = g_list_prepend (history->back_list, history->current_directory);
+      thunar_history_error_not_found (goto_file, NULL);
+
+      /* delete item from the history */
+      lp = g_slist_find (history->forward_list, goto_file);
+      if (lp != NULL)
+        {
+          g_object_unref (lp->data);
+          history->forward_list = g_slist_delete_link (history->forward_list, lp);
+        }
+
+      goto update_actions;
+    }
+
+  /* prepend the previous current directory to the "back" list */
+  if (G_LIKELY (history->current_directory != NULL))
+    {
+      gfile = thunar_history_get_gfile (history->current_directory);
+      history->back_list = g_slist_prepend (history->back_list, gfile);
+
+      g_object_unref (history->current_directory);
+      history->current_directory = NULL;
+    }
 
-      /* remove the first directory from the "forward" list and make it the current directory */
-      history->current_directory = history->forward_list->data;
-      history->forward_list = g_list_delete_link (history->forward_list, history->forward_list);
+  for (lp = history->forward_list; lp != NULL; lp = lnext)
+    {
+      lnext = lp->next;
+
+      if (g_file_equal (goto_file, G_FILE (lp->data)))
+        {
+          if (directory != NULL)
+            history->current_directory = g_object_ref (directory);
+
+          /* remove the new dirctory from the list */
+          g_object_unref (lp->data);
+          history->forward_list = g_slist_delete_link (history->forward_list, lp);
+
+          break;
+        }
+
+      /* remove item from the list */
+      history->forward_list = g_slist_remove_link (history->forward_list, lp);
+
+      /* prepend item to the back list */
+      lp->next = history->back_list;
+      history->back_list = lp;
     }
 
+  if (directory != NULL)
+    g_object_unref (directory);
+
   /* tell the other modules to change the current directory */
   if (G_LIKELY (history->current_directory != NULL))
     thunar_navigator_change_directory (THUNAR_NAVIGATOR (history), history->current_directory);
 
+  update_actions:
+
   /* update the sensitivity of the actions */
   gtk_action_set_sensitive (history->action_back, (history->back_list != NULL));
   gtk_action_set_sensitive (history->action_forward, (history->forward_list != NULL));
@@ -372,9 +526,10 @@ thunar_history_action_back (GtkAction     *action,
 {
   _thunar_return_if_fail (GTK_IS_ACTION (action));
   _thunar_return_if_fail (THUNAR_IS_HISTORY (history));
-  
+
   /* go back one step */
-  thunar_history_go_back (history, 1);
+  if (history->back_list != NULL)
+    thunar_history_go_back (history, history->back_list->data);
 }
 
 
@@ -383,14 +538,14 @@ static void
 thunar_history_action_back_nth (GtkWidget     *item,
                                 ThunarHistory *history)
 {
-  guint n;
+  GFile *file;
 
   _thunar_return_if_fail (GTK_IS_MENU_ITEM (item));
   _thunar_return_if_fail (THUNAR_IS_HISTORY (history));
 
-  n = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (item), "thunar-history-index"));
-  if (G_LIKELY (n > 0))
-    thunar_history_go_back (history, n);
+  file = g_object_get_qdata (G_OBJECT (item), thunar_history_gfile_quark);
+  if (G_LIKELY (file != NULL))
+    thunar_history_go_back (history, file);
 }
 
 
@@ -403,7 +558,8 @@ thunar_history_action_forward (GtkAction     *action,
   _thunar_return_if_fail (THUNAR_IS_HISTORY (history));
 
   /* go forward one step */
-  thunar_history_go_forward (history, 1);
+  if (history->forward_list != NULL)
+    thunar_history_go_forward (history, history->forward_list->data);
 }
 
 
@@ -412,14 +568,14 @@ static void
 thunar_history_action_forward_nth (GtkWidget     *item,
                                    ThunarHistory *history)
 {
-  guint n;
+  GFile *file;
 
   _thunar_return_if_fail (GTK_IS_MENU_ITEM (item));
   _thunar_return_if_fail (THUNAR_IS_HISTORY (history));
 
-  n = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (item), "thunar-history-index"));
-  if (G_LIKELY (n > 0))
-    thunar_history_go_forward (history, n);
+  file = g_object_get_qdata (G_OBJECT (item), thunar_history_gfile_quark);
+  if (G_LIKELY (file != NULL))
+    thunar_history_go_forward (history, file);
 }
 
 
@@ -435,8 +591,10 @@ thunar_history_show_menu (GtkAction     *action,
   GtkWidget         *image;
   GtkWidget         *item;
   GdkPixbuf         *icon;
-  GList             *lp;
-  guint              n;
+  GSList            *lp;
+  ThunarFile        *file;
+  const gchar       *display_name;
+  const gchar       *icon_name;
 
   _thunar_return_if_fail (GTK_IS_ACTION (action));
   _thunar_return_if_fail (GTK_IS_MENU_SHELL (menu));
@@ -461,24 +619,45 @@ thunar_history_show_menu (GtkAction     *action,
     }
 
   /* add menu items for all list items */
-  for (n = 1; lp != NULL; lp = lp->next, ++n)
+  for (;lp != NULL; lp = lp->next)
     {
-      /* load the icon for the file */
-      icon = thunar_icon_factory_load_file_icon (icon_factory, lp->data, THUNAR_FILE_ICON_STATE_DEFAULT, 16);
-
       /* add an item for this file */
-      item = gtk_image_menu_item_new_with_label (thunar_file_get_display_name (lp->data));
-      g_object_set_data (G_OBJECT (item), I_("thunar-history-index"), GUINT_TO_POINTER (n));
-      g_signal_connect_object (G_OBJECT (item), "activate", handler, history, 0);
+      display_name = g_object_get_qdata (G_OBJECT (lp->data), thunar_history_display_name_quark);
+      item = gtk_image_menu_item_new_with_label (display_name);
+      g_object_set_qdata (G_OBJECT (item), thunar_history_gfile_quark, lp->data);
+      g_signal_connect (G_OBJECT (item), "activate", handler, history);
       gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
       gtk_widget_show (item);
 
-      /* setup the image for the file */
-      image = gtk_image_new_from_pixbuf (icon);
-      gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
+      file = thunar_file_cache_lookup (lp->data);
+      image = NULL;
+      if (file != NULL)
+        {
+          /* load the icon for the file */
+          icon = thunar_icon_factory_load_file_icon (icon_factory, file, THUNAR_FILE_ICON_STATE_DEFAULT, 16);
+          if (icon != NULL)
+            {
+              /* setup the image for the file */
+              image = gtk_image_new_from_pixbuf (icon);
+              g_object_unref (G_OBJECT (icon));
+            }
+        }
 
-      /* release the icon */
-      g_object_unref (G_OBJECT (icon));
+      if (image == NULL)
+        {
+          /* some custom likely alternatives */
+          if (thunar_g_file_is_root (lp->data))
+            icon_name = "drive-harddisk";
+          else if (thunar_g_file_is_home (lp->data))
+            icon_name = "user-home";
+          else if (g_file_has_uri_scheme (lp->data, "file"))
+            icon_name = GTK_STOCK_DIRECTORY;
+          else
+            icon_name = "folder-remote";
+
+          image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
+        }
+      gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
     }
 
   /* release the icon factory */
@@ -557,10 +736,9 @@ thunar_history_set_action_group (ThunarHistory  *history,
  * thunar_file_history_peek_back:
  * @history : a #ThunarHistory.
  *
- * Returns the previous directory in the history. 
+ * Returns the previous directory in the history.
  *
- * The returned #ThunarFile is owned by the #ThunarHistory and must
- * not be released by the caller.
+ * The returned #ThunarFile must be released by the caller.
  *
  * Return value: the previous #ThunarFile in the history.
  **/
@@ -573,7 +751,7 @@ thunar_history_peek_back (ThunarHistory *history)
 
   /* pick the first (conceptually the last) file in the back list, if there are any */
   if (history->back_list != NULL)
-    result = history->back_list->data;
+    result = thunar_file_get (history->back_list->data, NULL);
 
   return result;
 }
@@ -584,11 +762,10 @@ thunar_history_peek_back (ThunarHistory *history)
  * thunar_file_history_peek_forward:
  * @history : a #ThunarHistory.
  *
- * Returns the next directory in the history. This often but not always 
+ * Returns the next directory in the history. This often but not always
  * refers to a child of the current directory.
  *
- * The returned #ThunarFile is owned by the #ThunarHistory and must
- * not be released by the caller.
+ * The returned #ThunarFile must be released by the caller.
  *
  * Return value: the next #ThunarFile in the history.
  **/
@@ -601,7 +778,7 @@ thunar_history_peek_forward (ThunarHistory *history)
 
   /* pick the first file in the forward list, if there are any */
   if (history->forward_list != NULL)
-    result = history->forward_list->data;
+    result = thunar_file_get (history->forward_list->data, NULL);
 
   return result;
 }
diff --git a/thunar/thunar-window.c b/thunar/thunar-window.c
index 8a56f94..3e87a7f 100644
--- a/thunar/thunar-window.c
+++ b/thunar/thunar-window.c
@@ -3071,6 +3071,8 @@ thunar_window_set_current_directory (ThunarWindow *window,
            * directory */
           if (thunar_file_is_parent (window->current_directory, selected_file))
             selected_files.data = selected_file;
+          else
+            g_object_unref (selected_file);
         }
 
       /* do the same with the previous file in the history */
@@ -3083,13 +3085,18 @@ thunar_window_set_current_directory (ThunarWindow *window,
                * new directory */
               if (thunar_file_is_parent (window->current_directory, selected_file))
                 selected_files.data = selected_file;
+              else
+                g_object_unref (selected_file);
             }
         }
 
       /* select the previous or next file from the history if it is inside the
        * new current directory */
       if (selected_files.data != NULL)
-        thunar_component_set_selected_files (THUNAR_COMPONENT (window->view), &selected_files);
+        {
+          thunar_component_set_selected_files (THUNAR_COMPONENT (window->view), &selected_files);
+          g_object_unref (G_OBJECT (selected_files.data));
+        }
     }
 }
 


More information about the Xfce4-commits mailing list