Logo Search packages:      
Sourcecode: ubuntuone-client-gnome version File versions  Download package

ubuntuone-nautilus.c

/*
 * ubuntuone-nautilus.c - Nautilus extensions for Ubuntu One
 *
 * Authors: Tim Cole <tim.cole@canonical.com>
 *          Rodney Dawes <rodney.dawes@canonical.com>
 *          Rodrigo Moya <rodrigo.moya@canonical.com>
 *
 * 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 <http://www.gnu.org/licenses/>.
 *
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <glib/gi18n-lib.h>
#include <libnautilus-extension/nautilus-extension-types.h>
#include <libnautilus-extension/nautilus-file-info.h>
#include <libnautilus-extension/nautilus-info-provider.h>
#include <libnautilus-extension/nautilus-menu-provider.h>
#include <libnautilus-extension/nautilus-location-widget-provider.h>
#include <libsyncdaemon/libsyncdaemon.h>
#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 <gtk/gtk.h>

#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>

/* 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;
}

Generated by  Doxygen 1.6.0   Back to index