/* * UbuntuOne Nautilus plugin * * Authors: Rodrigo Moya * * Copyright 2009-2010 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include "context-menu.h" #include "location-widget.h" #include "share-dialog.h" typedef struct { UbuntuOneNautilus *uon; gchar *path; GtkWidget *parent; /* Whether to make a file public or private */ gboolean make_public; } MenuCallbackData; static void free_menu_cb_data (gpointer data, GObject *where_the_object_was) { MenuCallbackData *cb_data = (MenuCallbackData *) data; g_free (cb_data->path); g_free (cb_data); } /* Menu callbacks */ static void got_public_meta (SyncdaemonFilesystemInterface *interface, gboolean success, SyncdaemonMetadata *metadata, gpointer user_data) { MenuCallbackData *data = (MenuCallbackData *) user_data; const gchar * share_id, * node_id; SyncdaemonInterface *public; if (!success) { g_warning ("ERROR: getting metadata for public file"); return; } share_id = syncdaemon_metadata_get_share_id (metadata); node_id = syncdaemon_metadata_get_node_id (metadata); public = syncdaemon_daemon_get_publicfiles_interface (data->uon->syncdaemon); if (public != NULL) { syncdaemon_publicfiles_interface_change_public_access (SYNCDAEMON_PUBLICFILES_INTERFACE (public), share_id, node_id, data->make_public); } } static void unsubscribe_folder_cb (NautilusMenuItem *item, gpointer user_data) { SyncdaemonInterface *interface; MenuCallbackData * data = (MenuCallbackData *) user_data; /* Perform the removal of this folder */ interface = syncdaemon_daemon_get_folders_interface (data->uon->syncdaemon); if (interface != NULL) { SyncdaemonFolderInfo *folder_info; folder_info = syncdaemon_folders_interface_get_info (SYNCDAEMON_FOLDERS_INTERFACE (interface), data->path); if (folder_info != NULL) { if (ubuntuone_check_shares_and_public_files (data->uon, folder_info, data->parent)) { syncdaemon_folders_interface_delete (SYNCDAEMON_FOLDERS_INTERFACE (interface), syncdaemon_folder_info_get_volume_id (folder_info)); } g_object_unref (G_OBJECT (folder_info)); } } } static void subscribe_folder_cb (NautilusMenuItem *item, gpointer user_data) { SyncdaemonInterface *interface; MenuCallbackData * data = (MenuCallbackData *) user_data; /* Perform the addition of this folder */ interface = syncdaemon_daemon_get_folders_interface (data->uon->syncdaemon); if (interface != NULL) { /* If there is no user authenticated, make Syncdaemon do so */ if (!syncdaemon_authentication_has_credentials (syncdaemon_daemon_get_authentication (data->uon->syncdaemon))) syncdaemon_daemon_connect (data->uon->syncdaemon); syncdaemon_folders_interface_create (SYNCDAEMON_FOLDERS_INTERFACE (interface), data->path); } } static void copy_public_url_cb (NautilusMenuItem *item, gpointer user_data) { MenuCallbackData * data = (MenuCallbackData *) user_data; gchar * url; url = g_hash_table_lookup (data->uon->public, data->path); gtk_clipboard_set_text (gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), url, strlen (url)); gtk_clipboard_store (gtk_clipboard_get(GDK_SELECTION_CLIPBOARD)); } static void toggle_publicity_cb (NautilusMenuItem * item, gpointer user_data) { SyncdaemonFilesystemInterface *interface; MenuCallbackData * data = (MenuCallbackData *) user_data; interface = (SyncdaemonFilesystemInterface *) syncdaemon_daemon_get_filesystem_interface (data->uon->syncdaemon); if (interface != NULL) { /* we know this will not be a directory (so no need for _and_quick_tree_synced) */ syncdaemon_filesystem_interface_get_metadata_async (interface, data->path, FALSE, (SyncdaemonGotMetadataFunc) got_public_meta, data); } g_hash_table_replace (data->uon->public, g_strdup (data->path), g_strdup (UPDATE_PENDING)); file_watcher_update_path (data->uon->file_watcher, data->path); } static void share_folder_cb (NautilusMenuItem *item, gpointer user_data) { MenuCallbackData * data = (MenuCallbackData *) user_data; GtkWidget * dialog; dialog = share_dialog_new (data->parent, data->uon, data->path); gtk_widget_show (dialog); } static void unshare_folder_cb (NautilusMenuItem *item, gpointer user_data) { MenuCallbackData * data = (MenuCallbackData *) user_data; SyncdaemonSharesInterface *interface; interface = (SyncdaemonSharesInterface *) syncdaemon_daemon_get_shares_interface (data->uon->syncdaemon); if (interface != NULL) syncdaemon_shares_interface_delete (interface, data->path); } static void toggle_location_cb (NautilusMenuItem *item, gpointer user_data) { GConfClient *conf_client; conf_client = gconf_client_get_default (); gconf_client_set_bool (conf_client, EXPANDER_SHOWN_KEY, !ubuntuone_is_location_bar_enabled (), NULL); } gboolean check_share_offer_pending (UbuntuOneNautilus *uon, const gchar *path) { GSList *shares, *l; SyncdaemonInterface *interface; gboolean is_share_offer_pending = FALSE; const gchar *node_id; interface = syncdaemon_daemon_get_shares_interface (uon->syncdaemon); if (SYNCDAEMON_IS_SHARES_INTERFACE (interface)) { shares = syncdaemon_shares_interface_get_shared (SYNCDAEMON_SHARES_INTERFACE (interface)); for (l = shares; l != NULL; l = l->next) { SyncdaemonShareInfo *share_info = SYNCDAEMON_SHARE_INFO (l->data); if (g_strcmp0 (syncdaemon_share_info_get_path (share_info), path) == 0) { node_id = syncdaemon_share_info_get_node_id (share_info); if (node_id == NULL) is_share_offer_pending = TRUE; break; } } g_slist_free (shares); } return is_share_offer_pending; } NautilusMenuItem * context_menu_new (UbuntuOneNautilus *uon, GtkWidget *window, GList *files) { NautilusFileInfo *file; NautilusMenu *submenu; NautilusMenuItem *root_item, *menu_item, *urlitem; gchar *path, *item, *homedir_path, *path_uri; gboolean is_managed, is_root, is_udf, is_public, is_shared, is_pending; gboolean is_shared_to_me, is_inhome, is_dir, is_regular, is_symlink; gboolean is_share_offer_pending; MenuCallbackData *cb_data; is_managed = is_root = is_udf = is_public = is_shared = is_pending = FALSE; is_shared_to_me = is_inhome = is_dir = is_regular = is_symlink = FALSE; is_share_offer_pending = FALSE; if (g_list_length (files) != 1) return NULL; file = NAUTILUS_FILE_INFO (g_list_nth_data (files, 0)); path_uri = nautilus_file_info_get_uri (file); path = g_filename_from_uri (path_uri, NULL, NULL); g_free (path_uri); if (path == NULL) return NULL; if (syncdaemon_daemon_is_folder_enabled (uon->syncdaemon, path, &is_root)) is_managed = TRUE; homedir_path = g_strdup_printf ("%s/", g_get_home_dir()); if (strncmp (path, homedir_path, strlen (homedir_path)) == 0) is_inhome = TRUE; g_free (homedir_path); if ((item = g_hash_table_lookup (uon->udfs, path)) != NULL) { is_udf = TRUE; if (strcmp (item, UPDATE_PENDING) == 0) is_pending = TRUE; } else if ((item = g_hash_table_lookup (uon->public, path)) != NULL) { is_public = TRUE; if (strcmp (item, UPDATE_PENDING) == 0) is_pending = TRUE; } if (ubuntuone_is_folder_shared (uon, path)) { is_shared = TRUE; if (check_share_offer_pending (uon, path)) is_share_offer_pending = TRUE; } if (ubuntuone_is_inside_shares (uon, path)) is_shared_to_me = TRUE; is_dir = nautilus_file_info_is_directory (file); is_regular = nautilus_file_info_get_file_type (file) == G_FILE_TYPE_REGULAR; is_symlink = g_file_test (path, G_FILE_TEST_IS_SYMLINK); cb_data = g_new0 (MenuCallbackData, 1); cb_data->uon = uon; cb_data->parent = window; cb_data->path = g_strdup (path); /* Create the root item */ root_item = nautilus_menu_item_new ("ubuntuone", _("_Ubuntu One"), _("Ubuntu One options"), "ubuntuone"); submenu = nautilus_menu_new (); nautilus_menu_item_set_submenu (root_item, submenu); g_object_weak_ref (G_OBJECT (root_item), (GWeakNotify) free_menu_cb_data, cb_data); /* Share/unshare */ if ((is_managed || is_udf) && !is_root && is_dir && !is_symlink) { menu_item = nautilus_menu_item_new ("ubuntuone-share", _("_Share..."), _("Share this folder on Ubuntu One"), "ubuntuone"); if (is_pending) g_object_set (menu_item, "sensitive", FALSE, NULL); g_signal_connect (menu_item, "activate", G_CALLBACK (share_folder_cb), cb_data); } else { /* the different tooltips will probably do us no good */ if (is_root) { menu_item = nautilus_menu_item_new ("ubuntuone-noshare-root", _("_Share..."), _("Sorry, you can't share the root of a Ubuntu One volume"), "ubuntuone"); } else if (!(is_managed || is_udf)) { menu_item = nautilus_menu_item_new ("ubuntuone-noshare-unmanaged", _("_Share..."), _("Sorry, you can't share folders not managed by Ubuntu One"), "ubuntuone"); } else { menu_item = nautilus_menu_item_new ("ubuntuone-noshare-unmanaged", _("_Share..."), _("Sorry, you can only share folders"), "ubuntuone"); } g_object_set (menu_item, "sensitive", FALSE, NULL); } nautilus_menu_append_item (submenu, menu_item); if ((is_managed && is_shared) && !is_root && is_dir && !is_symlink) { menu_item = nautilus_menu_item_new ("ubuntuone-unshare", _("Stop _Sharing"), _("Stop sharing this folder on Ubuntu One"), "ubuntuone"); if (is_pending || is_share_offer_pending) g_object_set (menu_item, "sensitive", FALSE, NULL); g_signal_connect (menu_item, "activate", G_CALLBACK (unshare_folder_cb), cb_data); nautilus_menu_append_item (submenu, menu_item); } /* UDF logic * * XXX: clean this up and separate the logic out and reuse this * and locationbar somewhere (libsd?) */ menu_item = NULL; if (is_dir && is_inhome && !is_symlink) { /* UDFs could be happening */ if (is_managed) { if (strcmp (path, uon->managed) == 0) { /* the Ubuntu One directory, no UDFs */ menu_item = nautilus_menu_item_new ("ubuntuone-no-disable-u1", _("Stop Synchronizing This _Folder"), _("Sorry, you can't stop synchronizing ~/Ubuntu One"), "ubuntuone"); g_object_set (menu_item, "sensitive", FALSE, NULL); } else if (is_root) { /* the root of a UDF: disabling possible */ menu_item = nautilus_menu_item_new ("ubuntuone-disable-udf", _("Stop Synchronizing This _Folder"), _("Stop synchronizing this folder with Ubuntu One"), "ubuntuone"); g_signal_connect (menu_item, "activate", G_CALLBACK (unsubscribe_folder_cb), cb_data); } } else { /* unmanaged */ menu_item = nautilus_menu_item_new ("ubuntuone-enable-udf", _("Synchronize This _Folder"), _("Start synchronizing this folder with Ubuntu One"), "ubuntuone"); g_signal_connect (menu_item, "activate", G_CALLBACK (subscribe_folder_cb), cb_data); } } else { if (is_dir) { menu_item = nautilus_menu_item_new ("ubuntuone-no-disable-u1", _("Synchronize This _Folder"), _("Sorry, you can only synchronize folders within your home folder"), "ubuntuone"); } else { menu_item = nautilus_menu_item_new ("ubuntuone-no-disable-u1", _("Synchronize This _Folder"), _("Sorry, you can only synchronize folders"), "ubuntuone"); } g_object_set (menu_item, "sensitive", FALSE, NULL); } if (!menu_item) { menu_item = nautilus_menu_item_new ("ubuntuone-no-udf-operation-possible", _("Synchronize This _Folder"), _("Synchronization not possible for this folder"), "ubuntuone"); g_object_set (menu_item, "sensitive", FALSE, NULL); } nautilus_menu_append_item (submenu, menu_item); /* public files */ menu_item = urlitem = NULL; if (!is_shared_to_me && is_managed && is_regular && !is_symlink) { if (is_public) { urlitem = nautilus_menu_item_new ("ubuntuone-geturl", _("Copy Web _Link"), _("Copy the Ubuntu One public URL for this file to the clipboard."), "ubuntuone"); if (is_pending) g_object_set (urlitem, "sensitive", FALSE, NULL); g_signal_connect (urlitem, "activate", G_CALLBACK (copy_public_url_cb), cb_data); menu_item = nautilus_menu_item_new ("ubuntuone-unpublish", _("Stop _Publishing"), _("No longer share this file with everyone via Ubuntu One."), "ubuntuone"); if (is_pending) g_object_set (menu_item, "sensitive", FALSE, NULL); cb_data->make_public = FALSE; } else { menu_item = nautilus_menu_item_new ("ubuntuone-publish", _("_Publish"), _("Make this file available to anyone via Ubuntu One."), "ubuntuone"); cb_data->make_public = TRUE; } g_signal_connect (menu_item, "activate", G_CALLBACK (toggle_publicity_cb), cb_data); } if (!urlitem) { urlitem = nautilus_menu_item_new ("ubuntuone-geturl", _("Copy Web _Link"), _("Sorry, no public URL for this file via Ubuntu One."), "ubuntuone"); g_object_set (urlitem, "sensitive", FALSE, NULL); } if (!menu_item) { menu_item = nautilus_menu_item_new ("ubuntuone-publish", _("_Publish"), _("Sorry, unable to publish via Ubuntu One."), "ubuntuone"); g_object_set (menu_item, "sensitive", FALSE, NULL); } nautilus_menu_append_item (submenu, menu_item); nautilus_menu_append_item (submenu, urlitem); /* location bar enable/disable */ if (ubuntuone_is_location_bar_enabled ()) { menu_item = nautilus_menu_item_new ("ubuntuone-location-hide", _("Hide _Ribbon"), _("Do not show the Ubuntu One ribbon" " in selected folders"), "ubuntuone"); } else { menu_item = nautilus_menu_item_new ("ubuntuone-location-show", _("Show _Ribbon in Some Folders"), _("Show the Ubuntu One ribbon" " in selected folders"), "ubuntuone"); } g_signal_connect (menu_item, "activate", G_CALLBACK (toggle_location_cb), cb_data); nautilus_menu_append_item (submenu, menu_item); g_free (path); return root_item; }