[gthumb] selections: pressing control-n again goes back to the previous view



commit ce6aabd0c9372f22339866aa664df620fbcefb20
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Mon Dec 31 15:00:39 2012 +0100

    selections: pressing control-n again goes back to the previous view

 extensions/selections/actions.c |   12 +++-
 gthumb/gth-browser.c            |  156 ++++++++++++++++++++++++++++++++++++---
 gthumb/gth-browser.h            |    2 +
 gthumb/gth-file-list.c          |   45 +++++++++++-
 gthumb/gth-file-list.h          |    3 +
 gthumb/gth-file-view.c          |    8 ++
 gthumb/gth-file-view.h          |    4 +
 gthumb/gth-grid-view.c          |   21 +++++-
 8 files changed, 237 insertions(+), 14 deletions(-)
---
diff --git a/extensions/selections/actions.c b/extensions/selections/actions.c
index 9b655ba..2829e3e 100644
--- a/extensions/selections/actions.c
+++ b/extensions/selections/actions.c
@@ -34,10 +34,18 @@ gth_browser_activate_action_show_selection (GthBrowser *browser,
 
 	uri = g_strdup_printf ("selection:///%d", n_selection);
 	location = g_file_new_for_uri (uri);
-	gth_browser_load_location (browser, location);
 
-	g_free (uri);
+	if (_g_file_equal_uris (location, gth_browser_get_location (browser))) {
+		if (! gth_browser_restore_state (browser))
+			gth_browser_load_location (browser, location);
+	}
+	else {
+		gth_browser_save_state (browser);
+		gth_browser_load_location (browser, location);
+	}
+
 	g_object_unref (location);
+	g_free (uri);
 }
 
 
diff --git a/gthumb/gth-browser.c b/gthumb/gth-browser.c
index 85688f3..7098a32 100644
--- a/gthumb/gth-browser.c
+++ b/gthumb/gth-browser.c
@@ -86,6 +86,16 @@ enum {
 };
 
 
+typedef struct {
+	gboolean        saved;
+	GthBrowserPage  page;
+	GFile          *location;
+	GFile          *current_file;
+	GList          *selected;
+	double          vscroll;
+} BrowserState;
+
+
 struct _GthBrowserPrivate {
 	/* UI staff */
 
@@ -169,6 +179,7 @@ struct _GthBrowserPrivate {
 	gboolean           shrink_wrap_viewer;
 	gboolean           file_properties_on_the_right;
 	GthSidebarState    viewer_sidebar;
+	BrowserState       state;
 
 	/* settings */
 
@@ -205,6 +216,38 @@ struct _GthBrowserPrivate {
 static guint gth_browser_signals[LAST_SIGNAL] = { 0 };
 
 
+/* -- browser_state -- */
+
+
+static void
+browser_state_init (BrowserState *state)
+{
+	state->saved = FALSE;
+	state->page = 0;
+	state->location = NULL;
+	state->current_file = NULL;
+	state->selected = NULL;
+}
+
+
+static void
+browser_state_free (BrowserState *state)
+{
+	if (! state->saved)
+		return;
+
+	_g_object_unref (state->location);
+	_g_object_unref (state->current_file);
+	g_list_foreach (state->selected, (GFunc) gtk_tree_path_free, NULL);
+	g_list_free (state->selected);
+
+	state->location = NULL;
+	state->current_file = NULL;
+	state->selected = NULL;
+	state->saved = FALSE;
+}
+
+
 /* -- monitor_event_data -- */
 
 
@@ -1154,6 +1197,8 @@ typedef struct {
 	GthFileData   *requested_folder;
 	GFile         *requested_folder_parent;
 	GFile         *file_to_select;
+	GList         *selected;
+	double         vscroll;
 	GthAction      action;
 	gboolean       automatic;
 	GList         *list;
@@ -1168,6 +1213,8 @@ static LoadData *
 load_data_new (GthBrowser *browser,
 	       GFile      *location,
 	       GFile      *file_to_select,
+	       GList      *selected,
+	       double      vscroll,
 	       GthAction   action,
 	       gboolean    automatic,
 	       GFile      *entry_point)
@@ -1183,6 +1230,8 @@ load_data_new (GthBrowser *browser,
 		load_data->file_to_select = g_file_dup (file_to_select);
 	else if (browser->priv->current_file != NULL)
 		load_data->file_to_select = g_file_dup (browser->priv->current_file->file);
+	load_data->selected = g_list_copy_deep (selected, (GCopyFunc) gtk_tree_path_copy, NULL);
+	load_data->vscroll = vscroll;
 	load_data->action = action;
 	load_data->automatic = automatic;
 	load_data->cancellable = g_cancellable_new ();
@@ -1221,6 +1270,7 @@ load_data_free (LoadData *data)
 	g_object_unref (data->requested_folder);
 	_g_object_unref (data->requested_folder_parent);
 	_g_object_unref (data->file_to_select);
+	g_list_free_full (data->selected, (GDestroyNotify) gtk_tree_path_free);
 	_g_object_unref (data->file_source);
 	_g_object_list_unref (data->list);
 	_g_object_unref (data->entry_point);
@@ -1229,7 +1279,14 @@ load_data_free (LoadData *data)
 }
 
 
-static void _gth_browser_load (GthBrowser *browser, GFile *location, GFile *file_to_select, GthAction action, gboolean automatic);
+static void
+_gth_browser_load (GthBrowser *browser,
+		   GFile      *location,
+		   GFile      *file_to_select,
+		   GList      *selected,
+		   double      vscroll,
+		   GthAction   action,
+		   gboolean    automatic);
 
 
 static char *
@@ -1326,6 +1383,8 @@ load_data_done (LoadData *load_data,
 			_gth_browser_load (load_data->browser,
 					   parent,
 					   NULL,
+					   NULL,
+					   0,
 					   load_data->action,
 					   TRUE);
 			g_object_unref (parent);
@@ -1747,6 +1806,8 @@ load_data_continue (LoadData *load_data,
 
 		if (load_data->file_to_select != NULL)
 			gth_file_list_make_file_visible (GTH_FILE_LIST (browser->priv->file_list), load_data->file_to_select);
+		else if ((load_data->selected != NULL) || (load_data->vscroll > 0))
+			gth_file_list_restore_state (GTH_FILE_LIST (browser->priv->file_list), load_data->selected, load_data->vscroll);
 
 		_gth_browser_update_statusbar_list_info (browser);
 
@@ -1922,6 +1983,8 @@ mount_volume_ready_cb (GObject      *source_object,
 	_gth_browser_load (load_data->browser,
 			   load_data->requested_folder->file,
 			   load_data->file_to_select,
+			   NULL,
+			   0,
 			   load_data->action,
 			   load_data->automatic);
 
@@ -1941,6 +2004,8 @@ static void
 _gth_browser_load (GthBrowser *browser,
 		   GFile      *location,
 		   GFile      *file_to_select,
+		   GList      *selected,
+		   double      vscroll,
 		   GthAction   action,
 		   gboolean    automatic)
 {
@@ -1968,7 +2033,14 @@ _gth_browser_load (GthBrowser *browser,
 	}
 
 	entry_point = get_nearest_entry_point (location);
-	load_data = load_data_new (browser, location, file_to_select, action, automatic, entry_point);
+	load_data = load_data_new (browser,
+				   location,
+				   file_to_select,
+				   selected,
+				   vscroll,
+				   action,
+				   automatic,
+				   entry_point);
 
 	if (entry_point == NULL) {
 		GMountOperation *mount_op;
@@ -2612,6 +2684,7 @@ gth_browser_finalize (GObject *object)
 {
 	GthBrowser *browser = GTH_BROWSER (object);
 
+	browser_state_free (&browser->priv->state);
 	_g_object_unref (browser->priv->browser_settings);
 	_g_object_unref (browser->priv->messages_settings);
 	_g_object_unref (browser->priv->desktop_interface_settings);
@@ -2851,7 +2924,7 @@ folder_tree_list_children_cb (GthFolderTree *folder_tree,
 			      GFile         *file,
 			      GthBrowser    *browser)
 {
-	_gth_browser_load (browser, file, NULL, GTH_ACTION_LIST_CHILDREN, FALSE);
+	_gth_browser_load (browser, file, NULL, NULL, 0, GTH_ACTION_LIST_CHILDREN, FALSE);
 }
 
 
@@ -2860,7 +2933,7 @@ folder_tree_load_cb (GthFolderTree *folder_tree,
 		     GFile         *file,
 		     GthBrowser    *browser)
 {
-	_gth_browser_load (browser, file, NULL, GTH_ACTION_VIEW, FALSE);
+	_gth_browser_load (browser, file, NULL, NULL, 0, GTH_ACTION_VIEW, FALSE);
 }
 
 
@@ -3120,10 +3193,10 @@ folder_changed_cb (GthMonitor      *monitor,
 		return;
 
 	if ((event == GTH_MONITOR_EVENT_DELETED) && (_g_file_list_find_file_or_ancestor (list, browser->priv->location->file) != NULL))
-		_gth_browser_load (browser, parent, NULL, GTH_ACTION_GO_TO, TRUE);
+		_gth_browser_load (browser, parent, NULL, NULL, 0, GTH_ACTION_GO_TO, TRUE);
 
 	if ((event == GTH_MONITOR_EVENT_CHANGED) && (_g_file_list_find_file_or_ancestor (list, browser->priv->location->file) != NULL)) {
-		_gth_browser_load (browser, browser->priv->location->file, NULL, GTH_ACTION_GO_TO, TRUE);
+		_gth_browser_load (browser, browser->priv->location->file, NULL, NULL, 0, GTH_ACTION_GO_TO, TRUE);
 		return;
 	}
 
@@ -4278,6 +4351,8 @@ gth_browser_init (GthBrowser *browser)
 	browser->priv->desktop_interface_settings = g_settings_new (GNOME_DESKTOP_INTERFACE_SCHEMA);
 	browser->priv->file_properties_on_the_right = g_settings_get_boolean (browser->priv->browser_settings, PREF_BROWSER_PROPERTIES_ON_THE_RIGHT);
 
+	browser_state_init (&browser->priv->state);
+
 	/* find a suitable size for the window */
 
 	window_width = g_settings_get_int (browser->priv->browser_settings, PREF_BROWSER_WINDOW_WIDTH);
@@ -4850,7 +4925,18 @@ gth_browser_go_to (GthBrowser *browser,
 		   GFile      *file_to_select)
 {
 	gth_window_set_current_page (GTH_WINDOW (browser), GTH_BROWSER_PAGE_BROWSER);
-	_gth_browser_load (browser, location, file_to_select, GTH_ACTION_GO_TO, FALSE);
+	_gth_browser_load (browser, location, file_to_select, NULL, 0, GTH_ACTION_GO_TO, FALSE);
+}
+
+
+static void
+gth_browser_go_to_with_state (GthBrowser  *browser,
+			      GFile       *location,
+			      GList       *selected,
+			      double       vscroll)
+{
+	gth_window_set_current_page (GTH_WINDOW (browser), GTH_BROWSER_PAGE_BROWSER);
+	_gth_browser_load (browser, location, NULL, selected, vscroll, GTH_ACTION_GO_TO, FALSE);
 }
 
 
@@ -4868,7 +4954,7 @@ gth_browser_go_back (GthBrowser *browser,
 		return;
 
 	browser->priv->history_current = new_current;
-	_gth_browser_load (browser, (GFile*) browser->priv->history_current->data, NULL, GTH_ACTION_GO_BACK, FALSE);
+	_gth_browser_load (browser, (GFile*) browser->priv->history_current->data, NULL, NULL, 0, GTH_ACTION_GO_BACK, FALSE);
 }
 
 
@@ -4886,7 +4972,7 @@ gth_browser_go_forward (GthBrowser *browser,
 		return;
 
 	browser->priv->history_current = new_current;
-	_gth_browser_load (browser, (GFile *) browser->priv->history_current->data, NULL, GTH_ACTION_GO_FORWARD, FALSE);
+	_gth_browser_load (browser, (GFile *) browser->priv->history_current->data, NULL, NULL, 0, GTH_ACTION_GO_FORWARD, FALSE);
 }
 
 
@@ -5703,7 +5789,7 @@ file_metadata_ready_cb (GList    *files,
 		GFile *parent;
 
 		parent = g_file_get_parent (file_data->file);
-		_gth_browser_load (browser, parent, file_data->file, GTH_ACTION_GO_TO, FALSE);
+		_gth_browser_load (browser, parent, file_data->file, NULL, 0, GTH_ACTION_GO_TO, FALSE);
 		g_object_unref (parent);
 	}
 
@@ -6573,3 +6659,53 @@ gth_browser_file_menu_popup (GthBrowser     *browser,
 			button,
 			event_time);
 }
+
+
+void
+gth_browser_save_state (GthBrowser *browser)
+{
+	browser_state_free (&browser->priv->state);
+
+	browser->priv->state.saved = TRUE;
+	browser->priv->state.page = gth_window_get_current_page (GTH_WINDOW (browser));
+	if (browser->priv->location != NULL)
+		browser->priv->state.location = g_object_ref (browser->priv->location->file);
+	if (browser->priv->current_file != NULL)
+		browser->priv->state.current_file = g_object_ref (browser->priv->current_file->file);
+	browser->priv->state.selected = gth_file_selection_get_selected (GTH_FILE_SELECTION (gth_file_list_get_view (GTH_FILE_LIST (browser->priv->file_list))));
+	browser->priv->state.vscroll = gtk_adjustment_get_value (gth_file_list_get_vadjustment (GTH_FILE_LIST (browser->priv->file_list)));
+}
+
+
+gboolean
+gth_browser_restore_state (GthBrowser *browser)
+{
+	if (! browser->priv->state.saved)
+		return FALSE;
+
+	switch (browser->priv->state.page) {
+	case GTH_BROWSER_PAGE_BROWSER:
+		if (browser->priv->state.current_file != NULL) {
+			gth_browser_go_to (browser,
+					   browser->priv->state.location,
+					   browser->priv->state.current_file);
+		}
+		else {
+			_gth_browser_load_file (browser, NULL, FALSE);
+			gth_browser_go_to_with_state (browser,
+						      browser->priv->state.location,
+						      browser->priv->state.selected,
+						      browser->priv->state.vscroll);
+		}
+		break;
+
+	case GTH_BROWSER_PAGE_VIEWER:
+		gth_browser_load_location (browser, browser->priv->state.current_file);
+		break;
+
+	default:
+		break;
+	}
+
+	return TRUE;
+}
diff --git a/gthumb/gth-browser.h b/gthumb/gth-browser.h
index 0a2138b..4e12d30 100644
--- a/gthumb/gth-browser.h
+++ b/gthumb/gth-browser.h
@@ -188,6 +188,8 @@ void             gth_browser_ask_whether_to_save    (GthBrowser       *browser,
 				 	 	     GthBrowserCallback
 				 	 	     	     	       callback,
 				 	 	     gpointer          user_data);
+void             gth_browser_save_state             (GthBrowser       *browser);
+gboolean         gth_browser_restore_state          (GthBrowser       *browser);
 
 /* protected methods */
 
diff --git a/gthumb/gth-file-list.c b/gthumb/gth-file-list.c
index a8889c2..847705d 100644
--- a/gthumb/gth-file-list.c
+++ b/gthumb/gth-file-list.c
@@ -55,7 +55,8 @@ typedef enum {
 	GTH_FILE_LIST_OP_TYPE_SET_SORT_FUNC,
 	GTH_FILE_LIST_OP_TYPE_ENABLE_THUMBS,
 	GTH_FILE_LIST_OP_TYPE_RENAME_FILE,
-	GTH_FILE_LIST_OP_TYPE_MAKE_FILE_VISIBLE
+	GTH_FILE_LIST_OP_TYPE_MAKE_FILE_VISIBLE,
+	GTH_FILE_LIST_OP_TYPE_RESTORE_STATE
 } GthFileListOpType;
 
 
@@ -72,6 +73,8 @@ typedef struct {
 	GFile               *file;
 	GthFileData         *file_data;
 	int                  position;
+	GList               *selected;
+	double               vscroll;
 } GthFileListOp;
 
 
@@ -198,6 +201,9 @@ gth_file_list_op_free (GthFileListOp *op)
 	case GTH_FILE_LIST_OP_TYPE_MAKE_FILE_VISIBLE:
 		g_object_unref (op->file);
 		break;
+	case GTH_FILE_LIST_OP_TYPE_RESTORE_STATE:
+		g_list_free_full (op->selected, (GDestroyNotify) gtk_tree_path_free);
+		break;
 	default:
 		break;
 	}
@@ -1321,6 +1327,7 @@ gfl_make_file_visible (GthFileList *file_list,
 
 	pos = gth_file_store_get_pos ((GthFileStore *) gth_file_view_get_model (GTH_FILE_VIEW (file_list->priv->view)), file);
 	if (pos >= 0) {
+		gth_file_selection_unselect_all (GTH_FILE_SELECTION (file_list->priv->view));
 		gth_file_selection_select (GTH_FILE_SELECTION (file_list->priv->view), pos);
 		gth_file_view_set_cursor (GTH_FILE_VIEW (file_list->priv->view), pos);
 	}
@@ -1339,6 +1346,39 @@ gth_file_list_make_file_visible (GthFileList *file_list,
 }
 
 
+static void
+gfl_restore_state (GthFileList *file_list,
+		   GList       *selected,
+		   double       vscroll)
+{
+	GList *scan;
+
+	for (scan = selected; scan; scan = scan->next) {
+		GtkTreePath *path = scan->data;
+		int          pos;
+
+		pos = gtk_tree_path_get_indices (path)[0];
+		gth_file_selection_select (GTH_FILE_SELECTION (file_list->priv->view), pos);
+	}
+
+	gth_file_view_set_vscroll (GTH_FILE_VIEW (file_list->priv->view), vscroll);
+}
+
+
+void
+gth_file_list_restore_state (GthFileList *file_list,
+			     GList       *selected,
+			     double       vscroll)
+{
+	GthFileListOp *op;
+
+	op = gth_file_list_op_new (GTH_FILE_LIST_OP_TYPE_RESTORE_STATE);
+	op->selected = g_list_copy_deep (selected, (GCopyFunc) gtk_tree_path_copy, NULL);
+	op->vscroll = vscroll;
+	_gth_file_list_queue_op (file_list, op);
+}
+
+
 GtkWidget *
 gth_file_list_get_view (GthFileList *file_list)
 {
@@ -1942,6 +1982,9 @@ _gth_file_list_exec_next_op (GthFileList *file_list)
 	case GTH_FILE_LIST_OP_TYPE_MAKE_FILE_VISIBLE:
 		gfl_make_file_visible (file_list, op->file);
 		break;
+	case GTH_FILE_LIST_OP_TYPE_RESTORE_STATE:
+		gfl_restore_state (file_list, op->selected, op->vscroll);
+		break;
 	default:
 		exec_next_op = FALSE;
 		break;
diff --git a/gthumb/gth-file-list.h b/gthumb/gth-file-list.h
index 4519612..18c68af 100644
--- a/gthumb/gth-file-list.h
+++ b/gthumb/gth-file-list.h
@@ -105,6 +105,9 @@ void              gth_file_list_set_caption       (GthFileList          *file_li
 					           const char           *attribute);
 void              gth_file_list_make_file_visible (GthFileList          *file_list,
 						   GFile                *file);
+void              gth_file_list_restore_state     (GthFileList          *file_list,
+						   GList                *selected,
+						   double                vscroll);
 GtkWidget *       gth_file_list_get_view          (GthFileList          *file_list);
 GtkWidget *       gth_file_list_get_empty_view    (GthFileList          *file_list);
 GtkAdjustment *   gth_file_list_get_vadjustment   (GthFileList          *file_list);
diff --git a/gthumb/gth-file-view.c b/gthumb/gth-file-view.c
index 66a644a..536887e 100644
--- a/gthumb/gth-file-view.c
+++ b/gthumb/gth-file-view.c
@@ -167,6 +167,14 @@ gth_file_view_scroll_to (GthFileView *self,
 }
 
 
+void
+gth_file_view_set_vscroll (GthFileView *self,
+			   double       vscroll)
+{
+	GTH_FILE_VIEW_GET_INTERFACE (self)->set_vscroll (self, vscroll);
+}
+
+
 GthVisibility
 gth_file_view_get_visibility (GthFileView *self,
 			      int          pos)
diff --git a/gthumb/gth-file-view.h b/gthumb/gth-file-view.h
index f38828f..dd30544 100644
--- a/gthumb/gth-file-view.h
+++ b/gthumb/gth-file-view.h
@@ -65,6 +65,8 @@ struct _GthFileViewInterface {
 	void            (*scroll_to)                     (GthFileView              *self,
 							  int                       pos,
 							  double                    yalign);
+	void            (*set_vscroll)                   (GthFileView              *self,
+							  double                    vscroll);
 	GthVisibility   (*get_visibility)                (GthFileView              *self,
 							  int                       pos);
 	int             (*get_at_position)               (GthFileView              *self,
@@ -108,6 +110,8 @@ gboolean        gth_file_view_get_thumbnail_size (GthFileView             *self)
 void            gth_file_view_scroll_to          (GthFileView             *self,
 						  int                      pos,
 						  double                   yalign);
+void            gth_file_view_set_vscroll        (GthFileView             *self,
+						  double                   vscroll);
 GthVisibility   gth_file_view_get_visibility     (GthFileView             *self,
 						  int                      pos);
 int             gth_file_view_get_at_position    (GthFileView             *self,
diff --git a/gthumb/gth-grid-view.c b/gthumb/gth-grid-view.c
index 7e10ff6..50b7e67 100644
--- a/gthumb/gth-grid-view.c
+++ b/gthumb/gth-grid-view.c
@@ -145,6 +145,7 @@ struct _GthGridViewPrivate {
 	int                    focused_item;
 	int                    first_focused_item;  /* Used to do multiple selection with the keyboard. */
 	guint                  make_focused_visible : 1;
+	double                 initial_vscroll;
 	guint                  needs_relayout : 1;
 	guint                  needs_relayout_after_size_allocate : 1;
 
@@ -521,6 +522,18 @@ gth_grid_view_scroll_to (GthFileView *file_view,
 }
 
 
+
+static void
+gth_grid_view_set_vscroll (GthFileView *file_view,
+			   double       vscroll)
+{
+	GthGridView *self = GTH_GRID_VIEW (file_view);
+
+	self->priv->initial_vscroll = vscroll;
+	gtk_adjustment_set_value (self->priv->vadjustment, vscroll);
+}
+
+
 static GthVisibility
 gth_grid_view_get_visibility (GthFileView *file_view,
 			      int          pos)
@@ -910,6 +923,11 @@ _gth_grid_view_relayout_cb (gpointer data)
 		_gth_grid_view_make_item_fully_visible (self, self->priv->focused_item);
 	}
 
+	if (self->priv->initial_vscroll > 0) {
+		gtk_adjustment_set_value (self->priv->vadjustment, self->priv->initial_vscroll);
+		self->priv->initial_vscroll = 0;
+	}
+
 	return FALSE;
 }
 
@@ -2005,7 +2023,6 @@ gth_grid_view_select (GthFileSelection *selection,
 	case GTK_SELECTION_MULTIPLE:
 		self->priv->select_pending = FALSE;
 
-		_gth_grid_view_unselect_all (self, NULL);
 		_gth_grid_view_set_item_selected_and_emit_signal (self, TRUE, pos);
 		self->priv->last_selected_pos = pos;
 		self->priv->last_selected_item = g_list_nth (self->priv->items, pos)->data;
@@ -3761,6 +3778,7 @@ static void
 gth_grid_view_gth_file_view_interface_init (GthFileViewInterface *iface)
 {
 	iface->scroll_to = gth_grid_view_scroll_to;
+	iface->set_vscroll = gth_grid_view_set_vscroll;
 	iface->get_visibility = gth_grid_view_get_visibility;
 	iface->get_at_position = gth_grid_view_get_at_position;
 	iface->get_first_visible = gth_grid_view_get_first_visible;
@@ -3791,6 +3809,7 @@ gth_grid_view_init (GthGridView *self)
 	self->priv->focused_item = -1;
 	self->priv->first_focused_item = -1;
 	self->priv->make_focused_visible = FALSE;
+	self->priv->initial_vscroll = 0.0;
 	self->priv->needs_relayout = FALSE;
 	self->priv->needs_relayout_after_size_allocate = FALSE;
 	self->priv->layout_timeout = 0;



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