From e4c70bb691b8aba359c9acc737e0331ddde7deda Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Fri, 7 Dec 2012 13:42:39 -0600 Subject: [PATCH] New machinery to add application-specific shortcuts The file chooser needs them for gtk_file_chooser_add_shortcut_folder() and friends. Signed-off-by: Federico Mena Quintero --- gtk/gtkplacessidebar.c | 146 +++++++++++++++++++++++++++++++++++++++++ gtk/gtkplacessidebar.h | 4 ++ 2 files changed, 150 insertions(+) diff --git a/gtk/gtkplacessidebar.c b/gtk/gtkplacessidebar.c index 79f86b8bc1..874da64d84 100644 --- a/gtk/gtkplacessidebar.c +++ b/gtk/gtkplacessidebar.c @@ -132,6 +132,8 @@ struct _GtkPlacesSidebar { gboolean mounting; GtkPlacesOpenMode go_to_after_mount_open_mode; + GSList *shortcuts; + GDBusProxy *hostnamed_proxy; char *hostname; @@ -694,6 +696,55 @@ get_desktop_directory_uri (void) } } +static void +add_application_shortcuts (GtkPlacesSidebar *sidebar) +{ + GSList *l; + + for (l = sidebar->shortcuts; l; l = l->next) { + GFile *file; + GFileInfo *info; + + file = G_FILE (l->data); + + /* FIXME: we are getting file info synchronously. We may want to do it async at some point. */ + info = g_file_query_info (file, + "standard::display-name,standard::icon", + G_FILE_QUERY_INFO_NONE, + NULL, + NULL); /* NULL-GError */ + + if (info) { + char *uri; + char *tooltip; + const char *name; + GIcon *icon; + + name = g_file_info_get_display_name (info); + + /* FIXME: in commit 0ed400b9c1692e42498bff3c10780073ec137f63, nautilus added the ability + * to get a symbolic icon for bookmarks. We don't have that machinery. Should we + * just copy that code? + */ + icon = g_file_info_get_icon (info); + + uri = g_file_get_uri (file); + tooltip = g_file_get_parse_name (file); + + add_place (sidebar, PLACES_BUILT_IN, + SECTION_COMPUTER, + name, icon, uri, + NULL, NULL, NULL, 0, + tooltip); + + g_free (uri); + g_free (tooltip); + + g_object_unref (info); + } + } +} + static void update_places (GtkPlacesSidebar *sidebar) { @@ -837,6 +888,9 @@ update_places (GtkPlacesSidebar *sidebar) g_object_unref (icon); } + /* Application-side shortcuts */ + add_application_shortcuts (sidebar); + /* go through all connected drives */ drives = g_volume_monitor_get_connected_drives (volume_monitor); @@ -3439,6 +3493,8 @@ gtk_places_sidebar_init (GtkPlacesSidebar *sidebar) sidebar->bookmarks_manager = _gtk_bookmarks_manager_new (bookmarks_changed_cb, sidebar); + sidebar->shortcuts = NULL; + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sidebar), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); @@ -3642,6 +3698,9 @@ gtk_places_sidebar_dispose (GObject *object) g_clear_object (&sidebar->store); + g_slist_free_full (sidebar->shortcuts, g_object_unref); + sidebar->shortcuts = NULL; + if (sidebar->volume_monitor != NULL) { g_signal_handlers_disconnect_by_func (sidebar->volume_monitor, volume_added_callback, sidebar); @@ -4021,3 +4080,90 @@ gtk_places_sidebar_set_accept_uri_drops (GtkPlacesSidebar *sidebar, gboolean acc sidebar->accept_uri_drops = !!accept_uri_drops; } + +static GSList * +find_shortcut_link (GtkPlacesSidebar *sidebar, GFile *location) +{ + GSList *l; + + for (l = sidebar->shortcuts; l; l = l->next) { + GFile *shortcut; + + shortcut = G_FILE (l->data); + if (g_file_equal (shortcut, location)) + return l; + } + + return NULL; +} + +gboolean +gtk_places_sidebar_add_shortcut (GtkPlacesSidebar *sidebar, GFile *location, GError **error) +{ + g_return_val_if_fail (GTK_IS_PLACES_SIDEBAR (sidebar), FALSE); + g_return_val_if_fail (G_IS_FILE (location), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (find_shortcut_link (sidebar, location)) { + char *uri; + + uri = g_file_get_uri (location); + g_set_error (error, + GTK_FILE_CHOOSER_ERROR, + GTK_FILE_CHOOSER_ERROR_ALREADY_EXISTS, + _("Shortcut %s already exists"), + uri); + g_free (uri); + + return FALSE; + } + + g_object_ref (location); + sidebar->shortcuts = g_slist_append (sidebar->shortcuts, location); + + update_places (sidebar); + + return TRUE; +} + +gboolean +gtk_places_sidebar_remove_shortcut (GtkPlacesSidebar *sidebar, GFile *location, GError **error) +{ + GSList *link; + GFile *shortcut; + + g_return_val_if_fail (GTK_IS_PLACES_SIDEBAR (sidebar), FALSE); + g_return_val_if_fail (G_IS_FILE (location), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + link = find_shortcut_link (sidebar, location); + if (!link) { + char *uri; + + uri = g_file_get_uri (location); + g_set_error (error, + GTK_FILE_CHOOSER_ERROR, + GTK_FILE_CHOOSER_ERROR_NONEXISTENT, + _("Shortcut %s does not exist"), + uri); + g_free (uri); + + return FALSE; + } + + shortcut = G_FILE (link->data); + g_object_unref (shortcut); + + sidebar->shortcuts = g_slist_delete_link (sidebar->shortcuts, link); + update_places (sidebar); + + return TRUE; +} + +GSList * +gtk_places_sidebar_list_shortcuts (GtkPlacesSidebar *sidebar) +{ + g_return_val_if_fail (GTK_IS_PLACES_SIDEBAR (sidebar), FALSE); + + return g_slist_copy_deep (sidebar->shortcuts, (GCopyFunc) g_object_ref, NULL); +} diff --git a/gtk/gtkplacessidebar.h b/gtk/gtkplacessidebar.h index 303b3fe0e6..c9eb5da27a 100644 --- a/gtk/gtkplacessidebar.h +++ b/gtk/gtkplacessidebar.h @@ -72,6 +72,10 @@ void gtk_places_sidebar_set_show_cwd (GtkPlacesSidebar *sidebar, gboolean show_c void gtk_places_sidebar_set_accept_uri_drops (GtkPlacesSidebar *sidebar, gboolean accept_uri_drops); +gboolean gtk_places_sidebar_add_shortcut (GtkPlacesSidebar *sidebar, GFile *location, GError **error); +gboolean gtk_places_sidebar_remove_shortcut (GtkPlacesSidebar *sidebar, GFile *location, GError **error); +GSList *gtk_places_sidebar_list_shortcuts (GtkPlacesSidebar *sidebar); + G_END_DECLS #endif /* __GTK_PLACES_SIDEBAR_H__ */