/* * ubuntuone-nautilus.c - Nautilus extensions for Ubuntu One * * Authors: Tim Cole * Rodney Dawes * 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 #include #include #include #include #include "ubuntuone-nautilus.h" #include "context-menu.h" #include "location-widget.h" /* We need to do this explicitly because older versions of nautilus * don't seem to do it for us */ #include #include #include #include #include /* The header is generated from ubuntuone-marshallers.list */ #include "ubuntuone-marshallers.h" static void ubuntuone_nautilus_finalize (GObject *object); static void ubuntuone_nautilus_register_type (GTypeModule *module); /* DBus signal and async method call handlers */ static void ubuntuone_nautilus_daemon_ready (SyncdaemonDaemon *daemon, gpointer user_data); static GObjectClass *parent_class = NULL; /* Update file info provider */ static NautilusOperationResult ubuntuone_nautilus_update_file_info (NautilusInfoProvider *provider, NautilusFileInfo *file, GClosure *update_complete, NautilusOperationHandle **handle) { UbuntuOneNautilus *uon = UBUNTUONE_NAUTILUS (provider); /* If syncdaemon is not ready, do nothing */ if (!syncdaemon_daemon_is_ready (uon->syncdaemon)) return NAUTILUS_OPERATION_COMPLETE; file_watcher_add_file (uon->file_watcher, file); return NAUTILUS_OPERATION_COMPLETE; } static void ubuntuone_nautilus_info_provider_iface_init (NautilusInfoProviderIface * iface) { iface->update_file_info = ubuntuone_nautilus_update_file_info; } /* LocationWidget provider */ static GtkWidget * ubuntuone_nautilus_get_location_widget (NautilusLocationWidgetProvider * provider, const char * uri, GtkWidget * parent) { UbuntuOneNautilus * uon; gchar *path; GtkWidget *location; /* if the bar is disabled, do nothing */ if (!ubuntuone_is_location_bar_enabled ()) return NULL; uon = UBUNTUONE_NAUTILUS (provider); /* If syncdaemon is not ready, do nothing */ if (!syncdaemon_daemon_is_ready (uon->syncdaemon)) return NULL; path = g_filename_from_uri (uri, NULL, NULL); if (!path) return NULL; location = location_widget_new (uon, path); g_free (path); return location; } static void ubuntuone_nautilus_bar_provider_iface_init (NautilusLocationWidgetProviderIface * iface) { iface->get_widget = ubuntuone_nautilus_get_location_widget; } /* Menu provider */ static GList * ubuntuone_nautilus_get_menu_items (NautilusMenuProvider * provider, GtkWidget * window, GList * files) { UbuntuOneNautilus * uon; GList *items = NULL; NautilusMenuItem *root_item; uon = UBUNTUONE_NAUTILUS (provider); /* If syncdaemon is not ready, do nothing */ if (!syncdaemon_daemon_is_ready (uon->syncdaemon)) return NULL; root_item = context_menu_new (uon, window, files); if (root_item != NULL) items = g_list_append (items, root_item); return items; } static GList * ubuntuone_nautilus_get_bg_menu_items (NautilusMenuProvider * provider, GtkWidget * window, NautilusFileInfo * folder) { GList * files = NULL; GList * items = NULL; files = g_list_prepend (files, folder); items = ubuntuone_nautilus_get_menu_items (provider, window, files); files = g_list_remove (files, folder); g_list_free (files); return items; } static void ubuntuone_nautilus_menu_provider_iface_init (NautilusMenuProviderIface * iface) { iface->get_file_items = ubuntuone_nautilus_get_menu_items; iface->get_background_items = ubuntuone_nautilus_get_bg_menu_items; } /* GType and nautilus module stuff */ static GType un_type = 0; static void ubuntuone_nautilus_instance_init (UbuntuOneNautilus * uon) { uon->connected = FALSE; uon->udfs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); uon->public = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); uon->syncdaemon = syncdaemon_daemon_new (); g_signal_connect (G_OBJECT (uon->syncdaemon), "ready", G_CALLBACK (ubuntuone_nautilus_daemon_ready), uon); /* Create a FileWatcher object to watch files we know about from Nautilus */ uon->file_watcher = file_watcher_new (uon); /* Default to ~/Ubuntu One for now, as it's all we really support */ uon->managed = g_build_filename (g_get_home_dir (), "Ubuntu One", G_DIR_SEPARATOR_S, NULL); uon->gotroot = FALSE; uon->gotudfs = FALSE; } static void ubuntuone_nautilus_class_init (UbuntuOneNautilusClass * klass) { parent_class = g_type_class_peek_parent (klass); G_OBJECT_CLASS(klass)->finalize = ubuntuone_nautilus_finalize; } static void ubuntuone_nautilus_finalize (GObject *object) { UbuntuOneNautilus * uon = UBUNTUONE_NAUTILUS(object); if (uon->file_watcher != NULL) g_object_unref (G_OBJECT (uon->file_watcher)); if (uon->syncdaemon) g_object_unref (uon->syncdaemon); g_hash_table_destroy (uon->udfs); uon->udfs = NULL; g_hash_table_destroy (uon->public); uon->public = NULL; } GType ubuntuone_nautilus_get_type (void) { return un_type; } static void ubuntuone_nautilus_register_type (GTypeModule * module) { static const GTypeInfo info = { sizeof (UbuntuOneNautilusClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) ubuntuone_nautilus_class_init, NULL, NULL, sizeof (UbuntuOneNautilus), 0, (GInstanceInitFunc) ubuntuone_nautilus_instance_init, }; static const GInterfaceInfo info_provider_iface_info = { (GInterfaceInitFunc) ubuntuone_nautilus_info_provider_iface_init, NULL, NULL }; static const GInterfaceInfo bar_provider_iface_info = { (GInterfaceInitFunc) ubuntuone_nautilus_bar_provider_iface_init, NULL, NULL }; static const GInterfaceInfo menu_provider_iface_info = { (GInterfaceInitFunc) ubuntuone_nautilus_menu_provider_iface_init, NULL, NULL }; un_type = g_type_module_register_type (module, G_TYPE_OBJECT, "UbuntuOneNautilus", &info, 0); g_type_module_add_interface (module, un_type, NAUTILUS_TYPE_INFO_PROVIDER, &info_provider_iface_info); g_type_module_add_interface (module, un_type, NAUTILUS_TYPE_LOCATION_WIDGET_PROVIDER, &bar_provider_iface_info); /* XXX Need to sign a request via DBus */ g_type_module_add_interface (module, un_type, NAUTILUS_TYPE_MENU_PROVIDER, &menu_provider_iface_info); } /* DBus signal handlers and async method call handlers */ static void ubuntuone_nautilus_daemon_ready (SyncdaemonDaemon *daemon, gpointer user_data) { UbuntuOneNautilus * uon = UBUNTUONE_NAUTILUS (user_data); gboolean is_online = FALSE; SyncdaemonInterface *interface; interface = syncdaemon_daemon_get_status_interface (daemon); if (interface != NULL) { SyncdaemonStatusInfo *status_info; status_info = syncdaemon_status_interface_get_current_status (SYNCDAEMON_STATUS_INTERFACE (interface)); is_online = syncdaemon_status_info_get_online (status_info); } /* Get the root when we get a status change signal, if we haven't yet */ if (!uon->gotroot) { uon->managed = g_build_filename (syncdaemon_daemon_get_root_dir (uon->syncdaemon), G_DIR_SEPARATOR_S, NULL); if (uon->managed != NULL) uon->gotroot = TRUE; } /* Get the list of UDFs if we haven't already */ if (!uon->gotudfs) { SyncdaemonInterface *interface; interface = syncdaemon_daemon_get_folders_interface (uon->syncdaemon); if (interface != NULL) { GSList *folders, *l; folders = syncdaemon_folders_interface_get_folders (SYNCDAEMON_FOLDERS_INTERFACE (interface)); for (l = folders; l != NULL; l = l->next) { const gchar *path, *id; gboolean subscribed; SyncdaemonFolderInfo *folder_info = SYNCDAEMON_FOLDER_INFO (l->data); path = syncdaemon_folder_info_get_path (folder_info); id = syncdaemon_folder_info_get_volume_id (folder_info); subscribed = syncdaemon_folder_info_get_subscribed (folder_info); if (subscribed) { g_hash_table_insert (uon->udfs, g_strdup (path), g_strdup (id)); uon->gotudfs = TRUE; file_watcher_update_path (uon->file_watcher, path); } } g_slist_free (folders); } } /* Get the list of public files if we haven't already */ if (is_online) { SyncdaemonInterface *public; public = syncdaemon_daemon_get_publicfiles_interface (uon->syncdaemon); if (public != NULL) { GSList *files_list; /* We just call it here so that libsyncdaemon caches it, but we discard the list, as we don't need it yet */ files_list = syncdaemon_publicfiles_interface_get_public_files (SYNCDAEMON_PUBLICFILES_INTERFACE (public)); g_slist_free (files_list); } } } /* Required Nautilus module handling methods */ void nautilus_module_initialize (GTypeModule *module) { #ifdef ENABLE_NLS bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); #endif ubuntuone_nautilus_register_type (module); } void nautilus_module_shutdown (void) { } void nautilus_module_list_types (const GType **types, int *num_types) { static GType type_list[1]; type_list[0] = UBUNTUONE_TYPE_NAUTILUS; *types = type_list; *num_types = 1; }