diff options
author | William Jon McCann <jmccann@redhat.com> | 2012-07-09 09:35:50 -0400 |
---|---|---|
committer | William Jon McCann <jmccann@redhat.com> | 2012-07-10 10:30:23 -0400 |
commit | 338091bd0f28345b822c1d55055673d5ff963bc4 (patch) | |
tree | 589bf7cb8d2904e5efa3d7789f0b6c7f586a56e3 /src | |
parent | 5c06328bc1f06a306dc63eca712b46af7018344e (diff) | |
download | nautilus-338091bd0f28345b822c1d55055673d5ff963bc4.tar.gz |
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
Diffstat (limited to 'src')
-rw-r--r-- | src/nautilus-view.c | 235 | ||||
-rw-r--r-- | src/nautilus-window-manage-views.c | 21 | ||||
-rw-r--r-- | src/nautilus-window-slot.c | 11 | ||||
-rw-r--r-- | src/nautilus-window.c | 29 | ||||
-rw-r--r-- | 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 6679bc84b..9142983d5 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 bbcf1c149..c41a2059d 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 fcd536542..e815b559b 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 c91db78ad..9cf6e3647 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 1f022e835..2578cc820 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, |