Logo Search packages:      
Sourcecode: ubuntuone-client version File versions

ubuntuone-nautilus.c

/*
 * ubuntuone-nautilus.c - Nautilus extensions for Ubuntu One
 *
 * Authors: Tim Cole <tim.cole@canonical.com>
 *          Rodney Dawes <rodney.dawes@canonical.com>
 *
 * Copyright 2009 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 <dbus/dbus-glib.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 <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>

#define UBUNTUONE_TYPE_NAUTILUS  (ubuntuone_nautilus_get_type ())
#define UBUNTUONE_NAUTILUS(o)    (G_TYPE_CHECK_INSTANCE_CAST ((o), UBUNTUONE_TYPE_NAUTILUS, UbuntuOneNautilus))

typedef struct {
  GObject parent_slot;

  DBusGConnection * bus;
  DBusGProxy * u1_proxy;
  DBusGProxy * u1_status;
  DBusGProxy * u1_shares;
  DBusGProxy * u1_fs;

  /* Are we connected? */
  gboolean connected;

  /* The managed directory root */
  gchar * managed;

  /* Buttons, because we need a different one for each view */
  GHashTable * buttons;

  /* Lists of ul/dl/shares for setting emblems */
  GHashTable * uploads;
  GHashTable * downloads;
  GHashTable * shares;
} UbuntuOneNautilus;

typedef struct {
  GObjectClass parent_slot;
} UbuntuOneNautilusClass;

static void ubuntuone_nautilus_finalize(GObject * object);

static GType ubuntuone_nautilus_get_type (void);
static void ubuntuone_nautilus_register_type (GTypeModule * module);

/* DBus signal and async method call handlers */
static void ubuntuone_nautilus_share_metadata (DBusGProxy * proxy,
                                     DBusGProxyCall * call_id,
                                     gpointer user_data);
static void ubuntuone_nautilus_state_toggled (DBusGProxy * proxy,
                                    DBusGProxyCall * call_id,
                                    gpointer user_data);
static void ubuntuone_nautilus_got_root (DBusGProxy * proxy,
                               DBusGProxyCall * call_id,
                               gpointer user_data);
static void ubuntuone_nautilus_got_shared (DBusGProxy * proxy,
                                 DBusGProxyCall * call_id,
                                 gpointer user_data);
static void ubuntuone_nautilus_status_changed (DBusGProxy * proxy,
                                     GHashTable * hash,
                                     gpointer user_data);
static void ubuntuone_nautilus_upload_started (DBusGProxy * proxy,
                                     gchar * path,
                                     gpointer user_data);
static void ubuntuone_nautilus_upload_finished (DBusGProxy * proxy,
                                     gchar * path,
                                     gpointer user_data);
static void ubuntuone_nautilus_download_started (DBusGProxy * proxy,
                                     gchar * path,
                                     gpointer user_data);
static void ubuntuone_nautilus_download_finished (DBusGProxy * proxy,
                                      gchar * path,
                                      gpointer user_data);
static void ubuntuone_nautilus_share_created (DBusGProxy * proxy,
                                    GHashTable * hash,
                                    gpointer user_data);

static GObjectClass * parent_class = NULL;

/* Are we in an Ubuntu One managed directory */
static gboolean ubuntuone_is_storagefs (UbuntuOneNautilus * uon,
                              const char * path) {
  gboolean managed = FALSE;
  gchar * dirpath;

  if (!uon->managed)
    return FALSE;

  if (!path)
    return FALSE;

  if (strcmp (path, uon->managed) == 0)
    return TRUE;

  dirpath = g_strdup_printf ("%s/", uon->managed);
  if (strncmp (path, dirpath, strlen (dirpath)) == 0)
    managed = TRUE;

  g_free (dirpath);

  return managed;
}

/* Update file info provider */
static NautilusOperationResult ubuntuone_nautilus_update_file_info (NautilusInfoProvider * provider,
                                                    NautilusFileInfo * file,
                                                    GClosure * update_complete,
                                                    NautilusOperationHandle ** handle) {
  UbuntuOneNautilus * uon;
  gchar * share_status = NULL;
  char * path = NULL;
  int size = 0, ret = 0;

  uon = UBUNTUONE_NAUTILUS(provider);

  path = g_filename_from_uri (nautilus_file_info_get_uri (file), NULL, NULL);

  if (g_hash_table_lookup (uon->uploads, path))
    nautilus_file_info_add_emblem (file, "ubuntuone-uploading");

  if (g_hash_table_lookup (uon->downloads, path))
    nautilus_file_info_add_emblem (file, "ubuntuone-downloading");

  if (g_hash_table_lookup (uon->shares, path))
    nautilus_file_info_add_emblem (file, "shared");

  return NAUTILUS_OPERATION_COMPLETE;
}

static void ubuntuone_nautilus_info_provider_iface_init (NautilusInfoProviderIface * iface) {
  iface->update_file_info = ubuntuone_nautilus_update_file_info;
}

/* LocationWidget callbacks */
static void ubuntuone_nautilus_button_clicked (GtkButton * button,
                                     gpointer user_data) {
  UbuntuOneNautilus * uon = UBUNTUONE_NAUTILUS (user_data);

  if (uon->connected)
    dbus_g_proxy_begin_call (uon->u1_proxy, "disconnect",
                       ubuntuone_nautilus_state_toggled, NULL,
                       NULL, G_TYPE_INVALID);
  else
    dbus_g_proxy_begin_call (uon->u1_proxy, "connect",
                       ubuntuone_nautilus_state_toggled, NULL,
                       NULL, G_TYPE_INVALID);
}

static void ubuntuone_nautilus_button_destroyed (GtkObject * button,
                                     gpointer user_data) {
  UbuntuOneNautilus * uon = UBUNTUONE_NAUTILUS (user_data);
  gchar * path;

  /* Magic bag of holding +10:
   * Get the path so we can remove the button from the hash table
   */
  path = g_object_steal_data (G_OBJECT (button), "uon-path");
  g_hash_table_remove (uon->buttons, path);

  g_free (path);
}

/* LocationWidget provider */
static GtkWidget * ubuntuone_nautilus_get_location_widget(NautilusLocationWidgetProvider * provider,
                                            const char * uri,
                                            GtkWidget * parent) {
  UbuntuOneNautilus * uon;
  gchar * path;
  GtkWidget * hbox = NULL;
  GtkWidget * label, * button;
  gchar * labeltext;

  uon = UBUNTUONE_NAUTILUS (provider);

  path = g_filename_from_uri (uri, NULL, NULL);

  if (!ubuntuone_is_storagefs (uon, path))
    goto location_done;

  hbox = gtk_hbox_new (FALSE, 6);
  labeltext = g_strdup_printf ("<b>Ubuntu One</b> %s", _("File Sharing"));
  label = gtk_label_new (labeltext);
  gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  gtk_widget_show (label);

  /* Create a button and stick it in the hash, if we don't have one already */
  button = g_hash_table_lookup (uon->buttons, path);
  if (!button) {
    button = gtk_button_new_with_label (_("Connect"));
    /* Magic bag of holding +10:
     * We have to set the path as data on the object, to remove the button
     * from the hash table when it is destroyed (window close, etc...)
     */
    g_object_set_data_full (G_OBJECT (button), "uon-path",
                      g_strdup (path), g_free);
    g_hash_table_replace (uon->buttons, g_strdup (path), button);

    g_signal_connect (button, "destroy",
                  G_CALLBACK (ubuntuone_nautilus_button_destroyed), uon);
    g_signal_connect (button, "clicked",
                  G_CALLBACK (ubuntuone_nautilus_button_clicked), uon);
    gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
  }
  gtk_widget_show (button);

  gtk_widget_show (hbox);

 location_done:
  g_free (path);

  return hbox;
}

static void ubuntuone_nautilus_bar_provider_iface_init (NautilusLocationWidgetProviderIface * iface) {
  iface->get_widget = ubuntuone_nautilus_get_location_widget;
}

/* Magical struct for passing data in sharing callbacks */
struct _ShareCBData {
  UbuntuOneNautilus * uon;
  gchar * path;
  GtkWidget * parent;

  /* Share dialog widgets */
  GtkWidget * user_entry;
  GtkWidget * name_entry;
  GtkWidget * allow_mods;
};

static void __share_cb_data_free (struct _ShareCBData * data) {
  data->uon = NULL;
  data->parent = NULL;

  g_free (data->path);
  data->path = NULL;

  g_free (data);

  data = NULL;
}

/* Share on Ubuntu One dialog constructor */
static GtkWidget * ubuntuone_nautilus_share_dialog_construct (struct _ShareCBData * data) {
  GtkWidget * dialog;
  GtkWidget * area, * table, * label;

  dialog = gtk_dialog_new ();
  gtk_window_set_title (GTK_WINDOW (dialog), _("Share on Ubuntu One"));
  gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (data->parent));
  gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
  gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
  gtk_dialog_add_buttons (GTK_DIALOG (dialog),
                    GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                    ("Share"), GTK_RESPONSE_ACCEPT,
                    NULL);
  gtk_dialog_set_default_response (GTK_DIALOG (dialog),
                           GTK_RESPONSE_ACCEPT);
  gtk_window_set_icon_name (GTK_WINDOW (dialog), "ubuntuone-client");

  area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));

  table = gtk_table_new (3, 2, FALSE);
  gtk_table_set_row_spacings (GTK_TABLE (table), 12);
  gtk_table_set_col_spacings (GTK_TABLE (table), 6);
  gtk_container_set_border_width (GTK_CONTAINER (table), 7);
  gtk_widget_show (table);
  gtk_container_add (GTK_CONTAINER (area), table);

  label = gtk_label_new (_("Share _with (e-mail):"));
  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
  gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
  gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 0, 1);
  gtk_widget_show (label);

  data->user_entry = gtk_entry_new ();
  gtk_label_set_mnemonic_widget (GTK_LABEL (label), data->user_entry);
  gtk_table_attach_defaults (GTK_TABLE (table), data->user_entry, 1, 2, 0, 1);
  gtk_widget_show (data->user_entry);

  label = gtk_label_new (_("Share _Name:"));
  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
  gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
  gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 1, 2);
  gtk_widget_show (label);

  data->name_entry = gtk_entry_new ();
  gtk_label_set_mnemonic_widget (GTK_LABEL (label), data->name_entry);
  gtk_table_attach_defaults (GTK_TABLE (table), data->name_entry, 1, 2, 1, 2);
  gtk_widget_show (data->name_entry);

  data->allow_mods = gtk_check_button_new_with_mnemonic (_("_Allow Modification"));
  gtk_table_attach_defaults (GTK_TABLE (table), data->allow_mods, 0, 2, 2, 3);
  gtk_widget_show (data->allow_mods);

  return dialog;
}

/* Struct for post data for creating a share */
struct _SharePostData {
  gchar * email;
  gchar * name;
  gboolean modify;
};

static void __share_post_data_free (struct _SharePostData * data) {
  g_free (data->email);
  data->email = NULL;

  g_free (data->name);
  data->name = NULL;

  g_free (data);
  data = NULL;
}

/* Menu callbacks */
static void ubuntuone_nautilus_share_dialog_response (GtkDialog * dialog,
                                          gint response,
                                          gpointer user_data) {
  struct _ShareCBData * data = (struct _ShareCBData *) user_data;

  switch (response) {
  case GTK_RESPONSE_ACCEPT: {
    struct _SharePostData * pdata = g_new0 (struct _SharePostData, 1);

    pdata->email = g_strdup (gtk_entry_get_text (GTK_ENTRY (data->user_entry)));
    pdata->name = g_strdup (gtk_entry_get_text (GTK_ENTRY (data->name_entry)));
    pdata->modify = gtk_check_box_get_active (GTK_CHECK_BOX (data->allow_mods));

    dbus_g_proxy_begin_call (data->uon->u1_fs, "get_metadata",
                       ubuntuone_nautilus_share_metadata, pdata,
                       NULL,
                       G_TYPE_STRING, data->path,
                       G_TYPE_INVALID);
  }
  default:
    gtk_widget_destroy (GTK_WIDGET (dialog));
    break;
  }
  __share_cb_data_free (data);
}

static void ubuntuone_nautilus_share_dialog_closed (GtkDialog * dialog,
                                        gpointer user_data) {
  ubuntuone_nautilus_share_dialog_response (dialog, GTK_RESPONSE_CANCEL,
                                  user_data);
}

static void ubuntuone_nautilus_share_folder (NautilusMenuItem * item,
                                   gpointer * user_data) {
  struct _ShareCBData * data = (struct _ShareCBData *) user_data;
  GtkWidget * dialog;

  dialog = ubuntuone_nautilus_share_dialog_construct (data);
  g_signal_connect (dialog, "close",
                G_CALLBACK (ubuntuone_nautilus_share_dialog_closed), data);
  g_signal_connect (dialog, "response",
                G_CALLBACK (ubuntuone_nautilus_share_dialog_response), data);

  gtk_widget_show (dialog);
}


/* Menu provider */
static GList * ubuntuone_nautilus_get_menu_items (NautilusMenuProvider * provider,
                                       GtkWidget * window,
                                       GList * files) {
  UbuntuOneNautilus * uon;
  NautilusFileInfo * file;
  GList * items = NULL;
  gchar * path;
  gchar * shared;
  gchar * myfiles;
  struct _ShareCBData * share_cb_data;

  if (g_list_length (files) != 1)
    return NULL;

  uon = UBUNTUONE_NAUTILUS (provider);

  file = g_list_nth_data (files, 0);
  path = g_filename_from_uri (nautilus_file_info_get_uri (file), NULL, NULL);

  shared = g_build_filename (uon->managed, "Shared with Me", NULL);
  myfiles = g_build_filename (uon->managed, "My Files", NULL);

  if (!ubuntuone_is_storagefs (uon, path))
    goto done;

  if (strncmp (path, shared, strlen (shared)) == 0)
    goto done;

  if (strncmp (path, myfiles, strlen (myfiles)) != 0)
    goto done;

  share_cb_data = g_new0 (struct _ShareCBData, 1);
  share_cb_data->uon = uon;
  share_cb_data->parent = window;
  share_cb_data->path = g_strdup (path);

  if (nautilus_file_info_is_directory (file)) {
    NautilusMenuItem * item;

    item = nautilus_menu_item_new ("ubuntuone-share",
                           _("Share on Ubuntu One"),
                           _("Share this folder on Ubuntu One"),
                           "ubuntuone-client");
    g_signal_connect (item, "activate",
                  G_CALLBACK (ubuntuone_nautilus_share_folder),
                  share_cb_data);
    items = g_list_prepend (items, item);
  }

 done:
  g_free (myfiles);
  g_free (shared);
  g_free (path);
  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->uploads = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
  uon->downloads = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
  uon->shares = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);

  /* Magic bag of holding +10:
   * We store some button widgets in a hash table here, so that we can
   * update the button's label if there are multiple windows open
   * This is particularly an issue with spatial mode Nautilus
   */
  uon->buttons = g_hash_table_new_full (g_str_hash, g_str_equal,
                              g_free, NULL);

  uon->bus = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
  if (!uon->bus) {
    g_warning ("Failed to get session bus.");
    return;
  }

  uon->u1_proxy = dbus_g_proxy_new_for_name (uon->bus,
                                   "com.ubuntuone.SyncDaemon",
                                   "/",
                                   "com.ubuntuone.SyncDaemon.SyncDaemon");
  uon->u1_status = dbus_g_proxy_new_for_name (uon->bus,
                                    "com.ubuntuone.SyncDaemon",
                                    "/status",
                                    "com.ubuntuone.SyncDaemon.Status");
  uon->u1_shares = dbus_g_proxy_new_for_name (uon->bus,
                                    "com.ubuntuone.SyncDaemon",
                                    "/shares",
                                    "com.ubuntuone.SyncDaemon.Shares");

  dbus_g_proxy_begin_call (uon->u1_proxy, "get_rootdir",
                     ubuntuone_nautilus_got_root, uon,
                     NULL, G_TYPE_INVALID);
  dbus_g_proxy_begin_call (uon->u1_shares, "get_shared",
                     ubuntuone_nautilus_got_shared, uon,
                     NULL, G_TYPE_INVALID);

  dbus_g_proxy_add_signal (uon->u1_status, "StatusChanged",
                     dbus_g_type_get_map ("GHashTable",
                                    G_TYPE_STRING,
                                    G_TYPE_STRING),
                     G_TYPE_INVALID);
  dbus_g_proxy_connect_signal (uon->u1_status, "StatusChanged",
                         G_CALLBACK(ubuntuone_nautilus_status_changed),
                         uon, NULL);

  dbus_g_proxy_add_signal (uon->u1_status, "UploadStarted",
                     G_TYPE_STRING,
                     G_TYPE_INVALID);
  dbus_g_proxy_connect_signal (uon->u1_status, "UploadStarted",
                         G_CALLBACK (ubuntuone_nautilus_upload_started),
                         uon, NULL);
  dbus_g_proxy_add_signal (uon->u1_status, "UploadFinished",
                     G_TYPE_STRING,
                     G_TYPE_INVALID);
  dbus_g_proxy_connect_signal (uon->u1_status, "UploadFinished",
                         G_CALLBACK (ubuntuone_nautilus_upload_finished),
                         uon, NULL);
  dbus_g_proxy_add_signal (uon->u1_status, "DownloadStarted",
                     G_TYPE_STRING,
                     G_TYPE_INVALID);
  dbus_g_proxy_connect_signal (uon->u1_status, "DownloadStarted",
                         G_CALLBACK (ubuntuone_nautilus_download_started),
                         uon, NULL);
  dbus_g_proxy_add_signal (uon->u1_status, "DownloadFinished",
                     G_TYPE_STRING,
                     G_TYPE_INVALID);
  dbus_g_proxy_connect_signal (uon->u1_status, "DownloadFinished",
                         G_CALLBACK (ubuntuone_nautilus_download_finished),
                         uon, NULL);
  dbus_g_proxy_add_signal (uon->u1_shares, "ShareCreated",
                     dbus_g_type_get_map ("GHashTable",
                                    G_TYPE_STRING,
                                    G_TYPE_STRING),
                     G_TYPE_INVALID);
  dbus_g_proxy_connect_signal (uon->u1_shares, "ShareCreated",
                         G_CALLBACK (ubuntuone_nautilus_share_created),
                         uon, NULL);
}

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);
  GSList * l;

  g_object_unref (uon->u1_proxy);
  g_object_unref (uon->u1_status);
  g_object_unref (uon->bus);

  g_hash_table_destroy (uon->uploads);
  uon->uploads = NULL;

  g_hash_table_destroy (uon->downloads);
  uon->downloads = NULL;

  g_hash_table_destroy (uon->shares);
  uon->shares = NULL;

  g_hash_table_destroy (uon->buttons);
  uon->buttons = NULL;
}

static 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 */
#if 0
  g_type_module_add_interface (module,
                         un_type,
                         NAUTILUS_TYPE_MENU_PROVIDER,
                         &menu_provider_iface_info);
#endif
}


/* DBus signal handlers and async method call handlers */
static void ubuntuone_nautilus_share_metadata (DBusGProxy * proxy,
                                     DBusGProxyCall * call_id,
                                     gpointer user_data) {
  struct _SharePostData * data = (struct _SharePostData *) user_data;
  GHashTable * hash;
  GError * error = NULL;
  gchar * form_data;
  gchar * node;

  if (!dbus_g_proxy_end_call (proxy, call_id, &error,
                        dbus_g_type_get_map ("GHashTable",
                                       G_TYPE_STRING,
                                       G_TYPE_STRING), &hash,
                        G_TYPE_INVALID)) {
    g_warning ("ERROR: %s", error->message);
    goto share_done;
  }
  node = g_hash_table_lookup (hash, "node_id");

  /* Need to call a to-be-implemented DBus method on syncdaemon here */

 share_done:
  __share_post_data_free (data);
}

static void ubuntuone_nautilus_state_toggled (DBusGProxy * proxy,
                                    DBusGProxyCall * call_id,
                                    gpointer user_data) {
  dbus_g_proxy_end_call (proxy, call_id, NULL, G_TYPE_INVALID);
}

static void ubuntuone_nautilus_got_root (DBusGProxy * proxy,
                               DBusGProxyCall * call_id,
                               gpointer user_data) {
  UbuntuOneNautilus * uon;
  gchar * managed;
  GError * error = NULL;

  if (!dbus_g_proxy_end_call (proxy, call_id, &error,
                        G_TYPE_STRING, &managed,
                        G_TYPE_INVALID)) {
    g_warning ("ERROR: %s", error->message);
    return;
  }

  uon = UBUNTUONE_NAUTILUS (user_data);

  uon->managed = g_strdup (managed);
  g_free (managed);
}

static void ubuntuone_nautilus_got_shared (DBusGProxy * proxy,
                                 DBusGProxyCall * call_id,
                                 gpointer user_data) {
  UbuntuOneNautilus * uon;
  GSList * data, * l;
  GError * error = NULL;

  if (!dbus_g_proxy_end_call (proxy, call_id, &error,
                        dbus_g_type_get_collection ("GSList",
                                            dbus_g_type_get_map
                                            ("GHashTable",
                                             G_TYPE_STRING,
                                             G_TYPE_STRING)),
                        &data,
                        G_TYPE_INVALID)) {
    g_warning ("ERROR: %s", error->message);
    return;
  }

  uon = UBUNTUONE_NAUTILUS (user_data);
  for (l = data; l != NULL && l->data != NULL; l = l->next) {
    GHashTable * hash = l->data;
    ubuntuone_nautilus_share_created (proxy, hash, user_data);
    data = g_slist_remove (data, hash);
  }
  g_slist_free (data);
}

static void ubuntuone_nautilus_button_foreach (gpointer key,
                                     gpointer value,
                                     gpointer user_data) {
  const char * label = (const char *) user_data;
  GtkButton * button = GTK_BUTTON (value);

  gtk_button_set_label (button, label);
}

static void ubuntuone_nautilus_status_changed (DBusGProxy * proxy,
                                     GHashTable * hash,
                                     gpointer user_data) {
  UbuntuOneNautilus * uon = UBUNTUONE_NAUTILUS (user_data);
  gchar * status;
  gchar * is_online;
  gchar * is_connected;

  is_online = g_hash_table_lookup (hash, "is_online");
  is_connected = g_hash_table_lookup (hash, "is_connected");
  status = g_hash_table_lookup (hash, "name");

  if (is_online[0] == '\0' || is_connected[0] == '\0' ||
      strncmp (status, "INIT", 4) == 0||
      strncmp (status, "READY", 5) == 0) {
    uon->connected = FALSE;
    g_hash_table_foreach (uon->buttons,
                    (GHFunc) ubuntuone_nautilus_button_foreach,
                    _("Connect"));
  } else {
    uon->connected = TRUE;
    g_hash_table_foreach (uon->buttons,
                    (GHFunc) ubuntuone_nautilus_button_foreach,
                    _("Disconnect"));
  }
}

static void ubuntuone_nautilus_upload_started (DBusGProxy * proxy,
                                     gchar * path,
                                     gpointer user_data) {
  UbuntuOneNautilus * uon = UBUNTUONE_NAUTILUS (user_data);

  if (!g_hash_table_lookup (uon->uploads, path)) {
    gchar *new_path = g_strdup (path);
    g_hash_table_insert (uon->uploads, new_path, new_path);
    utime (path, NULL);
  }
}

static void ubuntuone_nautilus_upload_finished (DBusGProxy * proxy,
                                    gchar * path,
                                    gpointer user_data) {
  UbuntuOneNautilus * uon = UBUNTUONE_NAUTILUS (user_data);

  g_hash_table_remove (uon->uploads, path);
  utime (path, NULL);
}

static void ubuntuone_nautilus_download_started (DBusGProxy * proxy,
                                     gchar * path,
                                     gpointer user_data) {
  UbuntuOneNautilus * uon = UBUNTUONE_NAUTILUS (user_data);
  gchar * partial;
  const gchar * usepath;
  int fd;

  partial = g_strconcat (path, ".partial", NULL);
  if (g_file_test (path, G_FILE_TEST_IS_DIR))
    usepath = path;
  else
    usepath = partial;

  if (!g_hash_table_lookup (uon->uploads, usepath)) {
    gchar *new_path = g_strdup (usepath);
    g_hash_table_insert (uon->downloads, new_path, new_path);
    if (!g_file_test (usepath, G_FILE_TEST_EXISTS)) {
      fd = open (usepath, O_WRONLY | O_CREAT | O_NONBLOCK | O_NOCTTY,
             S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
      close (fd);
    }
    utime (usepath, NULL);
  }
  g_free (partial);
}

static void ubuntuone_nautilus_download_finished (DBusGProxy * proxy,
                                      gchar * path,
                                      gpointer user_data) {
  UbuntuOneNautilus * uon = UBUNTUONE_NAUTILUS (user_data);
  gchar * partial;
  const gchar * usepath;

  partial = g_strconcat (path, ".partial", NULL);
  if (g_file_test (path, G_FILE_TEST_IS_DIR))
    usepath = path;
  else
    usepath = partial;

  g_hash_table_remove (uon->downloads, usepath);
  utime (usepath, NULL);

  g_free (partial);
}

static void ubuntuone_nautilus_share_created (DBusGProxy * proxy,
                                    GHashTable * hash,
                                    gpointer user_data) {
  UbuntuOneNautilus * uon = UBUNTUONE_NAUTILUS (user_data);
  gchar * path;

  path = g_hash_table_lookup (hash, "path");
  if (!g_hash_table_lookup (uon->shares, path)) {
    gchar *new_share = g_strdup (path);
    g_hash_table_insert (uon->shares, new_share, new_share);
  }
}

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