LiNuCe wrote:
> Hello,
> 
>    Here is a small advice on improving navigation in Thunar.
> 
> The problem (and how to reproduce it)
> 
>    I go to /usr/doc where there are hundred of folders, I scroll down
> enough to be sure the folder I'm going to open is down enough to
> be out of the Thunar view if I scroll to the top of it :
> 
>       http://linuce.free.fr/screenshots/thunar-dev/thunar-browsing.0.png
> 
>    Now, I select bsd-games-2.13/ and I open this folder :
> 
>       http://linuce.free.fr/screenshots/thunar-dev/thunar-browsing.1.png
> 
>    Then, I go back to its parent folder, /usr/doc, either with the
> Back icon of the toolbar, or with the Parent icon of the toolbar
> (or with the Alt+Up keyboard shortcut) :
> 
>       http://linuce.free.fr/screenshots/thunar-dev/thunar-browsing.2.png
> 
>    As you can see on this screenshot, the Thunar view does not show
> the bsd-games-2.13/ folder from where I come from.
> 
> Expected results
> 
>    An expected result would be the Thunar view to select the
> bsd-games-2.13/ folder when going back from bsd-games-2.13/
> to /usr/doc (or at least to scroll the view in order to show it) :
> 
>       http://linuce.free.fr/screenshots/thunar-dev/thunar-browsing.3.png

Please try the attached patch (requires latest libexo, r20117). It
should do the trick. It's a bit different to the way it's done in
Nautilus tho. In Nautilus the scroll offset is associated with the
forward/back-history, which is IMHO not very useful in the context of
Thunar.

Benedikt
Index: thunar/thunar-icon-view.c
===================================================================
--- thunar/thunar-icon-view.c	(revision 20106)
+++ thunar/thunar-icon-view.c	(working copy)
@@ -59,10 +59,16 @@
                                                              GtkTreePath         *path,
                                                              gboolean             start_editing);
 static void         thunar_icon_view_scroll_to_path         (ThunarStandardView  *standard_view,
-                                                             GtkTreePath         *path);
+                                                             GtkTreePath         *path,
+                                                             gboolean             use_align,
+                                                             gfloat               row_align,
+                                                             gfloat               col_align);
 static GtkTreePath *thunar_icon_view_get_path_at_pos        (ThunarStandardView  *standard_view,
                                                              gint                 x,
                                                              gint                 y);
+static gboolean     thunar_icon_view_get_visible_range      (ThunarStandardView  *standard_view,
+                                                             GtkTreePath        **start_path,
+                                                             GtkTreePath        **end_path);
 static void         thunar_icon_view_highlight_path         (ThunarStandardView  *standard_view,
                                                              GtkTreePath         *path);
 static GtkAction   *thunar_icon_view_gesture_action         (ThunarIconView      *icon_view);
@@ -200,6 +206,7 @@
   thunarstandard_view_class->set_cursor = thunar_icon_view_set_cursor;
   thunarstandard_view_class->scroll_to_path = thunar_icon_view_scroll_to_path;
   thunarstandard_view_class->get_path_at_pos = thunar_icon_view_get_path_at_pos;
+  thunarstandard_view_class->get_visible_range = thunar_icon_view_get_visible_range;
   thunarstandard_view_class->highlight_path = thunar_icon_view_highlight_path;
   thunarstandard_view_class->zoom_level_property_name = "last-icon-view-zoom-level";
 
@@ -423,10 +430,13 @@
 
 static void
 thunar_icon_view_scroll_to_path (ThunarStandardView *standard_view,
-                                 GtkTreePath        *path)
+                                 GtkTreePath        *path,
+                                 gboolean            use_align,
+                                 gfloat              row_align,
+                                 gfloat              col_align)
 {
   g_return_if_fail (THUNAR_IS_ICON_VIEW (standard_view));
-  exo_icon_view_scroll_to_path (EXO_ICON_VIEW (GTK_BIN (standard_view)->child), path, FALSE, 0.0f, 0.0f);
+  exo_icon_view_scroll_to_path (EXO_ICON_VIEW (GTK_BIN (standard_view)->child), path, use_align, row_align, col_align);
 }
 
 
@@ -442,6 +452,17 @@
 
 
 
+static gboolean
+thunar_icon_view_get_visible_range (ThunarStandardView *standard_view,
+                                    GtkTreePath       **start_path,
+                                    GtkTreePath       **end_path)
+{
+  g_return_val_if_fail (THUNAR_IS_ICON_VIEW (standard_view), FALSE);
+  return exo_icon_view_get_visible_range (EXO_ICON_VIEW (GTK_BIN (standard_view)->child), start_path, end_path);
+}
+
+
+
 static void
 thunar_icon_view_highlight_path (ThunarStandardView *standard_view,
                                  GtkTreePath        *path)
Index: thunar/thunar-standard-view.c
===================================================================
--- thunar/thunar-standard-view.c	(revision 20114)
+++ thunar/thunar-standard-view.c	(working copy)
@@ -113,6 +113,8 @@
 static void                 thunar_standard_view_set_current_directory      (ThunarNavigator          *navigator,
                                                                              ThunarFile               *current_directory);
 static gboolean             thunar_standard_view_get_loading                (ThunarView               *view);
+static void                 thunar_standard_view_set_loading                (ThunarStandardView       *standard_view,
+                                                                             gboolean                  loading);
 static const gchar         *thunar_standard_view_get_statusbar_text         (ThunarView               *view);
 static gboolean             thunar_standard_view_get_show_hidden            (ThunarView               *view);
 static void                 thunar_standard_view_set_show_hidden            (ThunarView               *view,
@@ -276,6 +278,9 @@
    * new files are created by a ThunarVfsJob associated with this view
    */
   GClosure               *new_files_closure;
+
+  /* scroll offsets (-> GtkTreePath indices) per VFS path */
+  GHashTable             *scroll_offsets;
 };
 
 
@@ -513,6 +518,10 @@
   standard_view->priv->drag_scroll_timer_id = -1;
   standard_view->priv->drag_timer_id = -1;
 
+  /* setup the scroll paths offset table */
+  standard_view->priv->scroll_offsets = g_hash_table_new_full (thunar_vfs_path_hash, thunar_vfs_path_equal,
+                                                               (GDestroyNotify) thunar_vfs_path_unref, NULL);
+
   /* grab a reference on the preferences */
   standard_view->preferences = thunar_preferences_get ();
 
@@ -726,6 +735,9 @@
   /* release our list of currently selected files */
   thunar_file_list_free (standard_view->selected_files);
 
+  /* destroy the scroll offset table */
+  g_hash_table_destroy (standard_view->priv->scroll_offsets);
+
   /* free the statusbar text (if any) */
   g_free (standard_view->statusbar_text);
 
@@ -785,7 +797,6 @@
                                    GParamSpec   *pspec)
 {
   ThunarStandardView *standard_view = THUNAR_STANDARD_VIEW (object);
-  gboolean            loading;
 
   switch (prop_id)
     {
@@ -794,14 +805,9 @@
       break;
 
     case PROP_LOADING:
-      loading = g_value_get_boolean (value);
-      if (G_LIKELY (loading != standard_view->loading))
-        {
-          standard_view->loading = loading;
-          g_object_notify (object, "loading");
-          g_object_notify (object, "statusbar-text");
-        }
+      thunar_standard_view_set_loading (standard_view, g_value_get_boolean (value));
       break;
+      break;
       
     case PROP_SELECTED_FILES:
       thunar_component_set_selected_files (THUNAR_COMPONENT (object), g_value_get_boxed (value));
@@ -973,7 +979,7 @@
         }
 
       /* scroll to the first path (previously determined) */
-      (*THUNAR_STANDARD_VIEW_GET_CLASS (standard_view)->scroll_to_path) (standard_view, first_path);
+      (*THUNAR_STANDARD_VIEW_GET_CLASS (standard_view)->scroll_to_path) (standard_view, first_path, FALSE, 0.0f, 0.0f);
 
       /* release the tree paths */
       g_list_foreach (paths, (GFunc) gtk_tree_path_free, NULL);
@@ -1084,10 +1090,34 @@
 {
   ThunarStandardView *standard_view = THUNAR_STANDARD_VIEW (navigator);
   ThunarFolder       *folder;
+  GtkTreePath        *path;
+  ThunarFile         *file;
+  gint                offset;
 
   g_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view));
   g_return_if_fail (current_directory == NULL || THUNAR_IS_FILE (current_directory));
+  
+  /* determine the (previous) current directory */
+  file = thunar_navigator_get_current_directory (navigator);
+  if (G_LIKELY (file != NULL))
+    {
+      /* determine the first visible tree path */
+      if ((*THUNAR_STANDARD_VIEW_GET_CLASS (standard_view)->get_visible_range) (standard_view, &path, NULL))
+        {
+          /* determine the scroll offset from the tree path */
+          offset = gtk_tree_path_get_indices (path)[0] + 1;
+          gtk_tree_path_free (path);
+        }
+      else
+        {
+          /* just use the first available path */
+          offset = 0;
+        }
 
+      /* remember the scroll offset for the directory */
+      g_hash_table_replace (standard_view->priv->scroll_offsets, thunar_vfs_path_ref (thunar_file_get_path (file)), GINT_TO_POINTER (offset));
+    }
+
   /* disconnect any previous "loading" binding */
   if (G_LIKELY (standard_view->loading_binding != NULL))
     exo_binding_unbind (standard_view->loading_binding);
@@ -1134,6 +1164,49 @@
 
 
 
+static void
+thunar_standard_view_set_loading (ThunarStandardView *standard_view,
+                                  gboolean            loading)
+{
+  GtkTreePath *path;
+  ThunarFile  *file;
+  gint         offset;
+
+  loading = !!loading;
+
+  /* check if we're already in that state */
+  if (G_UNLIKELY (standard_view->loading == loading))
+    return;
+
+  /* apply the new state */
+  standard_view->loading = loading;
+
+  /* check if this state change was due to a "loading complete" event */
+  if (G_LIKELY (!loading))
+    {
+      /* determine the current directory */
+      file = thunar_navigator_get_current_directory (THUNAR_NAVIGATOR (standard_view));
+      if (G_LIKELY (file != NULL))
+        {
+          /* determine the scroll offset for this folder */
+          offset = GPOINTER_TO_INT (g_hash_table_lookup (standard_view->priv->scroll_offsets, thunar_file_get_path (file)));
+          if (G_LIKELY (offset > 0))
+            {
+              /* scroll to the path for the offset */
+              path = gtk_tree_path_new_from_indices (offset - 1, -1);
+              (*THUNAR_STANDARD_VIEW_GET_CLASS (standard_view)->scroll_to_path) (standard_view, path, TRUE, 0.0f, 0.0f);
+              gtk_tree_path_free (path);
+            }
+        }
+    }
+
+  /* notify listeners */
+  g_object_notify (G_OBJECT (standard_view), "loading");
+  g_object_notify (G_OBJECT (standard_view), "statusbar-text");
+}
+
+
+
 static const gchar*
 thunar_standard_view_get_statusbar_text (ThunarView *view)
 {
@@ -2123,7 +2196,7 @@
                   if (G_LIKELY (path_list != NULL))
                     {
                       /* place the cursor on the file and scroll the new position */
-                      (*THUNAR_STANDARD_VIEW_GET_CLASS (standard_view)->scroll_to_path) (standard_view, path_list->data);
+                      (*THUNAR_STANDARD_VIEW_GET_CLASS (standard_view)->scroll_to_path) (standard_view, path_list->data, FALSE, 0.0f, 0.0f);
 
                       /* update the selection, so we get updated actions, statusbar,
                        * etc. with the new file name and probably new mime type.
Index: thunar/thunar-standard-view.h
===================================================================
--- thunar/thunar-standard-view.h	(revision 20106)
+++ thunar/thunar-standard-view.h	(working copy)
@@ -78,7 +78,10 @@
    * scroll the view to the given path.
    */
   void         (*scroll_to_path)        (ThunarStandardView *standard_view,
-                                         GtkTreePath        *path);
+                                         GtkTreePath        *path,
+                                         gboolean            use_align,
+                                         gfloat              row_align,
+                                         gfloat              col_align);
 
   /* Returns the path at the given position or NULL if no item/row
    * is located at that coordinates. The path is freed by the caller.
@@ -87,6 +90,11 @@
                                          gint                x,
                                          gint                y);
 
+  /* Returns the visible range */
+  gboolean     (*get_visible_range)     (ThunarStandardView *standard_view,
+                                         GtkTreePath       **start_path,
+                                         GtkTreePath       **end_path);
+
   /* Sets the item/row that is highlighted for feedback. NULL is
    * passed for path to disable the highlighting.
    */
Index: thunar/thunar-details-view.c
===================================================================
--- thunar/thunar-details-view.c	(revision 20106)
+++ thunar/thunar-details-view.c	(working copy)
@@ -40,10 +40,16 @@
                                                                GtkTreePath            *path,
                                                                gboolean                start_editing);
 static void         thunar_details_view_scroll_to_path        (ThunarStandardView     *standard_view,
-                                                               GtkTreePath            *path);
+                                                               GtkTreePath            *path,
+                                                               gboolean                use_align,
+                                                               gfloat                  row_align,
+                                                               gfloat                  col_align);
 static GtkTreePath *thunar_details_view_get_path_at_pos       (ThunarStandardView     *standard_view,
                                                                gint                    x,
                                                                gint                    y);
+static gboolean     thunar_details_view_get_visible_range     (ThunarStandardView     *standard_view,
+                                                               GtkTreePath           **start_path,
+                                                               GtkTreePath           **end_path);
 static void         thunar_details_view_highlight_path        (ThunarStandardView     *standard_view,
                                                                GtkTreePath            *path);
 static void         thunar_details_view_notify_model          (GtkTreeView            *tree_view,
@@ -128,6 +134,7 @@
   thunarstandard_view_class->set_cursor = thunar_details_view_set_cursor;
   thunarstandard_view_class->scroll_to_path = thunar_details_view_scroll_to_path;
   thunarstandard_view_class->get_path_at_pos = thunar_details_view_get_path_at_pos;
+  thunarstandard_view_class->get_visible_range = thunar_details_view_get_visible_range;
   thunarstandard_view_class->highlight_path = thunar_details_view_highlight_path;
   thunarstandard_view_class->zoom_level_property_name = "last-details-view-zoom-level";
 }
@@ -349,7 +356,10 @@
 
 static void
 thunar_details_view_scroll_to_path (ThunarStandardView *standard_view,
-                                    GtkTreePath        *path)
+                                    GtkTreePath        *path,
+                                    gboolean            use_align,
+                                    gfloat              row_align,
+                                    gfloat              col_align)
 {
   GtkTreeViewColumn *column;
 
@@ -357,7 +367,7 @@
 
   /* tell the tree view to scroll to the given row */
   column = gtk_tree_view_get_column (GTK_TREE_VIEW (GTK_BIN (standard_view)->child), 0);
-  gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (GTK_BIN (standard_view)->child), path, column, FALSE, 0.0f, 0.0f);
+  gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (GTK_BIN (standard_view)->child), path, column, use_align, row_align, col_align);
 }
 
 
@@ -379,6 +389,22 @@
 
 
 
+static gboolean
+thunar_details_view_get_visible_range (ThunarStandardView *standard_view,
+                                       GtkTreePath       **start_path,
+                                       GtkTreePath       **end_path)
+{
+  g_return_val_if_fail (THUNAR_IS_DETAILS_VIEW (standard_view), FALSE);
+
+#if GTK_CHECK_VERSION(2,8,0)
+  return gtk_tree_view_get_visible_range (GTK_TREE_VIEW (GTK_BIN (standard_view)->child), start_path, end_path);
+#else
+  return FALSE;
+#endif
+}
+
+
+
 static void
 thunar_details_view_highlight_path (ThunarStandardView *standard_view,
                                     GtkTreePath        *path)
_______________________________________________
Thunar-dev mailing list
Thunar-dev@xfce.org
http://foo-projects.org/mailman/listinfo/thunar-dev

Reply via email to