]> git.0d.be Git - empathy.git/blobdiff - src/empathy-accounts-dialog.c
Merge branch 'gnome-3-8'
[empathy.git] / src / empathy-accounts-dialog.c
index d7b16edf2905f1e33b3023c0845118f1f373d201..27f41d37b8829224fffce0ae85f436e34a9aeb80 100644 (file)
  *          Danielle Madeley <danielle.madeley@collabora.co.uk>
  */
 
-#include <config.h>
-
-#include <string.h>
-#include <stdlib.h>
+#include "config.h"
+#include "empathy-accounts-dialog.h"
 
-#include <gtk/gtk.h>
 #include <glib/gi18n-lib.h>
-#include <dbus/dbus-glib.h>
-
-#include <telepathy-glib/account-manager.h>
-#include <telepathy-glib/defs.h>
-#include <telepathy-glib/util.h>
-
-#include <libempathy/empathy-utils.h>
-#include <libempathy/empathy-connection-managers.h>
-#include <libempathy/empathy-connectivity.h>
-#include <libempathy/empathy-tp-contact-factory.h>
-
-#include <libempathy-gtk/empathy-ui-utils.h>
-#include <libempathy-gtk/empathy-protocol-chooser.h>
-#include <libempathy-gtk/empathy-account-widget.h>
-#include <libempathy-gtk/empathy-account-widget-irc.h>
-#include <libempathy-gtk/empathy-account-widget-sip.h>
-#include <libempathy-gtk/empathy-cell-renderer-activatable.h>
-#include <libempathy-gtk/empathy-contact-widget.h>
-#include <libempathy-gtk/empathy-images.h>
 
-#include "empathy-accounts-dialog.h"
+#include "empathy-accounts-common.h"
+#include "empathy-account-widget-sip.h"
 #include "empathy-import-dialog.h"
 #include "empathy-import-utils.h"
+#include "empathy-local-xmpp-assistant-widget.h"
+#include "empathy-new-account-dialog.h"
+#include "empathy-pkg-kit.h"
+#include "empathy-ui-utils.h"
+#include "empathy-user-info.h"
+#include "empathy-utils.h"
 
 #define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT
-#include <libempathy/empathy-debug.h>
+#include "empathy-debug.h"
 
 /* Flashing delay for icons (milliseconds). */
 #define FLASH_TIMEOUT 500
@@ -76,7 +61,8 @@ G_DEFINE_TYPE (EmpathyAccountsDialog, empathy_accounts_dialog, GTK_TYPE_DIALOG);
 enum
 {
   NOTEBOOK_PAGE_ACCOUNT = 0,
-  NOTEBOOK_PAGE_LOADING
+  NOTEBOOK_PAGE_LOADING,
+  NOTEBOOK_PAGE_NO_PROTOCOL
 };
 
 typedef struct {
@@ -89,21 +75,19 @@ typedef struct {
   GtkWidget *image_status;
   GtkWidget *throbber;
   GtkWidget *enabled_switch;
-  GtkWidget *frame_no_protocol;
 
   GtkWidget *treeview;
+  GtkCellRenderer *name_renderer;
 
   GtkWidget *button_add;
   GtkWidget *button_remove;
   GtkWidget *button_import;
 
-  GtkWidget *combobox_protocol;
-  GtkWidget *hbox_protocol;
-
   GtkWidget *image_type;
   GtkWidget *label_name;
   GtkWidget *label_type;
   GtkWidget *dialog_content;
+  GtkWidget *user_info;
 
   GtkWidget *notebook_account;
   GtkWidget *spinner;
@@ -121,7 +105,7 @@ typedef struct {
    * That's kinda ugly; cf bgo #640417.
    *
    * */
-  EmpathyAccountWidget *setting_widget_object;
+  EmpathyAccountWidget *setting_widget;
 
   gboolean  connecting_show;
   guint connecting_id;
@@ -131,7 +115,7 @@ typedef struct {
 
   TpAccountManager *account_manager;
   EmpathyConnectionManagers *cms;
-  EmpathyConnectivity *connectivity;
+  GNetworkMonitor *connectivity;
 
   GtkWindow *parent_window;
   TpAccount *initial_selection;
@@ -143,6 +127,8 @@ typedef struct {
    * EmpathyAccountsDialog object. */
   gboolean force_change_row;
   GtkTreeRowReference *destination_row;
+
+  GHashTable *icons_cache;
 } EmpathyAccountsDialogPriv;
 
 enum {
@@ -160,21 +146,13 @@ enum {
 static EmpathyAccountSettings * accounts_dialog_model_get_selected_settings (
     EmpathyAccountsDialog *dialog);
 
-static gboolean accounts_dialog_get_settings_iter (
-    EmpathyAccountsDialog *dialog,
-    EmpathyAccountSettings *settings,
-    GtkTreeIter *iter);
-
 static void accounts_dialog_model_select_first (EmpathyAccountsDialog *dialog);
 
 static void accounts_dialog_update_settings (EmpathyAccountsDialog *dialog,
     EmpathyAccountSettings *settings);
 
-static void accounts_dialog_add (EmpathyAccountsDialog *dialog,
-    EmpathyAccountSettings *settings);
-
 static void accounts_dialog_model_set_selected (EmpathyAccountsDialog *dialog,
-    EmpathyAccountSettings *settings);
+    TpAccount *account);
 
 static void accounts_dialog_connection_changed_cb (TpAccount *account,
     guint old_status,
@@ -219,32 +197,47 @@ accounts_dialog_status_infobar_set_message (EmpathyAccountsDialog *dialog,
 
   message_markup = g_markup_printf_escaped ("<i>%s</i>", message);
   gtk_label_set_markup (GTK_LABEL (priv->label_status), message_markup);
+
+  gtk_widget_set_tooltip_text (priv->label_status, message);
+
   g_free (message_markup);
 }
 
 static void
-accounts_dialog_enable_account_cb (GObject *account,
+accounts_dialog_enable_account_cb (GObject *object,
     GAsyncResult *result,
     gpointer user_data)
 {
+  TpAccount *account = TP_ACCOUNT (object);
+  gboolean enable = GPOINTER_TO_UINT (user_data);
   GError *error = NULL;
+  TpAccountManager *am;
 
-  tp_account_set_enabled_finish (TP_ACCOUNT (account), result, &error);
-
-  if (error != NULL)
+  if (!tp_account_set_enabled_finish (account, result, &error))
     {
       DEBUG ("Could not enable the account: %s", error->message);
       g_error_free (error);
+      return;
     }
-  else
+
+  /* tp_account_is_enabled() is not updated yet at this point */
+  if (enable)
     {
-      TpAccountManager *am = tp_account_manager_dup ();
+      am = tp_account_manager_dup ();
 
-      empathy_connect_new_account (TP_ACCOUNT (account), am);
+      empathy_connect_new_account (account, am);
       g_object_unref (am);
     }
 }
 
+static void
+enable_and_connect_account (TpAccount *account,
+    gboolean enable)
+{
+  tp_account_set_enabled_async (account, enable,
+      accounts_dialog_enable_account_cb, GUINT_TO_POINTER (enable));
+}
+
 static void
 accounts_dialog_enable_switch_active_cb (GtkSwitch *sw,
     GParamSpec *spec,
@@ -252,6 +245,7 @@ accounts_dialog_enable_switch_active_cb (GtkSwitch *sw,
 {
   EmpathyAccountSettings *settings;
   TpAccount *account;
+  gboolean enable;
 
   settings = accounts_dialog_model_get_selected_settings (dialog);
   if (settings == NULL)
@@ -261,40 +255,84 @@ accounts_dialog_enable_switch_active_cb (GtkSwitch *sw,
   if (account == NULL)
     return;
 
-  tp_account_set_enabled_async (account, gtk_switch_get_active (sw),
-      accounts_dialog_enable_account_cb, NULL);
+  enable = gtk_switch_get_active (sw);
+
+  enable_and_connect_account (account, enable);
 }
 
 static void
-accounts_dialog_update_status_infobar (EmpathyAccountsDialog *dialog,
+install_haze_cb (GObject *source,
+    GAsyncResult *result,
+    gpointer user_data)
+{
+  GError *error = NULL;
+
+  if (!empathy_pkg_kit_install_packages_finish  (result, &error))
+    {
+      DEBUG ("Failed to install telepathy-haze: %s", error->message);
+
+      g_error_free (error);
+    }
+}
+
+static gboolean
+account_is_selected (EmpathyAccountsDialog *dialog,
     TpAccount *account)
 {
   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
-  gchar                     *status_message = NULL;
-  guint                     status;
-  guint                     reason;
-  guint                     presence;
-  GtkTreeView               *view;
-  GtkTreeModel              *model;
-  GtkTreeSelection          *selection;
-  GtkTreeIter               iter;
-  TpAccount                 *selected_account;
-  gboolean                  account_enabled;
-  gboolean                  creating_account;
-  TpStorageRestrictionFlags storage_restrictions = 0;
+  GtkTreeSelection *selection;
+  GtkTreeModel *model;
+  GtkTreeIter iter;
+  TpAccount *selected_account;
 
-  view = GTK_TREE_VIEW (priv->treeview);
-  selection = gtk_tree_view_get_selection (view);
+  if (account == NULL)
+    return FALSE;
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview));
 
   if (!gtk_tree_selection_get_selected (selection, &model, &iter))
-    return;
+    return FALSE;
 
   gtk_tree_model_get (model, &iter, COL_ACCOUNT, &selected_account, -1);
+
   if (selected_account != NULL)
     g_object_unref (selected_account);
 
+  return account == selected_account;
+}
+
+static gboolean
+account_can_be_enabled (TpAccount *account)
+{
+  TpStorageRestrictionFlags storage_restrictions;
+
+  storage_restrictions = tp_account_get_storage_restrictions (account);
+  if (storage_restrictions & TP_STORAGE_RESTRICTION_FLAG_CANNOT_SET_ENABLED)
+    return FALSE;
+
+  /* Butterfly accounts shouldn't be used any more */
+  if (!tp_strdiff (tp_account_get_cm_name (account),
+        "butterfly"))
+    return FALSE;
+
+  return TRUE;
+}
+
+static void
+accounts_dialog_update_status_infobar (EmpathyAccountsDialog *dialog,
+    TpAccount *account)
+{
+  EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
+  gchar                     *status_message = NULL;
+  guint                     status;
+  guint                     reason;
+  guint                     presence;
+  gboolean                  account_enabled;
+  gboolean                  creating_account;
+  gboolean display_switch = TRUE;
+
   /* do not update the infobar when the account is not selected */
-  if (account != selected_account)
+  if (!account_is_selected (dialog, account))
     return;
 
   if (account != NULL)
@@ -317,7 +355,7 @@ accounts_dialog_update_status_infobar (EmpathyAccountsDialog *dialog,
       if (!account_enabled)
         presence = TP_CONNECTION_PRESENCE_TYPE_OFFLINE;
 
-      storage_restrictions = tp_account_get_storage_restrictions (account);
+      display_switch = account_can_be_enabled (account);
     }
   else
     {
@@ -339,8 +377,7 @@ accounts_dialog_update_status_infobar (EmpathyAccountsDialog *dialog,
       accounts_dialog_enable_switch_active_cb, dialog);
 
   /* Display the Enable switch if account supports it */
-  gtk_widget_set_visible (priv->enabled_switch,
-      !(storage_restrictions & TP_STORAGE_RESTRICTION_FLAG_CANNOT_SET_ENABLED));
+  gtk_widget_set_visible (priv->enabled_switch, display_switch);
 
   if (account_enabled)
     {
@@ -410,7 +447,7 @@ accounts_dialog_update_status_infobar (EmpathyAccountsDialog *dialog,
                 g_free (message);
               }
 
-            if (!empathy_connectivity_is_online (priv->connectivity))
+            if (!g_network_monitor_get_network_available (priv->connectivity))
                accounts_dialog_status_infobar_set_message (dialog,
                     _("Offline — No Network Connection"));
 
@@ -430,8 +467,24 @@ accounts_dialog_update_status_infobar (EmpathyAccountsDialog *dialog,
     }
   else
     {
-      accounts_dialog_status_infobar_set_message (dialog,
-          _("Offline — Account Disabled"));
+      if (!tp_strdiff (tp_account_get_cm_name (account),
+            "butterfly"))
+        {
+          const gchar *packages[] = { "telepathy-haze", NULL };
+
+          accounts_dialog_status_infobar_set_message (dialog,
+              _("This account has been disabled because it relies on an old, "
+                "unsupported backend. Please install telepathy-haze and "
+                "restart your session to migrate the account."));
+
+          empathy_pkg_kit_install_packages_async (0, packages, NULL, NULL,
+              install_haze_cb, NULL);
+        }
+      else
+        {
+          accounts_dialog_status_infobar_set_message (dialog,
+              _("Offline — Account Disabled"));
+        }
 
       gtk_info_bar_set_message_type (GTK_INFO_BAR (priv->infobar),
           GTK_MESSAGE_WARNING);
@@ -471,7 +524,7 @@ empathy_account_dialog_cancel (EmpathyAccountsDialog *dialog)
       COL_ACCOUNT_SETTINGS, &settings,
       COL_ACCOUNT, &account, -1);
 
-  empathy_account_widget_discard_pending_changes (priv->setting_widget_object);
+  empathy_account_widget_discard_pending_changes (priv->setting_widget);
 
   if (account == NULL)
     {
@@ -503,28 +556,6 @@ empathy_account_dialog_widget_cancelled_cb (
   empathy_account_dialog_cancel (dialog);
 }
 
-static void
-empathy_account_dialog_account_created_cb (EmpathyAccountWidget *widget_object,
-    TpAccount *account,
-    EmpathyAccountsDialog *dialog)
-{
-  EmpathyAccountSettings *settings =
-      accounts_dialog_model_get_selected_settings (dialog);
-  EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
-
-  accounts_dialog_update_settings (dialog, settings);
-  accounts_dialog_update_status_infobar (dialog,
-      empathy_account_settings_get_account (settings));
-
-  gtk_widget_set_sensitive (priv->treeview, TRUE);
-  gtk_widget_set_sensitive (priv->button_add, TRUE);
-  gtk_widget_set_sensitive (priv->button_remove, TRUE);
-  gtk_widget_set_sensitive (priv->button_import, TRUE);
-
-  if (settings)
-    g_object_unref (settings);
-}
-
 static gboolean
 accounts_dialog_has_valid_accounts (EmpathyAccountsDialog *dialog)
 {
@@ -533,7 +564,7 @@ accounts_dialog_has_valid_accounts (EmpathyAccountsDialog *dialog)
   GtkTreeIter iter;
   gboolean creating;
 
-  g_object_get (priv->setting_widget_object,
+  g_object_get (priv->setting_widget,
       "creating-account", &creating, NULL);
 
   if (!creating)
@@ -552,33 +583,33 @@ account_dialog_create_edit_params_dialog (EmpathyAccountsDialog *dialog)
 {
   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
   EmpathyAccountSettings *settings;
-  GtkWidget *subdialog, *content, *content_area, *align;
+  GtkWidget *subdialog, *content_area, *align;
 
   settings = accounts_dialog_model_get_selected_settings (dialog);
+  if (settings == NULL)
+    return;
 
   subdialog = gtk_dialog_new_with_buttons (_("Edit Connection Parameters"),
       GTK_WINDOW (dialog),
       GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
       NULL, NULL);
 
-  priv->setting_widget_object =
+  gtk_window_set_resizable (GTK_WINDOW (subdialog), FALSE);
+
+  priv->setting_widget = (EmpathyAccountWidget *)
     empathy_account_widget_new_for_protocol (settings, FALSE);
 
-  g_object_add_weak_pointer (G_OBJECT (priv->setting_widget_object),
-      (gpointer *) &priv->setting_widget_object);
+  g_object_add_weak_pointer (G_OBJECT (priv->setting_widget),
+      (gpointer *) &priv->setting_widget);
 
   if (accounts_dialog_has_valid_accounts (dialog))
     empathy_account_widget_set_other_accounts_exist (
-        priv->setting_widget_object, TRUE);
+        priv->setting_widget, TRUE);
 
-  content = empathy_account_widget_get_widget (priv->setting_widget_object);
-
-  g_signal_connect (priv->setting_widget_object, "account-created",
-        G_CALLBACK (empathy_account_dialog_account_created_cb), dialog);
-  g_signal_connect (priv->setting_widget_object, "cancelled",
+  g_signal_connect (priv->setting_widget, "cancelled",
           G_CALLBACK (empathy_account_dialog_widget_cancelled_cb), dialog);
 
-  g_signal_connect_swapped (priv->setting_widget_object, "close",
+  g_signal_connect_swapped (priv->setting_widget, "close",
       G_CALLBACK (gtk_widget_destroy), subdialog);
 
   content_area = gtk_dialog_get_content_area (GTK_DIALOG (subdialog));
@@ -586,77 +617,74 @@ account_dialog_create_edit_params_dialog (EmpathyAccountsDialog *dialog)
   align = gtk_alignment_new (0.5, 0.5, 1, 1);
   gtk_alignment_set_padding (GTK_ALIGNMENT (align), 6, 0, 6, 6);
 
-  gtk_container_add (GTK_CONTAINER (align), content);
+  gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET (priv->setting_widget));
   gtk_box_pack_start (GTK_BOX (content_area), align, TRUE, TRUE, 0);
 
-  gtk_widget_show (content);
+  gtk_widget_show (GTK_WIDGET (priv->setting_widget));
   gtk_widget_show (align);
   gtk_widget_show (subdialog);
 }
 
 static void
-account_dialow_show_edit_params_dialog (EmpathyAccountsDialog *dialog,
-    GtkButton *button)
-{
-  DEBUG ("clicked");
-
-  account_dialog_create_edit_params_dialog (dialog);
-}
-
-static void
-account_dialog_show_contact_details_failed (EmpathyAccountsDialog *dialog,
-    gboolean error)
+use_external_storage_provider (EmpathyAccountsDialog *self,
+    TpAccount *account)
 {
-  EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
-  GtkWidget *infobar, *label;
+  const gchar *provider;
 
-  infobar = gtk_info_bar_new ();
-
-  if (error)
+  provider = tp_account_get_storage_provider (account);
+  if (!tp_strdiff (provider, "com.meego.libsocialweb"))
+    {
+      empathy_launch_external_app ("gnome-control-center.desktop",
+          "bisho.desktop", NULL);
+      return;
+    }
+  else if (!tp_strdiff (provider, EMPATHY_GOA_PROVIDER))
     {
-      gtk_info_bar_set_message_type (GTK_INFO_BAR (infobar), GTK_MESSAGE_ERROR);
-      label = gtk_label_new (_("Failed to retrieve your personal information "
-                               "from the server."));
+      empathy_launch_external_app ("gnome-online-accounts-panel.desktop",
+          NULL, NULL);
+      return;
+    }
+  else if (!tp_strdiff (provider, EMPATHY_UOA_PROVIDER))
+    {
+      empathy_launch_external_app ("gnome-credentials-panel.desktop",
+          NULL, NULL);
+      return;
     }
   else
     {
-      gtk_info_bar_set_message_type (GTK_INFO_BAR (infobar), GTK_MESSAGE_INFO);
-      label = gtk_label_new (_("Go online to edit your personal information."));
+      DEBUG ("Don't know how to handle %s", provider);
+      return;
     }
-
-  gtk_container_add (
-      GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (infobar))),
-      label);
-  gtk_box_pack_start (GTK_BOX (priv->dialog_content), infobar, FALSE, FALSE, 0);
-  gtk_widget_show_all (infobar);
 }
 
 static void
-account_dialog_got_self_contact (TpConnection *conn,
-    EmpathyContact *contact,
-    const GError *in_error,
-    gpointer user_data,
-    GObject *dialog)
+account_dialow_show_edit_params_dialog (EmpathyAccountsDialog *dialog,
+    GtkButton *button)
 {
-  EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
-  GtkWidget *editor;
+  EmpathyAccountSettings *settings;
+  TpAccount *account;
+  TpStorageRestrictionFlags storage_restrictions;
+
+  settings = accounts_dialog_model_get_selected_settings (dialog);
+  if (settings == NULL)
+    return;
+
+  account = empathy_account_settings_get_account (settings);
+  g_return_if_fail (account != NULL);
+
+  storage_restrictions = tp_account_get_storage_restrictions (account);
 
-  if (in_error != NULL)
+  /* Empathy can only edit accounts without the Cannot_Set_Parameters flag */
+  if (storage_restrictions & TP_STORAGE_RESTRICTION_FLAG_CANNOT_SET_PARAMETERS)
     {
-      DEBUG ("Failed to get self-contact: %s", in_error->message);
-      account_dialog_show_contact_details_failed (
-          EMPATHY_ACCOUNTS_DIALOG (dialog), TRUE);
-      return;
-    }
+      DEBUG ("Account is provided by an external storage provider");
 
-  /* create the contact info editor for this account */
-  editor = empathy_contact_widget_new (contact,
-      EMPATHY_CONTACT_WIDGET_EDIT_ALIAS |
-      EMPATHY_CONTACT_WIDGET_EDIT_AVATAR |
-      EMPATHY_CONTACT_WIDGET_NO_STATUS |
-      EMPATHY_CONTACT_WIDGET_EDIT_DETAILS);
-  gtk_box_pack_start (GTK_BOX (priv->dialog_content), editor, FALSE, FALSE, 0);
-  gtk_widget_show (editor);
+      use_external_storage_provider (dialog, account);
+    }
+  else
+    {
+      account_dialog_create_edit_params_dialog (dialog);
+    }
 }
 
 static void
@@ -666,43 +694,28 @@ account_dialog_create_dialog_content (EmpathyAccountsDialog *dialog,
   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
   const gchar *icon_name;
   TpAccount *account;
-  TpConnection *conn = NULL;
   GtkWidget *bbox, *button;
+  GtkWidget *alig;
 
   account = empathy_account_settings_get_account (settings);
 
-  // if (priv->setting_widget_object != NULL)
-  //   g_object_remove_weak_pointer (G_OBJECT (priv->setting_widget_object),
-  //       (gpointer *) &priv->setting_widget_object);
-
-  priv->dialog_content = gtk_vbox_new (FALSE, 6);
-  // FIXME: should align to the top
+  priv->dialog_content = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
   gtk_container_add (GTK_CONTAINER (priv->alignment_settings),
       priv->dialog_content);
   gtk_widget_show (priv->dialog_content);
 
-  /* request the self contact */
-  if (account != NULL)
-    conn = tp_account_get_connection (account);
-
-  if (conn != NULL)
-    {
-      empathy_tp_contact_factory_get_from_handle (conn,
-          tp_connection_get_self_handle (conn),
-          account_dialog_got_self_contact,
-          NULL, NULL, G_OBJECT (dialog));
-    }
-  else
-    {
-      account_dialog_show_contact_details_failed (dialog, FALSE);
-    }
+  alig = gtk_alignment_new (0.5, 0, 1, 1);
+  priv->user_info = empathy_user_info_new (account);
+  gtk_container_add (GTK_CONTAINER (alig), priv->user_info);
+  gtk_box_pack_start (GTK_BOX (priv->dialog_content), alig, TRUE, TRUE, 0);
+  gtk_widget_show (alig);
+  gtk_widget_show (priv->user_info);
 
-  bbox = gtk_hbutton_box_new ();
+  bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
   gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
   gtk_box_pack_end (GTK_BOX (priv->dialog_content), bbox, FALSE, TRUE, 0);
   gtk_widget_show (bbox);
 
-  /* FIXME: make this handle external accounts */
   button = gtk_button_new_with_mnemonic (_("_Edit Connection Parameters..."));
   gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, TRUE, 0);
   gtk_widget_show (button);
@@ -778,100 +791,9 @@ accounts_dialog_has_pending_change (EmpathyAccountsDialog *dialog,
   if (gtk_tree_selection_get_selected (selection, &model, &iter))
     gtk_tree_model_get (model, &iter, COL_ACCOUNT, account, -1);
 
-  return priv->setting_widget_object != NULL
+  return priv->setting_widget != NULL
       && empathy_account_widget_contains_pending_changes (
-          priv->setting_widget_object);
-}
-
-static void
-accounts_dialog_setup_ui_to_add_account (EmpathyAccountsDialog *dialog)
-{
-  EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
-  EmpathyAccountSettings *settings;
-
-  settings = empathy_protocol_chooser_create_account_settings (
-      EMPATHY_PROTOCOL_CHOOSER (priv->combobox_protocol));
-  if (settings == NULL)
-    return;
-
-  accounts_dialog_add (dialog, settings);
-  accounts_dialog_model_set_selected (dialog, settings);
-
-  gtk_widget_show_all (priv->hbox_protocol);
-
-  g_object_unref (settings);
-}
-
-static void
-accounts_dialog_protocol_changed_cb (GtkWidget *widget,
-    EmpathyAccountsDialog *dialog)
-{
-  EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
-  GtkTreeSelection *selection;
-  GtkTreeModel *model;
-  GtkTreeIter iter;
-  gboolean creating;
-  EmpathyAccountSettings *settings;
-  gchar *account = NULL, *password = NULL;
-
-  /* The "changed" signal is fired during the initiation of the
-   * EmpathyProtocolChooser while populating the widget. Such signals should
-   * be ignored so we check if we are actually creating a new account. */
-  if (priv->setting_widget_object == NULL)
-    return;
-
-  g_object_get (priv->setting_widget_object,
-      "creating-account", &creating, NULL);
-  if (!creating)
-    return;
-
-  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview));
-
-  if (!gtk_tree_selection_get_selected (selection, &model, &iter))
-    return;
-
-  /* Save "account" and "password" parameters */
-  g_object_get (priv->setting_widget_object, "settings", &settings, NULL);
-
-  if (settings != NULL)
-    {
-      account = g_strdup (empathy_account_settings_get_string (settings,
-            "account"));
-      password = g_strdup (empathy_account_settings_get_string (settings,
-            "password"));
-      g_object_unref (settings);
-    }
-
-  /* We are creating a new widget to replace the current one, don't ask
-   * confirmation to the user. */
-  priv->force_change_row = TRUE;
-
-  /* We'll update the selection after we create the new account widgets;
-   * updating it right now causes problems for the # of accounts = zero case */
-  g_signal_handlers_block_by_func (selection,
-      accounts_dialog_model_selection_changed, dialog);
-
-  gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
-
-  g_signal_handlers_unblock_by_func (selection,
-      accounts_dialog_model_selection_changed, dialog);
-
-  accounts_dialog_setup_ui_to_add_account (dialog);
-
-  /* Restore "account" and "password" parameters in the new widget */
-  if (account != NULL)
-    {
-      empathy_account_widget_set_account_param (priv->setting_widget_object,
-          account);
-      g_free (account);
-    }
-
-  if (password != NULL)
-    {
-      empathy_account_widget_set_password_param (priv->setting_widget_object,
-          password);
-      g_free (password);
-    }
+          priv->setting_widget);
 }
 
 static void
@@ -932,10 +854,32 @@ get_dialog_primary_text (TpAccount *account)
 
 static void
 accounts_dialog_button_add_clicked_cb (GtkWidget *button,
-    EmpathyAccountsDialog *dialog)
+    EmpathyAccountsDialog *self)
 {
-  accounts_dialog_setup_ui_to_add_account (dialog);
-  account_dialog_create_edit_params_dialog (dialog);
+  GtkWidget *dialog;
+  gint response;
+
+  dialog = empathy_new_account_dialog_new (GTK_WINDOW (self));
+  gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+
+  response = gtk_dialog_run (GTK_DIALOG (dialog));
+
+  if (response == GTK_RESPONSE_APPLY)
+    {
+      EmpathyAccountSettings *settings;
+      TpAccount *account;
+
+      settings = empathy_new_account_dialog_get_settings (
+          EMPATHY_NEW_ACCOUNT_DIALOG (dialog));
+
+      /* The newly created account has already been added by
+       * accounts_dialog_account_validity_changed_cb so we just
+       * have to select it. */
+      account = empathy_account_settings_get_account (settings);
+      accounts_dialog_model_set_selected (self, account);
+    }
+
+  gtk_widget_destroy (dialog);
 }
 
 static void
@@ -971,29 +915,27 @@ accounts_dialog_update_settings (EmpathyAccountsDialog *dialog,
 
           return;
         }
-      if (empathy_connection_managers_get_cms_num (priv->cms) > 0)
-        {
-          /* We have no account configured but we have some
-           * profiles installed. The user obviously wants to add
-           * an account. Click on the Add button for him. */
-          accounts_dialog_button_add_clicked_cb (priv->button_add,
-              dialog);
-          return;
-        }
 
-      /* No account and no profile, warn the user */
+      /* No account selected */
       gtk_widget_hide (priv->vbox_details);
-      gtk_widget_show (priv->frame_no_protocol);
-      gtk_widget_set_sensitive (priv->button_add, FALSE);
+      gtk_widget_set_sensitive (priv->button_add, TRUE);
+      gtk_widget_set_sensitive (priv->button_remove, FALSE);
+
+      gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook_account),
+          NOTEBOOK_PAGE_NO_PROTOCOL);
       return;
     }
 
   /* We have an account selected, destroy old settings and create a new
    * one for the account selected */
-  gtk_widget_hide (priv->frame_no_protocol);
   gtk_widget_show (priv->vbox_details);
-  gtk_widget_hide (priv->hbox_protocol);
 
+  if (priv->user_info != NULL)
+    {
+      empathy_user_info_apply_async ((EmpathyUserInfo *) priv->user_info,
+          NULL, NULL);
+      priv->user_info = NULL;
+    }
   if (priv->dialog_content)
     {
       gtk_widget_destroy (priv->dialog_content);
@@ -1078,6 +1020,28 @@ get_status_icon_for_account (EmpathyAccountsDialog *self,
   return empathy_icon_name_for_presence (presence);
 }
 
+static GdkPixbuf *
+ensure_icon (EmpathyAccountsDialog *self,
+    const gchar *icon_name)
+{
+  EmpathyAccountsDialogPriv *priv = GET_PRIV (self);
+  GdkPixbuf *pixbuf;
+
+  pixbuf = g_hash_table_lookup (priv->icons_cache, icon_name);
+  if (pixbuf == NULL)
+    {
+      pixbuf = empathy_pixbuf_from_icon_name (icon_name, GTK_ICON_SIZE_BUTTON);
+
+      if (pixbuf == NULL)
+        return NULL;
+
+      g_hash_table_insert (priv->icons_cache, g_strdup (icon_name),
+          pixbuf);
+    }
+
+  return g_object_ref (pixbuf);
+}
+
 static void
 accounts_dialog_model_status_pixbuf_data_func (GtkTreeViewColumn *tree_column,
     GtkCellRenderer *cell,
@@ -1086,15 +1050,23 @@ accounts_dialog_model_status_pixbuf_data_func (GtkTreeViewColumn *tree_column,
     EmpathyAccountsDialog *dialog)
 {
   TpAccount *account;
+  const gchar *icon_name;
+  GdkPixbuf *pixbuf;
 
   gtk_tree_model_get (model, iter, COL_ACCOUNT, &account, -1);
 
+  icon_name = get_status_icon_for_account (dialog, account);
+  pixbuf = ensure_icon (dialog, icon_name);
+
   g_object_set (cell,
-      "icon-name", get_status_icon_for_account (dialog, account),
+      "pixbuf", pixbuf,
       NULL);
 
   if (account != NULL)
     g_object_unref (account);
+
+  if (pixbuf != NULL)
+    g_object_unref (pixbuf);
 }
 
 static void
@@ -1115,7 +1087,7 @@ accounts_dialog_model_protocol_pixbuf_data_func (GtkTreeViewColumn *tree_column,
       -1);
 
   icon_name = empathy_account_settings_get_icon_name (settings);
-  pixbuf = empathy_pixbuf_from_icon_name (icon_name, GTK_ICON_SIZE_BUTTON);
+  pixbuf = ensure_icon (dialog, icon_name);
 
   g_object_set (cell,
       "visible", TRUE,
@@ -1308,24 +1280,6 @@ accounts_dialog_button_remove_clicked_cb (GtkWidget *button,
   accounts_dialog_remove_account_iter (dialog, &iter);
 }
 
-#ifdef HAVE_MEEGO
-static void
-accounts_dialog_view_delete_activated_cb (EmpathyCellRendererActivatable *cell,
-    const gchar *path_string,
-    EmpathyAccountsDialog *dialog)
-{
-  EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
-  GtkTreeModel *model;
-  GtkTreeIter iter;
-
-  model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
-  if (!gtk_tree_model_get_iter_from_string (model, &iter, path_string))
-    return;
-
-  accounts_dialog_remove_account_iter (dialog, &iter);
-}
-#endif /* HAVE_MEEGO */
-
 static void
 accounts_dialog_model_add_columns (EmpathyAccountsDialog *dialog)
 {
@@ -1361,35 +1315,22 @@ accounts_dialog_model_add_columns (EmpathyAccountsDialog *dialog)
       NULL);
 
   /* Name renderer */
-  cell = gtk_cell_renderer_text_new ();
-  g_object_set (cell,
+  priv->name_renderer = gtk_cell_renderer_text_new ();
+  g_object_set (priv->name_renderer,
       "ellipsize", PANGO_ELLIPSIZE_END,
       "width-chars", 25,
       "editable", TRUE,
       NULL);
-  gtk_tree_view_column_pack_start (column, cell, TRUE);
-  gtk_tree_view_column_add_attribute (column, cell, "text", COL_NAME);
-  g_signal_connect (cell, "edited",
+  gtk_tree_view_column_pack_start (column, priv->name_renderer, TRUE);
+  gtk_tree_view_column_add_attribute (column, priv->name_renderer,
+      "text", COL_NAME);
+  g_signal_connect (priv->name_renderer, "edited",
       G_CALLBACK (accounts_dialog_name_edited_cb),
       dialog);
-  g_signal_connect (cell, "editing-started",
+  g_signal_connect (priv->name_renderer, "editing-started",
       G_CALLBACK (accounts_dialog_name_editing_started_cb),
       dialog);
-  g_object_set (cell, "ypad", 4, NULL);
-
-#ifdef HAVE_MEEGO
-  /* Delete column */
-  cell = empathy_cell_renderer_activatable_new ();
-  gtk_tree_view_column_pack_start (column, cell, FALSE);
-  g_object_set (cell,
-        "icon-name", GTK_STOCK_DELETE,
-        "show-on-select", TRUE,
-        NULL);
-
-  g_signal_connect (cell, "path-activated",
-      G_CALLBACK (accounts_dialog_view_delete_activated_cb),
-      dialog);
-#endif /* HAVE_MEEGO */
+  g_object_set (priv->name_renderer, "ypad", 4, NULL);
 }
 
 static EmpathyAccountSettings *
@@ -1433,9 +1374,9 @@ accounts_dialog_model_selection_changed (GtkTreeSelection *selection,
   if (settings != NULL)
     g_object_unref (settings);
 
-  if (priv->setting_widget_object != NULL)
+  if (priv->setting_widget != NULL)
     {
-      g_object_get (priv->setting_widget_object,
+      g_object_get (priv->setting_widget,
           "creating-account", &creating, NULL);
     }
 
@@ -1464,7 +1405,7 @@ accounts_dialog_selection_change_response_cb (GtkDialog *message_dialog,
 
         priv->force_change_row = TRUE;
         empathy_account_widget_discard_pending_changes (
-            priv->setting_widget_object);
+            priv->setting_widget);
 
         path = gtk_tree_row_reference_get_path (priv->destination_row);
         selection = gtk_tree_view_get_selection (
@@ -1571,41 +1512,6 @@ accounts_dialog_model_setup (EmpathyAccountsDialog *dialog)
   g_object_unref (store);
 }
 
-static gboolean
-accounts_dialog_get_settings_iter (EmpathyAccountsDialog *dialog,
-    EmpathyAccountSettings *settings,
-    GtkTreeIter *iter)
-{
-  GtkTreeView      *view;
-  GtkTreeModel     *model;
-  gboolean          ok;
-  EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
-
-  /* Update the status in the model */
-  view = GTK_TREE_VIEW (priv->treeview);
-  model = gtk_tree_view_get_model (view);
-
-  for (ok = gtk_tree_model_get_iter_first (model, iter);
-       ok;
-       ok = gtk_tree_model_iter_next (model, iter))
-    {
-      EmpathyAccountSettings *this_settings;
-      gboolean   equal;
-
-      gtk_tree_model_get (model, iter,
-          COL_ACCOUNT_SETTINGS, &this_settings,
-          -1);
-
-      equal = (this_settings == settings);
-      g_object_unref (this_settings);
-
-      if (equal)
-        return TRUE;
-    }
-
-  return FALSE;
-}
-
 static gboolean
 accounts_dialog_get_account_iter (EmpathyAccountsDialog *dialog,
     TpAccount *account,
@@ -1624,15 +1530,15 @@ accounts_dialog_get_account_iter (EmpathyAccountsDialog *dialog,
        ok;
        ok = gtk_tree_model_iter_next (model, iter))
     {
-      EmpathyAccountSettings *settings;
+      TpAccount *this_account;
       gboolean   equal;
 
       gtk_tree_model_get (model, iter,
-          COL_ACCOUNT_SETTINGS, &settings,
+          COL_ACCOUNT, &this_account,
           -1);
 
-      equal = empathy_account_settings_has_account (settings, account);
-      g_object_unref (settings);
+      equal = (this_account == account);
+      g_object_unref (this_account);
 
       if (equal)
         return TRUE;
@@ -1665,11 +1571,11 @@ select_and_scroll_to_iter (EmpathyAccountsDialog *dialog,
 
 static void
 accounts_dialog_model_set_selected (EmpathyAccountsDialog *dialog,
-    EmpathyAccountSettings *settings)
+    TpAccount *account)
 {
   GtkTreeIter       iter;
 
-  if (accounts_dialog_get_settings_iter (dialog, settings, &iter))
+  if (accounts_dialog_get_account_iter (dialog, account, &iter))
     select_and_scroll_to_iter (dialog, &iter);
 }
 
@@ -1680,7 +1586,32 @@ accounts_dialog_treeview_enabled_cb (GtkMenuItem *item,
   gboolean enabled;
 
   enabled = tp_account_is_enabled (account);
-  tp_account_set_enabled_async (account, !enabled, NULL, NULL);
+
+  enable_and_connect_account (account, !enabled);
+}
+
+static void
+accounts_dialog_treeview_rename_cb (GtkMenuItem *item,
+    EmpathyAccountsDialog *self)
+{
+  EmpathyAccountsDialogPriv *priv = GET_PRIV (self);
+  GtkTreePath *path;
+  GtkTreeIter iter;
+  GtkTreeSelection *selection;
+  GtkTreeModel *model;
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview));
+  if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+    return;
+  path = gtk_tree_model_get_path (model, &iter);
+
+  g_object_set (G_OBJECT (priv->name_renderer), "editable", TRUE, NULL);
+
+  gtk_widget_grab_focus (GTK_WIDGET (priv->treeview));
+  gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->treeview), path,
+      gtk_tree_view_get_column (GTK_TREE_VIEW (priv->treeview), 0), TRUE);
+
+  gtk_tree_path_free (path);
 }
 
 static gboolean
@@ -1694,8 +1625,7 @@ accounts_dialog_treeview_button_press_event_cb (GtkTreeView *view,
   GtkTreePath *path = NULL;
   GtkTreeIter iter;
   GtkWidget *menu;
-  GtkWidget *item_enable, *item_disable;
-  GtkWidget *image_enable, *image_disable;
+  GtkWidget *item;
 
   /* ignore multiple clicks */
   if (event->type != GDK_BUTTON_PRESS)
@@ -1718,41 +1648,37 @@ accounts_dialog_treeview_button_press_event_cb (GtkTreeView *view,
   /* Create the menu */
   menu = empathy_context_menu_new (GTK_WIDGET (view));
 
-  /* Get images for menu items */
-  image_enable = gtk_image_new_from_icon_name (empathy_icon_name_for_presence (
-        tp_account_manager_get_most_available_presence (
-          priv->account_manager, NULL, NULL)),
-      GTK_ICON_SIZE_MENU);
-  image_disable = gtk_image_new_from_icon_name (
-      empathy_icon_name_for_presence (TP_CONNECTION_PRESENCE_TYPE_OFFLINE),
-      GTK_ICON_SIZE_MENU);
-
-  /* Menu items: to enabled/disable the account */
-  item_enable = gtk_image_menu_item_new_with_mnemonic (_("_Enable"));
-  item_disable = gtk_image_menu_item_new_with_mnemonic (_("_Disable"));
-  gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item_enable),
-      image_enable);
-  gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item_disable),
-      image_disable);
-
-  gtk_menu_shell_append (GTK_MENU_SHELL (menu), item_enable);
-  gtk_menu_shell_append (GTK_MENU_SHELL (menu), item_disable);
-
-  if (tp_account_is_enabled (account))
-    {
-      tp_g_signal_connect_object (item_disable, "activate",
+  /* Menu item: to enabled/disable the account */
+  item = gtk_check_menu_item_new_with_mnemonic (_("_Enabled"));
+
+  gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+
+  if (account_can_be_enabled (account))
+    {
+      gboolean active;
+
+      active = tp_account_is_enabled (account);
+      gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item),
+          active);
+
+      tp_g_signal_connect_object (item, "activate",
           G_CALLBACK (accounts_dialog_treeview_enabled_cb), account, 0);
-      gtk_widget_set_sensitive (item_enable, FALSE);
     }
   else
     {
-      tp_g_signal_connect_object (item_enable, "activate",
-          G_CALLBACK (accounts_dialog_treeview_enabled_cb), account, 0);
-      gtk_widget_set_sensitive (item_disable, FALSE);
+      gtk_widget_set_sensitive (item, FALSE);
     }
 
-  gtk_widget_show (item_enable);
-  gtk_widget_show (item_disable);
+  gtk_widget_show (item);
+
+  /* Menu item: Rename */
+  item = gtk_menu_item_new_with_mnemonic (_("Rename"));
+  gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+
+  tp_g_signal_connect_object (item, "activate",
+      G_CALLBACK (accounts_dialog_treeview_rename_cb), dialog, 0);
+
+  gtk_widget_show (item);
 
   /* FIXME: Add here presence items, to be able to set per-account presence */
 
@@ -1768,24 +1694,12 @@ finally:
 }
 
 static void
-accounts_dialog_add (EmpathyAccountsDialog *dialog,
-    EmpathyAccountSettings *settings)
+reload_account_widget (EmpathyAccountsDialog *self)
 {
-  GtkTreeModel       *model;
-  GtkTreeIter         iter;
-  const gchar        *name;
-  EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
-
-  model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
-  name = empathy_account_settings_get_display_name (settings);
-
-  gtk_list_store_append (GTK_LIST_STORE (model), &iter);
+  EmpathyAccountSettings *settings;
 
-  gtk_list_store_set (GTK_LIST_STORE (model), &iter,
-      COL_NAME, name,
-      COL_STATUS, TP_CONNECTION_STATUS_DISCONNECTED,
-      COL_ACCOUNT_SETTINGS, settings,
-      -1);
+  settings = accounts_dialog_model_get_selected_settings (self);
+  accounts_dialog_update_settings (self, settings);
 }
 
 static void
@@ -1901,6 +1815,40 @@ accounts_dialog_account_display_name_changed_cb (TpAccount *account,
   g_object_unref (settings);
 }
 
+static void
+conn_prepare_cb (GObject *source,
+    GAsyncResult *result,
+    gpointer user_data)
+{
+  EmpathyAccountsDialog *self = user_data;
+
+  reload_account_widget (self);
+}
+
+static void
+accounts_dialog_notify_connection_cb (TpAccount *account,
+    GParamSpec *spec,
+    EmpathyAccountsDialog *self)
+{
+  TpConnection *conn;
+  if (!account_is_selected (self, account))
+    return;
+
+  conn = tp_account_get_connection (account);
+  if (conn == NULL)
+    {
+      reload_account_widget (self);
+    }
+  else
+    {
+      /* Wait for this feature so TpConnection will have fetch the
+       * self handle */
+      GQuark features[] = { TP_CONNECTION_FEATURE_CONNECTED, 0 };
+
+      tp_proxy_prepare_async (conn, features, conn_prepare_cb, self);
+    }
+}
+
 static void
 accounts_dialog_add_account (EmpathyAccountsDialog *dialog,
     TpAccount *account)
@@ -1912,6 +1860,7 @@ accounts_dialog_add_account (EmpathyAccountsDialog *dialog,
   const gchar        *name;
   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
   gboolean selected = FALSE;
+  GtkTreeSelection *selection;
 
   model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
   status = tp_account_get_connection_status (account, NULL);
@@ -1919,24 +1868,32 @@ accounts_dialog_add_account (EmpathyAccountsDialog *dialog,
 
   settings = empathy_account_settings_new_for_account (account);
 
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview));
+
   if (!accounts_dialog_get_account_iter (dialog, account, &iter))
     {
-      gtk_list_store_append (GTK_LIST_STORE (model), &iter);
+      /* Select the account if it's the first added */
+      if (gtk_tree_selection_count_selected_rows (selection) == 0)
+        selected = TRUE;
+
+      gtk_list_store_insert_with_values (GTK_LIST_STORE (model), &iter, -1,
+          COL_NAME, name,
+          COL_STATUS, status,
+          COL_ACCOUNT, account,
+          COL_ACCOUNT_SETTINGS, settings,
+          -1);
     }
   else
     {
-      GtkTreeSelection *selection;
-
-      selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview));
       selected = gtk_tree_selection_iter_is_selected (selection, &iter);
-    }
 
-  gtk_list_store_set (GTK_LIST_STORE (model), &iter,
-      COL_NAME, name,
-      COL_STATUS, status,
-      COL_ACCOUNT, account,
-      COL_ACCOUNT_SETTINGS, settings,
-      -1);
+      gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+          COL_NAME, name,
+          COL_STATUS, status,
+          COL_ACCOUNT, account,
+          COL_ACCOUNT_SETTINGS, settings,
+          -1);
+    }
 
   if (selected)
     {
@@ -1962,36 +1919,19 @@ accounts_dialog_add_account (EmpathyAccountsDialog *dialog,
       G_CALLBACK (accounts_dialog_connection_changed_cb), dialog, 0);
   tp_g_signal_connect_object (account, "presence-changed",
       G_CALLBACK (accounts_dialog_presence_changed_cb), dialog, 0);
+  tp_g_signal_connect_object (account, "notify::connection",
+      G_CALLBACK (accounts_dialog_notify_connection_cb), dialog, 0);
 
   g_object_unref (settings);
 }
 
-static void
-account_prepare_cb (GObject *source_object,
-    GAsyncResult *result,
-    gpointer user_data)
-{
-  EmpathyAccountsDialog *dialog = EMPATHY_ACCOUNTS_DIALOG (user_data);
-  TpAccount *account = TP_ACCOUNT (source_object);
-  GError *error = NULL;
-
-  if (!tp_proxy_prepare_finish (account, result, &error))
-    {
-      DEBUG ("Failed to prepare account: %s", error->message);
-      g_error_free (error);
-      return;
-    }
-
-  accounts_dialog_add_account (dialog, account);
-}
-
 static void
 accounts_dialog_account_validity_changed_cb (TpAccountManager *manager,
     TpAccount *account,
     gboolean valid,
     EmpathyAccountsDialog *dialog)
 {
-  tp_proxy_prepare_async (account, NULL, account_prepare_cb, dialog);
+  accounts_dialog_add_account (dialog, account);
 }
 
 static void
@@ -2002,11 +1942,11 @@ accounts_dialog_accounts_model_row_inserted_cb (GtkTreeModel *model,
 {
   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
 
-  if (priv->setting_widget_object != NULL &&
+  if (priv->setting_widget != NULL &&
       accounts_dialog_has_valid_accounts (dialog))
     {
       empathy_account_widget_set_other_accounts_exist (
-          priv->setting_widget_object, TRUE);
+          priv->setting_widget, TRUE);
     }
 }
 
@@ -2017,11 +1957,11 @@ accounts_dialog_accounts_model_row_deleted_cb (GtkTreeModel *model,
 {
   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
 
-  if (priv->setting_widget_object != NULL &&
+  if (priv->setting_widget != NULL &&
       !accounts_dialog_has_valid_accounts (dialog))
     {
       empathy_account_widget_set_other_accounts_exist (
-          priv->setting_widget_object, FALSE);
+          priv->setting_widget, FALSE);
     }
 }
 
@@ -2070,15 +2010,24 @@ accounts_dialog_account_enabled_cb (TpAccountManager *manager,
   enable_or_disable_account (dialog, account, TRUE);
 }
 
-static void
-accounts_dialog_button_import_clicked_cb (GtkWidget *button,
-    EmpathyAccountsDialog *dialog)
+static GtkWidget *
+display_import_dialog (EmpathyAccountsDialog *dialog)
 {
+  EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
   GtkWidget *import_dialog;
 
   import_dialog = empathy_import_dialog_new (GTK_WINDOW (dialog),
-      FALSE);
+      FALSE, priv->cms);
   gtk_widget_show (import_dialog);
+
+  return import_dialog;
+}
+
+static void
+accounts_dialog_button_import_clicked_cb (GtkWidget *button,
+    EmpathyAccountsDialog *dialog)
+{
+  display_import_dialog (dialog);
 }
 
 static void
@@ -2113,6 +2062,87 @@ accounts_dialog_set_selected_account (EmpathyAccountsDialog *dialog,
     select_and_scroll_to_iter (dialog, &iter);
 }
 
+static void
+salut_valid_cb (GtkWidget *widget,
+    gboolean valid,
+    GtkWidget *button)
+{
+  gtk_widget_set_sensitive (button, valid);
+}
+
+static void
+maybe_show_salut_dialog (EmpathyAccountsDialog *self)
+{
+  EmpathyAccountsDialogPriv *priv = GET_PRIV (self);
+  GtkWidget *dialog, *widget, *content, *button;
+  gint response;
+
+  if (!empathy_local_xmpp_assistant_widget_should_create_account (
+        priv->account_manager))
+    return;
+
+  widget = empathy_local_xmpp_assistant_widget_new ();
+  gtk_widget_show (widget);
+
+  dialog = gtk_dialog_new ();
+
+  gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+
+  gtk_dialog_add_button (GTK_DIALOG (dialog), _("_Skip"),
+      GTK_RESPONSE_NO);
+
+  button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+      _("_Connect"), GTK_RESPONSE_YES);
+  gtk_widget_set_sensitive (button,
+      empathy_local_xmpp_assistant_widget_is_valid (
+        EMPATHY_LOCAL_XMPP_ASSISTANT_WIDGET (widget)));
+
+  g_signal_connect (widget, "valid", G_CALLBACK (salut_valid_cb),
+      button);
+
+  content = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+  gtk_box_pack_start (GTK_BOX (content), widget, TRUE, TRUE, 0);
+
+  response = gtk_dialog_run (GTK_DIALOG (dialog));
+
+  if (response == GTK_RESPONSE_YES)
+    {
+      empathy_local_xmpp_assistant_widget_create_account (
+          EMPATHY_LOCAL_XMPP_ASSISTANT_WIDGET (widget));
+    }
+
+  gtk_widget_destroy (dialog);
+}
+
+static void
+import_dialog_response_cb (GtkDialog *dialog,
+    gint response_id,
+    EmpathyAccountsDialog *self)
+{
+  maybe_show_salut_dialog (self);
+}
+
+static void
+maybe_show_import_dialog (EmpathyAccountsDialog *self)
+{
+  EmpathyAccountsDialogPriv *priv = GET_PRIV (self);
+  GtkWidget *dialog;
+
+  if (empathy_accounts_has_non_salut_accounts (priv->account_manager))
+    return;
+
+  if (!empathy_import_accounts_to_import ())
+    {
+      maybe_show_salut_dialog (self);
+      return;
+    }
+
+  dialog = display_import_dialog (self);
+
+  tp_g_signal_connect_object (dialog, "response",
+      G_CALLBACK (import_dialog_response_cb), self, 0);
+}
+
 static void
 finished_loading (EmpathyAccountsDialog *self)
 {
@@ -2134,6 +2164,8 @@ finished_loading (EmpathyAccountsDialog *self)
   gtk_spinner_stop (GTK_SPINNER (priv->spinner));
   gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook_account),
       NOTEBOOK_PAGE_ACCOUNT);
+
+  maybe_show_import_dialog (self);
 }
 
 static void
@@ -2183,12 +2215,12 @@ accounts_dialog_accounts_setup (EmpathyAccountsDialog *dialog)
       dialog);
 
   /* Add existing accounts */
-  accounts = tp_account_manager_get_valid_accounts (priv->account_manager);
+  accounts = tp_account_manager_dup_valid_accounts (priv->account_manager);
   for (l = accounts; l; l = l->next)
     {
       accounts_dialog_add_account (dialog, l->data);
     }
-  g_list_free (accounts);
+  g_list_free_full (accounts, g_object_unref);
 
   priv->cms = empathy_connection_managers_dup_singleton ();
 
@@ -2225,7 +2257,7 @@ dialog_response_cb (GtkWidget *widget,
 
   if (response_id == GTK_RESPONSE_HELP)
     {
-      empathy_url_show (widget, "ghelp:empathy?accounts-window");
+      empathy_url_show (widget, "help:empathy/accounts-window");
     }
   else if (response_id == GTK_RESPONSE_CLOSE ||
       response_id == GTK_RESPONSE_DELETE_EVENT)
@@ -2276,14 +2308,12 @@ accounts_dialog_build_ui (EmpathyAccountsDialog *dialog)
   gui = empathy_builder_get_file (filename,
       "accounts_dialog_hbox", &top_hbox,
       "vbox_details", &priv->vbox_details,
-      "frame_no_protocol", &priv->frame_no_protocol,
       "alignment_settings", &priv->alignment_settings,
       "alignment_infobar", &priv->alignment_infobar,
       "treeview", &priv->treeview,
       "button_add", &priv->button_add,
       "button_remove", &priv->button_remove,
       "button_import", &priv->button_import,
-      "hbox_protocol", &priv->hbox_protocol,
       "notebook_account", &priv->notebook_account,
       "alignment_loading", &alig,
       "accounts_sw", &sw,
@@ -2291,8 +2321,6 @@ accounts_dialog_build_ui (EmpathyAccountsDialog *dialog)
       NULL);
   g_free (filename);
 
-  gtk_widget_set_no_show_all (priv->frame_no_protocol, TRUE);
-
   empathy_builder_connect (gui, dialog,
       "button_add", "clicked", accounts_dialog_button_add_clicked_cb,
       "button_remove", "clicked", accounts_dialog_button_remove_clicked_cb,
@@ -2309,11 +2337,6 @@ accounts_dialog_build_ui (EmpathyAccountsDialog *dialog)
 
   action_area = gtk_dialog_get_action_area (GTK_DIALOG (dialog));
 
-#ifdef HAVE_MEEGO
-  gtk_widget_hide (action_area);
-  gtk_widget_hide (priv->button_remove);
-#endif /* HAVE_MEEGO */
-
   /* Display loading page */
   priv->loading = TRUE;
 
@@ -2336,13 +2359,6 @@ accounts_dialog_build_ui (EmpathyAccountsDialog *dialog)
   gtk_widget_set_sensitive (priv->button_import, FALSE);
   gtk_widget_set_sensitive (priv->treeview, FALSE);
 
-  priv->combobox_protocol = empathy_protocol_chooser_new ();
-  gtk_box_pack_start (GTK_BOX (priv->hbox_protocol), priv->combobox_protocol,
-      TRUE, TRUE, 0);
-  g_signal_connect (priv->combobox_protocol, "changed",
-      G_CALLBACK (accounts_dialog_protocol_changed_cb),
-      dialog);
-
   if (priv->parent_window)
     gtk_window_set_transient_for (GTK_WINDOW (dialog),
         priv->parent_window);
@@ -2353,6 +2369,7 @@ accounts_dialog_build_ui (EmpathyAccountsDialog *dialog)
   gtk_widget_show (priv->infobar);
 
   grid = gtk_grid_new ();
+  gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
   gtk_container_add (
       GTK_CONTAINER (gtk_info_bar_get_content_area (
           GTK_INFO_BAR (priv->infobar))),
@@ -2381,7 +2398,7 @@ accounts_dialog_build_ui (EmpathyAccountsDialog *dialog)
             TP_CONNECTION_PRESENCE_TYPE_OFFLINE), GTK_ICON_SIZE_SMALL_TOOLBAR);
 
   priv->label_status = gtk_label_new (NULL);
-  gtk_label_set_line_wrap (GTK_LABEL (priv->label_status), TRUE);
+  gtk_label_set_ellipsize (GTK_LABEL (priv->label_status), PANGO_ELLIPSIZE_END);
 
   gtk_box_pack_start (GTK_BOX (hbox), priv->throbber, FALSE, FALSE, 0);
   gtk_box_pack_start (GTK_BOX (hbox), priv->image_status, FALSE, FALSE, 0);
@@ -2432,12 +2449,25 @@ do_dispose (GObject *obj)
   EmpathyAccountsDialog *dialog = EMPATHY_ACCOUNTS_DIALOG (obj);
   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
 
+  if (priv->user_info != NULL)
+    {
+      empathy_user_info_apply_async ((EmpathyUserInfo *) priv->user_info,
+          NULL, NULL);
+      priv->user_info = NULL;
+    }
+
   if (priv->connecting_id != 0)
     {
       g_source_remove (priv->connecting_id);
       priv->connecting_id = 0;
     }
 
+  if (priv->connectivity)
+    {
+      g_object_unref (priv->connectivity);
+      priv->connectivity = NULL;
+    }
+
   if (priv->account_manager != NULL)
     {
       g_object_unref (priv->account_manager);
@@ -2450,18 +2480,14 @@ do_dispose (GObject *obj)
       priv->cms = NULL;
     }
 
-  if (priv->connectivity)
-    {
-      g_object_unref (priv->connectivity);
-      priv->connectivity = NULL;
-    }
-
   if (priv->initial_selection != NULL)
     {
       g_object_unref (priv->initial_selection);
       priv->initial_selection = NULL;
     }
 
+  tp_clear_pointer (&priv->icons_cache, g_hash_table_unref);
+
   G_OBJECT_CLASS (empathy_accounts_dialog_parent_class)->dispose (obj);
 }
 
@@ -2523,7 +2549,8 @@ do_constructed (GObject *object)
   tp_proxy_prepare_async (priv->account_manager, NULL,
       accounts_dialog_manager_ready_cb, dialog);
 
-  priv->connectivity = empathy_connectivity_dup_singleton ();
+  priv->connectivity = g_network_monitor_get_default ();
+  g_object_ref (priv->connectivity);
 }
 
 static void
@@ -2555,6 +2582,9 @@ empathy_accounts_dialog_init (EmpathyAccountsDialog *dialog)
       EMPATHY_TYPE_ACCOUNTS_DIALOG,
       EmpathyAccountsDialogPriv);
   dialog->priv = priv;
+
+  priv->icons_cache = g_hash_table_new_full (g_str_hash, g_str_equal,
+      g_free, g_object_unref);
 }
 
 /* public methods */
@@ -2587,9 +2617,94 @@ empathy_accounts_dialog_show (GtkWindow *parent,
   return GTK_WIDGET (dialog);
 }
 
-void
-empathy_accounts_dialog_show_application (GdkScreen *screen,
-    TpAccount *selected_account,
+#ifdef HAVE_UOA
+typedef struct
+{
+  TpAccount *account;
+  gboolean if_needed;
+} LaunchUOACtx;
+
+static LaunchUOACtx *
+launch_uoa_ctx_new (TpAccount *account,
+    gboolean if_needed)
+{
+  LaunchUOACtx *ctx;
+
+  ctx = g_slice_new0 (LaunchUOACtx);
+  if (account != NULL)
+    ctx->account = g_object_ref (account);
+  ctx->if_needed = if_needed;
+
+  return ctx;
+}
+
+static void
+launch_uoa_ctx_free (LaunchUOACtx *ctx)
+{
+  g_clear_object (&ctx->account);
+  g_slice_free (LaunchUOACtx, ctx);
+}
+
+static void
+am_prepare_cb (GObject *source,
+    GAsyncResult *result,
+    gpointer user_data)
+{
+  TpAccountManager *manager = TP_ACCOUNT_MANAGER (source);
+  GError *error = NULL;
+  LaunchUOACtx *ctx = user_data;
+  gchar *args = NULL;
+
+  if (!tp_proxy_prepare_finish (manager, result, &error))
+    {
+      DEBUG ("Failed to prepare account manager: %s", error->message);
+      g_error_free (error);
+      goto out;
+    }
+
+  if (ctx->if_needed && empathy_accounts_has_non_salut_accounts (manager))
+    goto out;
+
+  if (ctx->account != NULL)
+    {
+      const GValue *value;
+
+      value = tp_account_get_storage_identifier (ctx->account);
+
+      if (G_VALUE_HOLDS_UINT (value))
+        args = g_strdup_printf ("account-details=%u", g_value_get_uint (value));
+    }
+
+  empathy_launch_external_app ("gnome-credentials-panel.desktop", args, NULL);
+
+  g_free (args);
+out:
+  launch_uoa_ctx_free (ctx);
+}
+
+static void
+launch_uoa_panel (TpAccount *selected_account,
+    gboolean if_needed,
+    gboolean hidden)
+{
+  TpAccountManager *manager;
+
+  if (hidden)
+    /* Nothing to do */
+    return;
+
+  manager = tp_account_manager_dup ();
+
+  tp_proxy_prepare_async (manager, NULL, am_prepare_cb,
+      launch_uoa_ctx_new (selected_account, if_needed));
+
+  g_object_unref (manager);
+}
+
+#else /* HAVE_UOA */
+
+static void
+launch_empathy_accounts (TpAccount *selected_account,
     gboolean if_needed,
     gboolean hidden)
 {
@@ -2618,6 +2733,20 @@ empathy_accounts_dialog_show_application (GdkScreen *screen,
 
   g_string_free (args, TRUE);
 }
+#endif /* HAVE_UOA */
+
+void
+empathy_accounts_dialog_show_application (GdkScreen *screen,
+    TpAccount *selected_account,
+    gboolean if_needed,
+    gboolean hidden)
+{
+#ifdef HAVE_UOA
+  launch_uoa_panel (selected_account, if_needed, hidden);
+#else
+  launch_empathy_accounts (selected_account, if_needed, hidden);
+#endif
+}
 
 gboolean
 empathy_accounts_dialog_is_creating (EmpathyAccountsDialog *dialog)
@@ -2625,10 +2754,10 @@ empathy_accounts_dialog_is_creating (EmpathyAccountsDialog *dialog)
   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
   gboolean result = FALSE;
 
-  if (priv->setting_widget_object == NULL)
+  if (priv->setting_widget == NULL)
     goto out;
 
-  g_object_get (priv->setting_widget_object,
+  g_object_get (priv->setting_widget,
       "creating-account", &result, NULL);
 
 out: