[nautilus] Add locations for open windows to the destination selection dialog



commit 338091bd0f28345b822c1d55055673d5ff963bc4
Author: William Jon McCann <jmccann redhat com>
Date:   Mon Jul 9 09:35:50 2012 -0400

    Add locations for open windows to the destination selection dialog
    
    These locations are identified as interesting by the fact that they
    are in use and it makes sense to offer them as quick options for
    explicit copies and moves.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=679580

 src/nautilus-view.c                |  235 ++++++++++++++++++++++++++++++++++--
 src/nautilus-window-manage-views.c |   21 +++-
 src/nautilus-window-slot.c         |   11 ++
 src/nautilus-window.c              |   29 +++++
 src/nautilus-window.h              |    1 +
 5 files changed, 287 insertions(+), 10 deletions(-)
---
diff --git a/src/nautilus-view.c b/src/nautilus-view.c
index 6679bc8..9142983 100644
--- a/src/nautilus-view.c
+++ b/src/nautilus-view.c
@@ -5727,12 +5727,208 @@ create_popup_menu (NautilusView *view, const char *popup_path)
 }
 
 typedef struct _CopyCallbackData {
-	NautilusView *view;
-	GList        *selection;
-	gboolean      is_move;
+	NautilusView   *view;
+	GtkFileChooser *chooser;
+	GHashTable     *locations;
+	GList          *selection;
+	gboolean        is_move;
 } CopyCallbackData;
 
 static void
+add_bookmark_for_uri (CopyCallbackData *data,
+		      const char       *uri)
+{
+	GError *error = NULL;
+	int count;
+
+	count = GPOINTER_TO_INT (g_hash_table_lookup (data->locations, uri));
+	if (count == 0) {
+		gtk_file_chooser_add_shortcut_folder_uri (data->chooser,
+							  uri,
+							  &error);
+		if (error != NULL) {
+			DEBUG ("Unable to add location '%s' to file selector: %s", uri, error->message);
+			g_clear_error (&error);
+		}
+	}
+	g_hash_table_replace (data->locations, g_strdup (uri), GINT_TO_POINTER (count + 1));
+}
+
+static void
+remove_bookmark_for_uri (CopyCallbackData *data,
+			 const char       *uri)
+{
+	GError *error = NULL;
+	int count;
+
+	count = GPOINTER_TO_INT (g_hash_table_lookup (data->locations, uri));
+	if (count == 1) {
+		gtk_file_chooser_remove_shortcut_folder_uri (data->chooser,
+							     uri,
+							     &error);
+		if (error != NULL) {
+			DEBUG ("Unable to remove location '%s' to file selector: %s", uri, error->message);
+			g_clear_error (&error);
+		}
+		g_hash_table_remove (data->locations, uri);
+	} else {
+		g_hash_table_replace (data->locations, g_strdup (uri), GINT_TO_POINTER (count - 1));
+	}
+}
+
+static void
+add_bookmarks_for_window_slot (CopyCallbackData   *data,
+			       NautilusWindowSlot *slot)
+{
+	char *uri;
+
+	uri = nautilus_window_slot_get_location_uri (slot);
+	if (uri != NULL) {
+		add_bookmark_for_uri (data, uri);
+	}
+	g_free (uri);
+}
+
+static void
+remove_bookmarks_for_window_slot (CopyCallbackData   *data,
+				  NautilusWindowSlot *slot)
+{
+	char *uri;
+
+	uri = nautilus_window_slot_get_location_uri (slot);
+	if (uri != NULL) {
+		remove_bookmark_for_uri (data, uri);
+	}
+	g_free (uri);
+}
+
+static void
+on_slot_location_changed (NautilusWindowSlot *slot,
+			  const char         *from,
+			  const char         *to,
+			  CopyCallbackData   *data)
+{
+	if (from != NULL) {
+		remove_bookmark_for_uri (data, from);
+	}
+
+	if (to != NULL) {
+		add_bookmark_for_uri (data, to);
+	}
+}
+
+static void
+on_slot_added (NautilusWindow     *window,
+	       NautilusWindowSlot *slot,
+	       CopyCallbackData   *data)
+{
+	add_bookmarks_for_window_slot (data, slot);
+	g_signal_connect (slot, "location-changed", G_CALLBACK (on_slot_location_changed), data);
+}
+
+static void
+on_slot_removed (NautilusWindow     *window,
+		 NautilusWindowSlot *slot,
+		 CopyCallbackData   *data)
+{
+	remove_bookmarks_for_window_slot (data, slot);
+	g_signal_handlers_disconnect_by_func (slot,
+					      G_CALLBACK (on_slot_location_changed),
+					      data);
+}
+
+static void
+add_bookmarks_for_window (CopyCallbackData *data,
+			  NautilusWindow   *window)
+{
+	GList *s;
+	GList *slots;
+
+	slots = nautilus_window_get_slots (window);
+	for (s = slots; s != NULL; s = s->next) {
+		NautilusWindowSlot *slot = s->data;
+		add_bookmarks_for_window_slot (data, slot);
+		g_signal_connect (slot, "location-changed", G_CALLBACK (on_slot_location_changed), data);
+	}
+	g_signal_connect (window, "slot-added", G_CALLBACK (on_slot_added), data);
+	g_signal_connect (window, "slot-removed", G_CALLBACK (on_slot_removed), data);
+}
+
+static void
+remove_bookmarks_for_window (CopyCallbackData *data,
+			     NautilusWindow   *window)
+{
+	GList *s;
+	GList *slots;
+
+	slots = nautilus_window_get_slots (window);
+	for (s = slots; s != NULL; s = s->next) {
+		NautilusWindowSlot *slot = s->data;
+		remove_bookmarks_for_window_slot (data, slot);
+		g_signal_handlers_disconnect_by_func (slot,
+						      G_CALLBACK (on_slot_location_changed),
+						      data);
+	}
+	g_signal_handlers_disconnect_by_func (window,
+					      G_CALLBACK (on_slot_added),
+					      data);
+	g_signal_handlers_disconnect_by_func (window,
+					      G_CALLBACK (on_slot_removed),
+					      data);
+}
+
+static void
+on_app_window_added (GtkApplication   *application,
+		     GtkWindow        *window,
+		     CopyCallbackData *data)
+{
+	add_bookmarks_for_window (data, NAUTILUS_WINDOW (window));
+}
+
+static void
+on_app_window_removed (GtkApplication   *application,
+		       GtkWindow        *window,
+		       CopyCallbackData *data)
+{
+	remove_bookmarks_for_window (data, NAUTILUS_WINDOW (window));
+}
+
+static void
+copy_data_free (CopyCallbackData *data)
+{
+	GtkApplication *application;
+	GList *windows;
+	GList *w;
+
+	application = gtk_window_get_application (GTK_WINDOW (data->view->details->window));
+	g_signal_handlers_disconnect_by_func (application,
+					      G_CALLBACK (on_app_window_added),
+					      data);
+	g_signal_handlers_disconnect_by_func (application,
+					      G_CALLBACK (on_app_window_removed),
+					      data);
+
+	windows = gtk_application_get_windows (application);
+	for (w = windows; w != NULL; w = w->next) {
+		NautilusWindow *window = w->data;
+		GList *slots;
+		GList *s;
+
+		slots = nautilus_window_get_slots (window);
+		for (s = slots; s != NULL; s = s->next) {
+			NautilusWindowSlot *slot = s->data;
+			g_signal_handlers_disconnect_by_func (slot, G_CALLBACK (on_slot_location_changed), data);
+		}
+		g_signal_handlers_disconnect_by_func (window, G_CALLBACK (on_slot_added), data);
+		g_signal_handlers_disconnect_by_func (window, G_CALLBACK (on_slot_removed), data);
+	}
+
+	nautilus_file_list_free (data->selection);
+	g_hash_table_destroy (data->locations);
+	g_free (data);
+}
+
+static void
 on_destination_dialog_response (GtkDialog *dialog,
 				gint       response_id,
 				gpointer   user_data)
@@ -5760,10 +5956,26 @@ on_destination_dialog_response (GtkDialog *dialog,
 		g_free (target_uri);
 	}
 
-	nautilus_file_list_free (copy_data->selection);
-	g_free (copy_data);
+	copy_data_free (copy_data);
 	gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
+static void
+add_window_location_bookmarks (CopyCallbackData *data)
+{
+	GtkApplication *application;
+	GList *windows;
+	GList *w;
 
+	application = gtk_window_get_application (GTK_WINDOW (data->view->details->window));
+	windows = gtk_application_get_windows (application);
+	g_signal_connect (application, "window-added", G_CALLBACK (on_app_window_added), data);
+	g_signal_connect (application, "window-removed", G_CALLBACK (on_app_window_removed), data);
+
+	for (w = windows; w != NULL; w = w->next) {
+		NautilusWindow *window = w->data;
+		add_bookmarks_for_window (data, window);
+	}
 }
 
 static void
@@ -5786,14 +5998,19 @@ copy_or_move_selection (NautilusView *view,
 	gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
 	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
 
-	uri = nautilus_directory_get_uri (view->details->model);
-	gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), uri);
-	g_free (uri);
-
 	copy_data = g_new0 (CopyCallbackData, 1);
 	copy_data->view = view;
 	copy_data->selection = selection;
 	copy_data->is_move = is_move;
+	copy_data->chooser = GTK_FILE_CHOOSER (dialog);
+	copy_data->locations = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+	add_window_location_bookmarks (copy_data);
+
+	uri = nautilus_directory_get_uri (view->details->model);
+	gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), uri);
+	g_free (uri);
+
 	g_signal_connect (dialog, "response",
 			  G_CALLBACK (on_destination_dialog_response),
 			  copy_data);
diff --git a/src/nautilus-window-manage-views.c b/src/nautilus-window-manage-views.c
index bbcf1c1..c41a205 100644
--- a/src/nautilus-window-manage-views.c
+++ b/src/nautilus-window-manage-views.c
@@ -1082,6 +1082,23 @@ nautilus_window_emit_location_change (NautilusWindow *window,
 	g_free (uri);
 }
 
+static void
+nautilus_window_slot_emit_location_change (NautilusWindowSlot *slot,
+					   GFile *from,
+					   GFile *to)
+{
+	char *from_uri = NULL;
+	char *to_uri = NULL;
+
+	if (from != NULL)
+		from_uri = g_file_get_uri (from);
+	if (to != NULL)
+		to_uri = g_file_get_uri (to);
+	g_signal_emit_by_name (slot, "location-changed", from_uri, to_uri);
+	g_free (to_uri);
+	g_free (from_uri);
+}
+
 /* reports location change to window's "loading-uri" clients, i.e.
  * sidebar panels [used when switching tabs]. It will emit the pending
  * location, or the existing location if none is pending.
@@ -1344,7 +1361,9 @@ update_for_new_location (NautilusWindowSlot *slot)
 	location_really_changed =
 		slot->location == NULL ||
 		!g_file_equal (slot->location, new_location);
-		
+
+	nautilus_window_slot_emit_location_change (slot, slot->location, new_location);
+
         /* Set the new location. */
 	g_clear_object (&slot->location);
 	slot->location = new_location;
diff --git a/src/nautilus-window-slot.c b/src/nautilus-window-slot.c
index fcd5365..e815b55 100644
--- a/src/nautilus-window-slot.c
+++ b/src/nautilus-window-slot.c
@@ -45,6 +45,7 @@ G_DEFINE_TYPE (NautilusWindowSlot, nautilus_window_slot, GTK_TYPE_BOX);
 enum {
 	ACTIVE,
 	INACTIVE,
+	LOCATION_CHANGED,
 	LAST_SIGNAL
 };
 
@@ -302,6 +303,16 @@ nautilus_window_slot_class_init (NautilusWindowSlotClass *klass)
 			      NULL, NULL,
 			      g_cclosure_marshal_VOID__VOID,
 			      G_TYPE_NONE, 0);
+	signals[LOCATION_CHANGED] =
+		g_signal_new ("location-changed",
+			      G_TYPE_FROM_CLASS (klass),
+			      G_SIGNAL_RUN_LAST,
+			      0,
+			      NULL, NULL,
+			      g_cclosure_marshal_generic,
+			      G_TYPE_NONE, 2,
+			      G_TYPE_STRING,
+			      G_TYPE_STRING);
 }
 
 GFile *
diff --git a/src/nautilus-window.c b/src/nautilus-window.c
index c91db78..9cf6e36 100644
--- a/src/nautilus-window.c
+++ b/src/nautilus-window.c
@@ -104,6 +104,8 @@ enum {
 	PROMPT_FOR_LOCATION,
 	LOADING_URI,
 	HIDDEN_FILES_MODE_CHANGED,
+	SLOT_ADDED,
+	SLOT_REMOVED,
 	LAST_SIGNAL
 };
 
@@ -459,6 +461,8 @@ close_slot (NautilusWindow     *window,
 
 	DEBUG ("Closing slot %p", slot);
 
+	g_signal_emit (window, signals[SLOT_REMOVED], 0, slot);
+
 	nautilus_window_manage_views_close_slot (slot);
 
 	notebook = GTK_NOTEBOOK (window->details->notebook);
@@ -503,6 +507,7 @@ nautilus_window_open_slot (NautilusWindow             *window,
 					   window);
 
 	window->details->slots = g_list_append (window->details->slots, slot);
+	g_signal_emit (window, signals[SLOT_ADDED], 0, slot);
 
 	return slot;
 }
@@ -2152,6 +2157,14 @@ nautilus_window_get_active_slot (NautilusWindow *window)
 	return window->details->active_slot;
 }
 
+GList *
+nautilus_window_get_slots (NautilusWindow *window)
+{
+	g_assert (NAUTILUS_IS_WINDOW (window));
+
+	return window->details->slots;
+}
+
 static void
 nautilus_window_reload (NautilusWindow *window)
 {
@@ -2361,6 +2374,22 @@ nautilus_window_class_init (NautilusWindowClass *class)
 			      g_cclosure_marshal_VOID__STRING,
 			      G_TYPE_NONE, 1,
 			      G_TYPE_STRING);
+	signals[SLOT_ADDED] =
+		g_signal_new ("slot-added",
+			      G_TYPE_FROM_CLASS (class),
+			      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+			      0,
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__OBJECT,
+			      G_TYPE_NONE, 1, NAUTILUS_TYPE_WINDOW_SLOT);
+	signals[SLOT_REMOVED] =
+		g_signal_new ("slot-removed",
+			      G_TYPE_FROM_CLASS (class),
+			      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+			      0,
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__OBJECT,
+			      G_TYPE_NONE, 1, NAUTILUS_TYPE_WINDOW_SLOT);
 
 	binding_set = gtk_binding_set_by_class (class);
 	gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, 0,
diff --git a/src/nautilus-window.h b/src/nautilus-window.h
index 1f022e8..2578cc8 100644
--- a/src/nautilus-window.h
+++ b/src/nautilus-window.h
@@ -131,6 +131,7 @@ void                 nautilus_window_report_load_underway  (NautilusWindow *wind
 void                 nautilus_window_view_visible          (NautilusWindow *window,
                                                             NautilusView *view);
 NautilusWindowSlot * nautilus_window_get_active_slot       (NautilusWindow *window);
+GList *              nautilus_window_get_slots             (NautilusWindow *window);
 NautilusWindowSlot * nautilus_window_open_slot             (NautilusWindow *window,
                                                             NautilusWindowOpenSlotFlags flags);
 void                 nautilus_window_slot_close            (NautilusWindow *window,



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