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

location-widget.c

/*
 * UbuntuOne Nautilus plugin
 *
 * Authors: 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 <libsyncdaemon/syncdaemon-folders-interface.h>
#include <libsyncdaemon/syncdaemon-shares-interface.h>
#include "location-widget.h"

#define DISABLED_SYNC_HELP  _("These files are not backed up and will not be available in your other computers")
#define ENABLED_SYNC_HELP _("These files are backed up and will be available in your other computers")

G_DEFINE_TYPE(LocationWidget, location_widget, GTK_TYPE_HBOX)

static void
start_spinner (LocationWidget *location)
{
      gtk_widget_set_sensitive (location->toggle_button, FALSE);
      gtk_widget_set_sensitive (location->help_label, FALSE);
      gtk_widget_show (location->spinner);
      gtk_spinner_start (GTK_SPINNER (location->spinner));
}

static void
stop_spinner (LocationWidget *location)
{
      gtk_spinner_stop (GTK_SPINNER (location->spinner));
      gtk_widget_hide (location->spinner);
      gtk_widget_set_sensitive (location->help_label, TRUE);
      gtk_widget_set_sensitive (location->toggle_button, TRUE);
}

static void
folder_created_cb (SyncdaemonDaemon *daemon, gboolean success, SyncdaemonFolderInfo *folder_info, gpointer user_data)
{
      const gchar *path;
      LocationWidget *location = LOCATION_WIDGET (user_data);

      path = syncdaemon_folder_info_get_path (folder_info);
      g_warning ("in folder_created_cb with path = %s", path);
      if (g_strcmp0 (path, location->path) == 0) {
            gtk_widget_set_sensitive (location->toggle_button, TRUE);
            gtk_label_set_text (GTK_LABEL (location->help_label), ENABLED_SYNC_HELP);
            if (!success) {
                  ubuntuone_show_error_dialog (location->uon, _("Error enabling folder"),
                                         _("Could not enable folder %s for synchronizing to Ubuntu One"),
                                         location->path);
            }

            stop_spinner (location);
      }
}

static void
folder_deleted_cb (SyncdaemonDaemon *daemon, gboolean success, SyncdaemonFolderInfo *folder_info, gpointer user_data)
{
      const gchar *path;
      LocationWidget *location = LOCATION_WIDGET (user_data);

      path = syncdaemon_folder_info_get_path (folder_info);
      if (g_strcmp0 (path, location->path) == 0) {
            stop_spinner (location);
            if (success)
                  gtk_label_set_text (GTK_LABEL (location->help_label), DISABLED_SYNC_HELP);
            else {
                  ubuntuone_show_error_dialog (location->uon, _("Error disabling folder"),
                                         _("Could not disable folder %s for synchronizing to Ubuntu One"),
                                         location->path);
            }

            stop_spinner (location);
      }
}

static void
location_widget_finalize (GObject *object)
{
      LocationWidget *location = LOCATION_WIDGET (object);

      g_signal_handlers_disconnect_by_func (location->uon->syncdaemon, folder_created_cb, location);
      g_signal_handlers_disconnect_by_func (location->uon->syncdaemon, folder_deleted_cb, location);

      if (location->conf_notify_id != 0)
            gconf_client_notify_remove (location->conf_client, location->conf_notify_id);

      if (location->conf_client != NULL)
            g_object_unref (G_OBJECT (location->conf_client));

      if (location->path != NULL)
            g_free (location->path);

      G_OBJECT_CLASS (location_widget_parent_class)->finalize (object);
}

static void
location_widget_class_init (LocationWidgetClass *klass)
{
      GObjectClass *object_class = G_OBJECT_CLASS (klass);

      object_class->finalize = location_widget_finalize;
}

static void sync_toggled_cb (GtkToggleButton *button, gpointer user_data);

static void
disable_u1 (LocationWidget *location)
{
      SyncdaemonInterface *interface;

      /* Perform the removal of this folder */
      interface = syncdaemon_daemon_get_folders_interface (location->uon->syncdaemon);
      if (interface != NULL) {
            SyncdaemonFolderInfo *folder_info;

                folder_info = syncdaemon_folders_interface_get_info (
                        SYNCDAEMON_FOLDERS_INTERFACE (interface),
                        location->path);
                if (folder_info != NULL) {
                        if (ubuntuone_check_shares_and_public_files (location->uon, folder_info, GTK_WIDGET (location))) {
                        start_spinner (location);

                                syncdaemon_folders_interface_delete (
                                        SYNCDAEMON_FOLDERS_INTERFACE (interface),
                                        syncdaemon_folder_info_get_volume_id (folder_info));
                        } else {
                        g_signal_handlers_block_by_func (location->toggle_button, sync_toggled_cb, location);
                        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (location->toggle_button), TRUE);
                        g_signal_handlers_unblock_by_func (location->toggle_button, sync_toggled_cb, location);
                  }

                        g_object_unref (G_OBJECT (folder_info));
                }
        }
}

static void enable_u1 (LocationWidget *location);

static void
daemon_connected_cb (SyncdaemonDaemon *daemon, gpointer user_data)
{
      LocationWidget *location = LOCATION_WIDGET (user_data);

      if (syncdaemon_daemon_has_network (daemon) &&
          syncdaemon_authentication_has_credentials (
                syncdaemon_daemon_get_authentication (daemon))) {
            enable_u1 (location);
      }
}

static void
enable_u1 (LocationWidget *location)
{
      SyncdaemonInterface *interface;

      /* Perform the addition of this folder */
      interface = syncdaemon_daemon_get_folders_interface (location->uon->syncdaemon);
      if (interface != NULL) {
            start_spinner (location);

            /* If there is no user authenticated, make Syncdaemon do so */
            if (syncdaemon_authentication_has_credentials (
                      syncdaemon_daemon_get_authentication (location->uon->syncdaemon))) {
                  syncdaemon_folders_interface_create (SYNCDAEMON_FOLDERS_INTERFACE (interface),
                                               location->path);
            } else {
                  g_signal_connect (G_OBJECT (location->uon->syncdaemon), "connected",
                                G_CALLBACK (daemon_connected_cb), location);
                  syncdaemon_daemon_connect (location->uon->syncdaemon);
            }
      }
}

static void
sync_toggled_cb (GtkToggleButton *button, gpointer user_data)
{
      LocationWidget *location = LOCATION_WIDGET (user_data);

      if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (location->toggle_button)))
            enable_u1 (location);
      else
            disable_u1 (location);
}

static gboolean
expander_clicked_cb (GtkExpander *expander, gpointer user_data)
{
      LocationWidget *location = LOCATION_WIDGET (user_data);
      gboolean expander_status = gtk_expander_get_expanded (expander);

        gconf_client_set_bool (location->conf_client,
                               EXPANDER_STATUS_KEY,
                               expander_status,
                               NULL);

      return FALSE;
}

static void
config_changed_cb (GConfClient *client, guint cnx_id, GConfEntry *entry, gpointer user_data)
{
      LocationWidget *location = LOCATION_WIDGET (user_data);

      if (g_strcmp0 (gconf_entry_get_key (entry), EXPANDER_STATUS_KEY) == 0) {
            gboolean expanded = gconf_client_get_bool (location->conf_client,
                                             EXPANDER_STATUS_KEY,
                                             NULL);
            gtk_expander_set_expanded (GTK_EXPANDER (location->expander),
                                 expanded);
                location->expander_status = expanded;
      }
}

static void
allocate_cb (GtkWidget *label, GtkAllocation *allocation, gpointer user_data)
{
      gint width;

      if (allocation->width < 100)
            width = 100;      /* some number */
      else
            width = allocation->width - 2;
      gtk_widget_set_size_request(label, width, -1);
}

static void
location_widget_init (LocationWidget *location)
{
      GtkWidget *hbox, *align;

      location->path = NULL;
      location->info_label = NULL;

      /* Read expander status from GConf */
      location->conf_client = gconf_client_get_default ();
      gconf_client_add_dir (location->conf_client, EXPANDER_STATUS_SECTION,
                        GCONF_CLIENT_PRELOAD_RECURSIVE, NULL);
      location->conf_notify_id = gconf_client_notify_add (location->conf_client,
                                              EXPANDER_STATUS_SECTION,
                                              (GConfClientNotifyFunc) config_changed_cb,
                                              location,
                                              NULL,
                                              NULL);
      location->expander_status = gconf_client_get_bool (location->conf_client,
                                             EXPANDER_STATUS_KEY, NULL);

      /* Create the widgets in the interface */
      hbox = gtk_hbox_new (FALSE, 0);
      gtk_widget_show (hbox);
      gtk_box_pack_start (GTK_BOX (location), hbox, TRUE, TRUE, 0);

      location->expander = gtk_expander_new ("<b>Ubuntu One</b>");
      gtk_widget_show (location->expander);
      gtk_expander_set_use_markup (GTK_EXPANDER (location->expander), TRUE);
      gtk_expander_set_expanded (GTK_EXPANDER (location->expander),
                           location->expander_status);
      g_signal_connect_after (G_OBJECT (location->expander), "activate",
                                G_CALLBACK (expander_clicked_cb), location);
      gtk_box_pack_start (GTK_BOX (hbox), location->expander, TRUE, TRUE, 0);
      location->info_label = gtk_expander_get_label_widget (GTK_EXPANDER (location->expander));

      location->help_label = gtk_label_new (DISABLED_SYNC_HELP);
      gtk_widget_show (location->help_label);
      gtk_label_set_use_markup (GTK_LABEL (location->help_label), TRUE);
      gtk_label_set_line_wrap (GTK_LABEL (location->help_label), TRUE);
      gtk_misc_set_alignment (GTK_MISC (location->help_label), 0.0, 0.5);
      gtk_misc_set_padding (GTK_MISC (location->help_label), 4, 4);
      g_signal_connect (G_OBJECT (location->help_label), "size-allocate",
                    G_CALLBACK (allocate_cb), NULL );
      gtk_container_add (GTK_CONTAINER (location->expander),
                     location->help_label);

      location->spinner = gtk_spinner_new ();
      gtk_box_pack_start (GTK_BOX (hbox), location->spinner, FALSE, FALSE, 0);

      /* Buttons */
      align = gtk_alignment_new (1.0, 0.0, 0.0, 0.0);
      gtk_widget_show (align);
      gtk_box_pack_start (GTK_BOX (hbox), align,
                      FALSE, FALSE, 0);

      location->toggle_button = gtk_check_button_new_with_label (_("Synchronize this folder"));
      gtk_widget_show (location->toggle_button);
      gtk_container_add (GTK_CONTAINER (align), location->toggle_button);
}

static gboolean
is_special_udf (UbuntuOneNautilus *uon, const gchar *path)
{
      gint i;
      gchar *special_udfs[] = {
            "Ubuntu One",
            "Ubuntu One/Shared With Me",
            ".ubuntuone/Purchased from Ubuntu One",
            ".local/share/ubuntuone"
      };

      for (i = 0; i < G_N_ELEMENTS (special_udfs); i++) {
            gchar *tmp;
            gboolean done = FALSE;

            tmp = g_build_filename (g_get_home_dir (), special_udfs[i], NULL);
            if (g_str_has_prefix (path, tmp))
                  done = TRUE;

            g_free (tmp);

            if (done)
                  return TRUE;
      }

      return FALSE;
}

GtkWidget *
location_widget_new (UbuntuOneNautilus *uon, const gchar *path)
{
      LocationWidget *location;
      gboolean is_root;
      gboolean is_xdg = FALSE;
      guint i = 0;

      g_return_val_if_fail (uon != NULL, NULL);
      g_return_val_if_fail (path != NULL, NULL);

      /* We only show the location bar for user's folders */
      if (!g_str_has_prefix (path, g_get_home_dir ()) ||
          strlen (path) == strlen (g_get_home_dir ()))
            return NULL;

      /* in fact, we only show it for the toplevel XDG dirs, or the
         root of UDFs.
         Note the user can have an XDG dir configured outside of
         their home, and we don't support that (so the above check
         is not actually redundant)

         As per lp:623482, don't show it on the Video directory.
      */
      for (i = 0; i < G_USER_N_DIRECTORIES; i++) {
            if (i != G_USER_DIRECTORY_VIDEOS &&
                g_strcmp0 (g_get_user_special_dir (i), path) == 0) {
                  is_xdg = TRUE;
                  break;
            }
      }
      if (!is_xdg) {
            /* last chance */
            syncdaemon_daemon_is_folder_enabled (uon->syncdaemon, path, &is_root);
            if (!is_root || is_special_udf (uon, path))
                  return NULL;
      }

      location = (LocationWidget *) g_object_new (TYPE_LOCATION_WIDGET, NULL);
      location->uon = uon;
      location->path = g_strdup (path);

      /* Connect to Syncdaemon signals */
      g_signal_connect (G_OBJECT (uon->syncdaemon), "folder_created",
                    G_CALLBACK (folder_created_cb), location);
      g_signal_connect (G_OBJECT (uon->syncdaemon), "folder_deleted",
                    G_CALLBACK (folder_deleted_cb), location);

      if (syncdaemon_daemon_is_folder_enabled (uon->syncdaemon, path, &is_root)) {
            /* Create label and disable button */
            gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (location->toggle_button), TRUE);
            if (!is_root || is_special_udf (uon, path))
                  gtk_widget_set_sensitive (location->toggle_button, FALSE);

            gtk_label_set_text (GTK_LABEL (location->help_label), ENABLED_SYNC_HELP);
      } else {
            /* Check if this is the 'Shared with me' folder */
            if (is_special_udf (uon, path)) {
                  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (location->toggle_button), TRUE);
                  gtk_widget_set_sensitive (location->toggle_button, FALSE);
            } else {
                  GSList *udfs, *l;
                  SyncdaemonInterface *interface;
                  gboolean allow_enabling = TRUE;

                  /* Check to see if this is the parent of a UDF */
                  interface = syncdaemon_daemon_get_folders_interface (uon->syncdaemon);
                  udfs = syncdaemon_folders_interface_get_folders (SYNCDAEMON_FOLDERS_INTERFACE (interface));
                  for (l = udfs; l != NULL; l = l->next) {
                        SyncdaemonFolderInfo *folder_info = SYNCDAEMON_FOLDER_INFO (l->data);

                        if (g_str_has_prefix (syncdaemon_folder_info_get_path (folder_info), path))
                              allow_enabling = FALSE;
                  }

                  g_slist_free (udfs);
                  
                  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (location->toggle_button), FALSE);
                  if (!allow_enabling) {
                        gtk_label_set_text (GTK_LABEL (location->help_label),
                                        _("This folder cannot be synchronized because it contains "
                                          "one or more folders that are already synchronized"));

                        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (location->toggle_button), FALSE);
                        gtk_widget_set_sensitive (location->toggle_button, FALSE);
                  }
            }
      }

      /* Check for connectivity */
      if (!syncdaemon_daemon_has_network (location->uon->syncdaemon)) {
            gtk_widget_set_sensitive (location->toggle_button, FALSE);
            gtk_label_set_text (GTK_LABEL (location->help_label),
                            _("Operations on this folder are disabled because there is no network "
                              "connection"));
      }

      g_signal_connect (G_OBJECT (location->toggle_button), "toggled",
                    G_CALLBACK (sync_toggled_cb), location);

      gtk_widget_show (GTK_WIDGET (location));

      return GTK_WIDGET (location);
}

Generated by  Doxygen 1.6.0   Back to index