[empathy] Separate the accounts dialog into its own program which works with the Gnome preferences and control



commit 2aa506e8a17ef67ddf43ee716b21afc780a9d0d2
Author: Travis Reitter <treitter gmail com>
Date:   Thu Feb 11 15:09:32 2010 -0800

    Separate the accounts dialog into its own program which works with the Gnome preferences and control center.
    
    Where available, this also supports embedding the preferences dialog in the
    "extensible-shell" control center (currently in development, but likely to be
    mainlined soon).

 configure.ac                          |   47 ++++++
 data/Makefile.am                      |    5 +-
 data/empathy-accounts.desktop.in.in   |   15 ++
 libempathy/empathy-account-settings.c |    7 +-
 src/Makefile.am                       |  103 ++++++++++--
 src/cc-empathy-accounts-page.c        |  207 ++++++++++++++++++++++++
 src/cc-empathy-accounts-page.h        |   55 +++++++
 src/cc-empathy-accounts-panel.c       |  134 +++++++++++++++
 src/cc-empathy-accounts-panel.h       |   55 +++++++
 src/empathy-accounts-common.c         |  216 +++++++++++++++++++++++++
 src/empathy-accounts-common.h         |   39 +++++
 src/empathy-accounts-dialog.c         |   56 +++++++
 src/empathy-accounts-dialog.h         |    6 +
 src/empathy-accounts-module.c         |   42 +++++
 src/empathy-accounts.c                |  287 +++++++++++++++++++++++++++++++++
 src/empathy-accounts.h                |   25 +++
 src/empathy-main-window.c             |   12 +-
 src/empathy.c                         |  199 +++---------------------
 18 files changed, 1311 insertions(+), 199 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index a218412..33340df 100644
--- a/configure.ac
+++ b/configure.ac
@@ -83,6 +83,8 @@ AC_PATH_PROG(GCONFTOOL, gconftool-2)
 AM_GCONF_SOURCE_2
 GLIB_GENMARSHAL=`$PKG_CONFIG glib-2.0 --variable=glib_genmarshal`
 AC_SUBST(GLIB_GENMARSHAL)
+CONTROL_CENTER_EXTENSIONDIR=`$PKG_CONFIG --variable=extensiondir libgnome-control-center-extension`
+AC_SUBST(CONTROL_CENTER_EXTENSIONDIR)
 
 AC_CHECK_PROGS([XSLTPROC], [xsltproc])
 if test -z "$XSLTPROC"; then
@@ -181,6 +183,20 @@ PKG_CHECK_MODULES(EMPATHY,
    gnome-keyring-1 >= $KEYRING_REQUIRED
 ])
 
+PKG_CHECK_MODULES(LIBEMPATHY_ACCOUNTS_PANEL,
+[
+   glib-2.0 >= $GLIB_REQUIRED
+   gobject-2.0
+   gio-2.0 >= $GLIB_REQUIRED
+   gdk-x11-2.0
+   gtk+-2.0 >= $GTK_REQUIRED
+   libebook-1.2
+   dbus-glib-1
+   telepathy-glib >= $TELEPATHY_GLIB_REQUIRED
+   unique-1.0
+   gnome-keyring-1 >= $KEYRING_REQUIRED
+])
+
 PKG_CHECK_MODULES(LIBNOTIFY, libnotify >= $LIBNOTIFY_REQUIRED)
 
 # -----------------------------------------------------------
@@ -438,6 +454,35 @@ fi
 AM_CONDITIONAL(HAVE_NST, test "x$have_nst" = "xyes")
 
 # -----------------------------------------------------------
+# new, single-window control center
+# -----------------------------------------------------------
+AC_ARG_ENABLE(control_center_embedding,
+              AS_HELP_STRING([--enable-control-center-embedding=@<:@no/yes/auto@:>@],
+                             [Enable support for single-window control center]),
+                             , enable_control_center_embedding=auto)
+
+if test "x$enable_control_center_embedding" != "xno"; then
+   PKG_CHECK_MODULES(CONTROL_CENTER_EMBEDDING,
+   [
+      libgnome-control-center-extension
+   ], have_control_center_embedding="yes", have_control_center_embedding="no")
+
+   if test "x$have_control_center_embedding" = "xyes"; then
+      AC_DEFINE(HAVE_CONTROL_CENTER_EMBEDDING, 1, [Define if you have the single-window control center])
+   fi
+else
+   have_control_center_embedding="no"
+fi
+
+if test "x$enable_control_center_embedding" = "xyes" -a "x$have_control_center_embedding" != "xyes"; then
+   AC_MSG_ERROR([Couldn't find single-window control center dependencies.])
+fi
+
+AM_CONDITIONAL(HAVE_CONTROL_CENTER_EMBEDDING, test "x$have_control_center_embedding" = "xyes")
+AC_SUBST(CONTROL_CENTER_EMBEDDING_CFLAGS)
+AC_SUBST(CONTROL_CENTER_EMBEDDING_LIBS)
+
+# -----------------------------------------------------------
 # Coding style checks
 # -----------------------------------------------------------
 AC_ARG_ENABLE(coding-style-checks,
@@ -452,6 +497,7 @@ AC_OUTPUT([
    Makefile
    data/Makefile
    data/empathy.desktop.in
+   data/empathy-accounts.desktop.in
    data/icons/Makefile
    extensions/Makefile
    po/Makefile.in
@@ -480,6 +526,7 @@ Configure summary:
 	Location awareness (Geoclue):  ${have_geoclue}
 	Adium themes (Webkit).......:  ${have_webkit}
 	Moblin widgets .............:  ${have_moblin}
+	Control center embedding....:  ${have_control_center_embedding}
 
     Connectivity:
 	NetworkManager integration..:  ${have_nm}
diff --git a/data/Makefile.am b/data/Makefile.am
index a4f37b6..8ba57bd 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -1,7 +1,10 @@
 SUBDIRS = icons
 
 desktopdir = $(datadir)/applications
-desktop_in_files = empathy.desktop.in
+desktop_in_files = \
+	empathy.desktop.in \
+	empathy-accounts.desktop.in \
+	$(NULL)
 desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
 @INTLTOOL_DESKTOP_RULE@
 
diff --git a/data/empathy-accounts.desktop.in.in b/data/empathy-accounts.desktop.in.in
new file mode 100644
index 0000000..7ec3e65
--- /dev/null
+++ b/data/empathy-accounts.desktop.in.in
@@ -0,0 +1,15 @@
+[Desktop Entry]
+Version=1.0
+_Name=Messaging and VoIP Accounts
+_GenericName=Messaging and VoIP Accounts
+_Comment=Manage Messaging and VoIP accounts
+Exec=empathy-accounts
+Icon=empathy
+StartupNotify=true
+Terminal=false
+Type=Application
+Categories=GNOME;GTK;Settings;DesktopSettings;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=empathy
+X-GNOME-Bugzilla-Component=General
+X-GNOME-Bugzilla-Version= VERSION@
diff --git a/libempathy/empathy-account-settings.c b/libempathy/empathy-account-settings.c
index 58b0b85..40df9a8 100644
--- a/libempathy/empathy-account-settings.c
+++ b/libempathy/empathy-account-settings.c
@@ -1237,13 +1237,18 @@ empathy_account_settings_has_account (EmpathyAccountSettings *settings,
     TpAccount *account)
 {
   EmpathyAccountSettingsPriv *priv;
+  const gchar *account_path;
+  const gchar *priv_account_path;
 
   g_return_val_if_fail (EMPATHY_IS_ACCOUNT_SETTINGS (settings), FALSE);
   g_return_val_if_fail (TP_IS_ACCOUNT (account), FALSE);
 
   priv = GET_PRIV (settings);
 
-  return (account == priv->account);
+  account_path = tp_proxy_get_object_path (TP_PROXY (account));
+  priv_account_path = tp_proxy_get_object_path (TP_PROXY (priv->account));
+
+  return (!tp_strdiff (account_path, priv_account_path));
 }
 
 gboolean
diff --git a/src/Makefile.am b/src/Makefile.am
index 24ba7b4..58bb6e3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,15 +1,20 @@
 include $(top_srcdir)/tools/flymake.mk
 
-AM_CPPFLAGS =						\
+CPPFLAGS_COMMON =					\
+	$(EMPATHY_CFLAGS)				\
 	$(ERROR_CFLAGS)					\
 	-I$(top_srcdir)                          	\
 	-DG_LOG_DOMAIN=\"empathy\"			\
-	$(EMPATHY_CFLAGS)				\
+	$(DISABLE_DEPRECATED)				\
+	$(WARN_CFLAGS)					\
+	$(NULL)
+
+AM_CPPFLAGS =						\
+	$(CPPFLAGS_COMMON)				\
 	$(LIBNOTIFY_CFLAGS)				\
 	$(LIBCHAMPLAIN_CFLAGS)				\
-	$(DISABLE_DEPRECATED)				\
 	$(WEBKIT_CFLAGS)				\
-	$(WARN_CFLAGS)
+	$(NULL)
 
 LDADD =								\
 	$(top_builddir)/libempathy-gtk/libempathy-gtk.la	\
@@ -20,16 +25,73 @@ LDADD =								\
 	$(LIBCHAMPLAIN_LIBS)					\
 	$(WEBKIT_LIBS)
 
+noinst_LTLIBRARIES = libempathy-accounts-common.la
+
+libempathy_accounts_common_la_SOURCES =					\
+	empathy-accounts-common.c empathy-accounts-common.h		\
+	empathy-account-assistant.c empathy-account-assistant.h		\
+	empathy-accounts-dialog.c empathy-accounts-dialog.h		\
+	empathy-auto-salut-account-helper.c empathy-auto-salut-account-helper.h \
+	empathy-import-dialog.c empathy-import-dialog.h			\
+	empathy-import-mc4-accounts.c empathy-import-mc4-accounts.h	\
+	empathy-import-pidgin.c empathy-import-pidgin.h			\
+	empathy-import-widget.c empathy-import-widget.h			\
+	empathy-import-utils.c empathy-import-utils.h			\
+	ephy-spinner.c ephy-spinner.h					\
+	$(NULL)
+
+libempathy_accounts_common_la_LIBADD =					\
+        $(top_builddir)/libempathy-gtk/libempathy-gtk.la		\
+        $(LIBNOTIFY_LIBS)						\
+        $(EMPATHY_LIBS)							\
+        $(LIBCHAMPLAIN_LIBS)						\
+        $(WEBKIT_LIBS)							\
+	$(NULL)
+
+if HAVE_CONTROL_CENTER_EMBEDDING
+ccmodulesdir = $(CONTROL_CENTER_EXTENSIONDIR)
+ccmodules_LTLIBRARIES = libempathy-accounts-panel.la
+
+libempathy_accounts_panel_la_SOURCES =				\
+	empathy-accounts-module.c				\
+	cc-empathy-accounts-page.c				\
+	cc-empathy-accounts-page.h				\
+	cc-empathy-accounts-panel.c				\
+	cc-empathy-accounts-panel.h				\
+	$(NULL)
+
+libempathy_accounts_panel_la_CPPFLAGS =				\
+	$(CPPFLAGS_COMMON)					\
+	$(CONTROL_CENTER_EMBEDDING_CFLAGS)			\
+	$(NULL)
+
+libempathy_accounts_panel_la_LDFLAGS = -export_dynamic -avoid-version -module -no-undefined -export-symbols-regex '^g_io_module_(load|unload)'
+
+libempathy_accounts_panel_la_LIBADD =				\
+	$(EMPATHY_LIBS)						\
+	$(CONTROL_CENTER_EMBEDDING_LIBS)			\
+	libempathy-accounts-common.la				\
+	$(NULL)
+endif
+
 bin_PROGRAMS =			\
-	empathy
+	empathy			\
+	empathy-accounts	\
+	$(NULL)
 
 BUILT_SOURCES=
 
+empathy_accounts_SOURCES =						\
+	empathy-accounts.c empathy-accounts.h				\
+	$(NULL)
+
+empathy_accounts_LDADD =						\
+	$(LDADD)							\
+	libempathy-accounts-common.la					\
+	$(NULL)
+
 empathy_handwritten_source = \
 	empathy-about-dialog.c empathy-about-dialog.h			\
-	empathy-account-assistant.c empathy-account-assistant.h		\
-	empathy-accounts-dialog.c empathy-accounts-dialog.h		\
-	empathy-auto-salut-account-helper.c empathy-auto-salut-account-helper.h \
 	empathy-call-window-fullscreen.c empathy-call-window-fullscreen.h \
 	empathy-call-window.c empathy-call-window.h			\
 	empathy-chat-window.c empathy-chat-window.h			\
@@ -37,11 +99,6 @@ empathy_handwritten_source = \
 	empathy-debug-window.c empathy-debug-window.h			\
 	empathy-event-manager.c empathy-event-manager.h			\
 	empathy-ft-manager.c empathy-ft-manager.h			\
-	empathy-import-dialog.c empathy-import-dialog.h			\
-	empathy-import-mc4-accounts.c empathy-import-mc4-accounts.h	\
-	empathy-import-pidgin.c empathy-import-pidgin.h			\
-	empathy-import-utils.c empathy-import-utils.h			\
-	empathy-import-widget.c empathy-import-widget.h			\
 	empathy-invite-participant-dialog.c empathy-invite-participant-dialog.h \
 	empathy-main-window.c empathy-main-window.h			\
 	empathy-new-chatroom-dialog.c empathy-new-chatroom-dialog.h	\
@@ -52,13 +109,25 @@ empathy_handwritten_source = \
 
 empathy_SOURCES =							\
 	$(empathy_handwritten_source)					\
-	ephy-spinner.c ephy-spinner.h
+	$(NULL)
+
+empathy_LDADD =								\
+	libempathy-accounts-common.la					\
+        $(top_builddir)/libempathy-gtk/libempathy-gtk.la		\
+        $(top_builddir)/libempathy/libempathy.la			\
+        $(top_builddir)/extensions/libemp-extensions.la			\
+        $(LIBNOTIFY_LIBS)						\
+        $(EMPATHY_LIBS)							\
+        $(LIBCHAMPLAIN_LIBS)						\
+        $(WEBKIT_LIBS)							\
+	$(NULL)
 
 nodist_empathy_SOURCES = $(BUILT_SOURCES)
 
 check_c_sources = \
     $(empathy_handwritten_source) \
     $(empathy_logs_SOURCES)
+
 include $(top_srcdir)/tools/check-coding-style.mk
 check-local: check-coding-style
 
@@ -94,6 +163,12 @@ EXTRA_DIST +=					\
 	empathy-map-view.ui
 endif
 
+if !HAVE_CONTROL_CENTER_EMBEDDING
+EXTRA_DIST += $(libempathy_accounts_panel_la_SOURCES)
+else
+check_c_sources += $(libempathy_accounts_panel_la_SOURCES)
+endif
+
 dist_man_MANS =			\
 	empathy.1
 
diff --git a/src/cc-empathy-accounts-page.c b/src/cc-empathy-accounts-page.c
new file mode 100644
index 0000000..e1502c5
--- /dev/null
+++ b/src/cc-empathy-accounts-page.c
@@ -0,0 +1,207 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Red Hat, Inc.
+ * Copyright (C) 2010 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <gtk/gtk.h>
+#include <gio/gio.h>
+#include <glib/gi18n-lib.h>
+
+#include <telepathy-glib/account-manager.h>
+#include <libempathy/empathy-connection-managers.h>
+#include <libempathy-gtk/empathy-ui-utils.h>
+
+#include "cc-empathy-accounts-page.h"
+#include "empathy-accounts-common.h"
+#include "empathy-account-assistant.h"
+#include "empathy-accounts-dialog.h"
+
+#define CC_EMPATHY_ACCOUNTS_PAGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CC_TYPE_EMPATHY_ACCOUNTS_PAGE, CcEmpathyAccountsPagePrivate))
+
+struct CcEmpathyAccountsPagePrivate
+{
+  /* the original window holding the dialog content; it needs to be retained and
+   * destroyed in our finalize(), since it invalidates its children (even if
+   * they've already been reparented by the time it is destroyed) */
+  GtkWidget *accounts_window;
+};
+
+G_DEFINE_TYPE (CcEmpathyAccountsPage, cc_empathy_accounts_page, CC_TYPE_PAGE)
+
+static void
+page_pack_with_accounts_dialog (CcEmpathyAccountsPage *page)
+{
+  GtkWidget *content;
+  GtkWidget *action_area;
+
+  if (!page->priv->accounts_window)
+    {
+      page->priv->accounts_window = empathy_accounts_dialog_show (NULL, NULL);
+      gtk_widget_hide (page->priv->accounts_window);
+
+      content = gtk_dialog_get_content_area (
+          GTK_DIALOG (page->priv->accounts_window));
+      action_area = gtk_dialog_get_action_area (
+          GTK_DIALOG (page->priv->accounts_window));
+      gtk_widget_set_no_show_all (action_area, TRUE);
+      gtk_widget_hide (action_area);
+
+      gtk_widget_reparent (content, GTK_WIDGET (page));
+    }
+}
+
+static void
+connection_managers_prepare (GObject *source,
+    GAsyncResult *result,
+    gpointer user_data)
+{
+  EmpathyConnectionManagers *cm_mgr = EMPATHY_CONNECTION_MANAGERS (source);
+  TpAccountManager *account_mgr;
+  CcEmpathyAccountsPage *page;
+
+  account_mgr = TP_ACCOUNT_MANAGER (g_object_get_data (G_OBJECT (cm_mgr),
+      "account-manager"));
+  page = CC_EMPATHY_ACCOUNTS_PAGE (g_object_get_data (G_OBJECT (cm_mgr),
+        "page"));
+
+  if (!empathy_connection_managers_prepare_finish (cm_mgr, result, NULL))
+    goto out;
+
+  page_pack_with_accounts_dialog (page);
+
+  if (empathy_accounts_import (account_mgr, cm_mgr))
+    empathy_account_assistant_show (NULL, cm_mgr);
+
+out:
+  /* remove ref from active_changed() */
+  g_object_unref (account_mgr);
+  g_object_unref (cm_mgr);
+}
+
+static void
+account_manager_ready_for_accounts_cb (GObject *source_object,
+    GAsyncResult *result,
+    gpointer user_data)
+{
+  TpAccountManager *account_mgr = TP_ACCOUNT_MANAGER (source_object);
+  CcEmpathyAccountsPage *page = CC_EMPATHY_ACCOUNTS_PAGE (user_data);
+  GError *error = NULL;
+
+  if (!tp_account_manager_prepare_finish (account_mgr, result, &error))
+    {
+      g_warning ("Failed to prepare account manager: %s", error->message);
+      g_error_free (error);
+      return;
+    }
+
+  if (empathy_accounts_has_non_salut_accounts (account_mgr))
+    {
+      page_pack_with_accounts_dialog (page);
+
+      /* remove ref from active_changed() */
+      g_object_unref (account_mgr);
+    }
+  else
+    {
+      EmpathyConnectionManagers *cm_mgr;
+
+      cm_mgr = empathy_connection_managers_dup_singleton ();
+
+      g_object_set_data_full (G_OBJECT (cm_mgr), "account-manager",
+          g_object_ref (account_mgr), (GDestroyNotify) g_object_unref);
+      g_object_set_data_full (G_OBJECT (cm_mgr), "page",
+          g_object_ref (page), (GDestroyNotify) g_object_unref);
+
+      empathy_connection_managers_prepare_async (cm_mgr,
+          connection_managers_prepare, page);
+    }
+}
+
+static void
+active_changed (CcPage *base_page,
+    gboolean is_active)
+{
+  CcEmpathyAccountsPage *page = CC_EMPATHY_ACCOUNTS_PAGE (base_page);
+  TpAccountManager *account_manager;
+
+  if (is_active)
+    {
+      /* unref'd in final endpoint callbacks */
+      account_manager = tp_account_manager_dup ();
+
+      tp_account_manager_prepare_async (account_manager, NULL,
+          account_manager_ready_for_accounts_cb, page);
+    }
+}
+
+static void
+cc_empathy_accounts_page_finalize (GObject *object)
+{
+  CcEmpathyAccountsPage *page;
+
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (CC_IS_EMPATHY_ACCOUNTS_PAGE (object));
+
+  page = CC_EMPATHY_ACCOUNTS_PAGE (object);
+
+  g_return_if_fail (page->priv != NULL);
+
+  gtk_widget_destroy (page->priv->accounts_window);
+
+  G_OBJECT_CLASS (cc_empathy_accounts_page_parent_class)->finalize (object);
+}
+
+static void
+cc_empathy_accounts_page_class_init (CcEmpathyAccountsPageClass *klass)
+{
+  GObjectClass  *object_class = G_OBJECT_CLASS (klass);
+  CcPageClass   *page_class = CC_PAGE_CLASS (klass);
+
+  object_class->finalize = cc_empathy_accounts_page_finalize;
+
+  page_class->active_changed = active_changed;
+
+  g_type_class_add_private (klass, sizeof (CcEmpathyAccountsPagePrivate));
+}
+
+static void
+cc_empathy_accounts_page_init (CcEmpathyAccountsPage *page)
+{
+  page->priv = CC_EMPATHY_ACCOUNTS_PAGE_GET_PRIVATE (page);
+
+  empathy_gtk_init ();
+}
+
+CcPage *
+cc_empathy_accounts_page_new (void)
+{
+  GObject *object;
+
+  object = g_object_new (CC_TYPE_EMPATHY_ACCOUNTS_PAGE,
+      "display-name", _("Messaging and VoIP Accounts"),
+      "id", "general",
+      NULL);
+
+  return CC_PAGE (object);
+}
diff --git a/src/cc-empathy-accounts-page.h b/src/cc-empathy-accounts-page.h
new file mode 100644
index 0000000..f526dca
--- /dev/null
+++ b/src/cc-empathy-accounts-page.h
@@ -0,0 +1,55 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Red Hat, Inc.
+ * Copyright (C) 2010 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __CC_EMPATHY_ACCOUNTS_PAGE_H
+#define __CC_EMPATHY_ACCOUNTS_PAGE_H
+
+#include <gtk/gtk.h>
+#include <libgnome-control-center-extension/cc-page.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_EMPATHY_ACCOUNTS_PAGE         (cc_empathy_accounts_page_get_type ())
+#define CC_EMPATHY_ACCOUNTS_PAGE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), CC_TYPE_EMPATHY_ACCOUNTS_PAGE, CcEmpathyAccountsPage))
+#define CC_EMPATHY_ACCOUNTS_PAGE_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), CC_TYPE_EMPATHY_ACCOUNTS_PAGE, CcEmpathyAccountsPageClass))
+#define CC_IS_EMPATHY_ACCOUNTS_PAGE(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), CC_TYPE_EMPATHY_ACCOUNTS_PAGE))
+#define CC_IS_EMPATHY_ACCOUNTS_PAGE_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), CC_TYPE_EMPATHY_ACCOUNTS_PAGE))
+#define CC_EMPATHY_ACCOUNTS_PAGE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CC_TYPE_EMPATHY_ACCOUNTS_PAGE, CcEmpathyAccountsPageClass))
+
+typedef struct CcEmpathyAccountsPagePrivate CcEmpathyAccountsPagePrivate;
+
+typedef struct
+{
+  CcPage parent;
+  CcEmpathyAccountsPagePrivate *priv;
+} CcEmpathyAccountsPage;
+
+typedef struct
+{
+  CcPageClass parent_class;
+} CcEmpathyAccountsPageClass;
+
+GType   cc_empathy_accounts_page_get_type   (void);
+CcPage* cc_empathy_accounts_page_new        (void);
+
+G_END_DECLS
+
+#endif /* __CC_EMPATHY_ACCOUNTS_PAGE_H */
diff --git a/src/cc-empathy-accounts-panel.c b/src/cc-empathy-accounts-panel.c
new file mode 100644
index 0000000..e975d27
--- /dev/null
+++ b/src/cc-empathy-accounts-panel.c
@@ -0,0 +1,134 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <gtk/gtk.h>
+#include <gio/gio.h>
+#include <glib/gi18n-lib.h>
+
+#include <gconf/gconf-client.h>
+
+#include "cc-empathy-accounts-panel.h"
+#include "cc-empathy-accounts-page.h"
+
+#define CC_EMPATHY_ACCOUNTS_PANEL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CC_TYPE_EMPATHY_ACCOUNTS_PANEL, CcEmpathyAccountsPanelPrivate))
+
+struct CcEmpathyAccountsPanelPrivate
+{
+  CcPage *empathy_accounts_page;
+};
+
+G_DEFINE_DYNAMIC_TYPE (CcEmpathyAccountsPanel, cc_empathy_accounts_panel, CC_TYPE_PANEL)
+
+static void
+setup_panel (CcEmpathyAccountsPanel *panel)
+{
+  panel->priv->empathy_accounts_page = cc_empathy_accounts_page_new ();
+
+  gtk_container_add (GTK_CONTAINER (panel),
+      GTK_WIDGET (panel->priv->empathy_accounts_page));
+
+  gtk_widget_show (GTK_WIDGET (panel->priv->empathy_accounts_page));
+
+  g_object_set (panel,
+      "current-page", panel->priv->empathy_accounts_page,
+      NULL);
+}
+
+static GObject *
+cc_empathy_accounts_panel_constructor (GType type,
+    guint n_construct_properties,
+    GObjectConstructParam *construct_properties)
+{
+  CcEmpathyAccountsPanel *empathy_accounts_panel;
+
+  empathy_accounts_panel = CC_EMPATHY_ACCOUNTS_PANEL (
+      G_OBJECT_CLASS (cc_empathy_accounts_panel_parent_class)->constructor (
+          type, n_construct_properties, construct_properties));
+
+  g_object_set (empathy_accounts_panel,
+      "display-name", _("Messaging and VoIP Accounts"),
+      "id", "empathy-accounts.desktop",
+      NULL);
+
+  setup_panel (empathy_accounts_panel);
+
+  return G_OBJECT (empathy_accounts_panel);
+}
+
+static void
+cc_empathy_accounts_panel_finalize (GObject *object)
+{
+  CcEmpathyAccountsPanel *empathy_accounts_panel;
+
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (CC_IS_EMPATHY_ACCOUNTS_PANEL (object));
+
+  empathy_accounts_panel = CC_EMPATHY_ACCOUNTS_PANEL (object);
+
+  g_return_if_fail (empathy_accounts_panel->priv != NULL);
+
+  g_object_unref (empathy_accounts_panel->priv->empathy_accounts_page);
+
+  G_OBJECT_CLASS (cc_empathy_accounts_panel_parent_class)->finalize (object);
+}
+
+static void
+cc_empathy_accounts_panel_class_init (CcEmpathyAccountsPanelClass *klass)
+{
+  GObjectClass  *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->constructor = cc_empathy_accounts_panel_constructor;
+  object_class->finalize = cc_empathy_accounts_panel_finalize;
+
+  g_type_class_add_private (klass, sizeof (CcEmpathyAccountsPanelPrivate));
+}
+
+static void
+cc_empathy_accounts_panel_class_finalize (CcEmpathyAccountsPanelClass *klass)
+{
+}
+
+static void
+cc_empathy_accounts_panel_init (CcEmpathyAccountsPanel *panel)
+{
+  GConfClient *client;
+
+  panel->priv = CC_EMPATHY_ACCOUNTS_PANEL_GET_PRIVATE (panel);
+
+  client = gconf_client_get_default ();
+  gconf_client_add_dir (client, "/desktop/gnome/peripherals/empathy_accounts",
+      GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+  gconf_client_add_dir (client, "/desktop/gnome/interface",
+      GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+  g_object_unref (client);
+}
+
+void
+cc_empathy_accounts_panel_register (GIOModule *module)
+{
+  cc_empathy_accounts_panel_register_type (G_TYPE_MODULE (module));
+  g_io_extension_point_implement (CC_PANEL_EXTENSION_POINT_NAME,
+      CC_TYPE_EMPATHY_ACCOUNTS_PANEL, "empathy-accounts", 10);
+}
diff --git a/src/cc-empathy-accounts-panel.h b/src/cc-empathy-accounts-panel.h
new file mode 100644
index 0000000..5e6f597
--- /dev/null
+++ b/src/cc-empathy-accounts-panel.h
@@ -0,0 +1,55 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Red Hat, Inc.
+ * Copyright (C) 2010 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __CC_EMPATHY_ACCOUNTS_PANEL_H
+#define __CC_EMPATHY_ACCOUNTS_PANEL_H
+
+#include <gtk/gtk.h>
+#include <libgnome-control-center-extension/cc-panel.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_EMPATHY_ACCOUNTS_PANEL         (cc_empathy_accounts_panel_get_type ())
+#define CC_EMPATHY_ACCOUNTS_PANEL(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), CC_TYPE_EMPATHY_ACCOUNTS_PANEL, CcEmpathyAccountsPanel))
+#define CC_EMPATHY_ACCOUNTS_PANEL_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), CC_TYPE_EMPATHY_ACCOUNTS_PANEL, CcEmpathyAccountsPanelClass))
+#define CC_IS_EMPATHY_ACCOUNTS_PANEL(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), CC_TYPE_EMPATHY_ACCOUNTS_PANEL))
+#define CC_IS_EMPATHY_ACCOUNTS_PANEL_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), CC_TYPE_EMPATHY_ACCOUNTS_PANEL))
+#define CC_EMPATHY_ACCOUNTS_PANEL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CC_TYPE_EMPATHY_ACCOUNTS_PANEL, CcEmpathyAccountsPanelClass))
+
+typedef struct CcEmpathyAccountsPanelPrivate CcEmpathyAccountsPanelPrivate;
+
+typedef struct
+{
+  CcPanel parent;
+  CcEmpathyAccountsPanelPrivate *priv;
+} CcEmpathyAccountsPanel;
+
+typedef struct
+{
+  CcPanelClass parent_class;
+} CcEmpathyAccountsPanelClass;
+
+GType cc_empathy_accounts_panel_get_type (void);
+void  cc_empathy_accounts_panel_register (GIOModule *module);
+
+G_END_DECLS
+
+#endif /* __CC_EMPATHY_ACCOUNTS_PANEL_H */
diff --git a/src/empathy-accounts-common.c b/src/empathy-accounts-common.c
new file mode 100644
index 0000000..89d7eb8
--- /dev/null
+++ b/src/empathy-accounts-common.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2005-2007 Imendio AB
+ * Copyright (C) 2007-2010 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY 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, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA  02110-1301  USA
+ *
+ * Authors: Martyn Russell <martyn imendio com>
+ *          Xavier Claessens <xclaesse gmail com>
+ *          Cosimo Cecchi <cosimo cecchi collabora co uk>
+ *          Jonathan Tellier <jonathan tellier gmail com>
+ *          Travis Reitter <travis reitter collabora co uk>
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <unique/unique.h>
+
+#include <telepathy-glib/account-manager.h>
+#include <telepathy-glib/util.h>
+
+#include <libempathy/empathy-utils.h>
+#include <libempathy/empathy-connection-managers.h>
+#include <libempathy-gtk/empathy-ui-utils.h>
+
+#include "empathy-accounts-common.h"
+#include "empathy-accounts-dialog.h"
+#include "empathy-account-assistant.h"
+#include "empathy-import-mc4-accounts.h"
+#include "empathy-auto-salut-account-helper.h"
+
+#define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT
+#include <libempathy/empathy-debug.h>
+
+gboolean
+empathy_accounts_has_non_salut_accounts (TpAccountManager *manager)
+{
+  gboolean ret = FALSE;
+  GList *accounts, *l;
+
+  accounts = tp_account_manager_get_valid_accounts (manager);
+
+  for (l = accounts ; l != NULL; l = g_list_next (l))
+    {
+      if (tp_strdiff (tp_account_get_protocol (l->data), "local-xmpp"))
+        {
+          ret = TRUE;
+          break;
+        }
+    }
+
+  g_list_free (accounts);
+
+  return ret;
+}
+
+/* Try to import accounts from MC4 and returns TRUE if we should display the
+ * accounts assistant. */
+gboolean
+empathy_accounts_import (TpAccountManager *account_mgr,
+    EmpathyConnectionManagers *cm_mgr)
+{
+  g_return_val_if_fail (tp_account_manager_is_prepared (account_mgr,
+      TP_ACCOUNT_MANAGER_FEATURE_CORE), FALSE);
+  g_return_val_if_fail (empathy_connection_managers_is_ready (cm_mgr), FALSE);
+
+  if (empathy_import_mc4_has_imported ())
+    return FALSE;
+
+  if (empathy_import_mc4_accounts (cm_mgr))
+    return FALSE;
+
+  if (empathy_accounts_has_non_salut_accounts (account_mgr))
+    return FALSE;
+
+  if (!should_create_salut_account (account_mgr))
+    return FALSE;
+
+  return TRUE;
+}
+
+static void
+do_show_accounts_ui (TpAccountManager *manager,
+    TpAccount *account,
+    GCallback window_destroyed_cb)
+{
+  GtkWidget *accounts_window;
+
+  accounts_window = empathy_accounts_dialog_show (NULL, account);
+
+  if (window_destroyed_cb)
+    g_signal_connect (accounts_window, "destroy", window_destroyed_cb, NULL);
+
+  gtk_window_present (GTK_WINDOW (accounts_window));
+}
+
+static GtkWidget*
+show_account_assistant (EmpathyConnectionManagers *connection_mgrs,
+    GCallback assistant_destroy_cb)
+{
+  GtkWidget *assistant;
+
+  assistant = empathy_account_assistant_show (NULL, connection_mgrs);
+  if (assistant_destroy_cb)
+    g_signal_connect (assistant, "destroy", assistant_destroy_cb, NULL);
+
+  return assistant;
+}
+
+static void
+connection_managers_prepare_cb (
+    EmpathyConnectionManagers *cm_mgr,
+    GAsyncResult *result,
+    gpointer user_data)
+{
+  GCallback assistant_destroy_cb = g_object_get_data (G_OBJECT (cm_mgr),
+      "assistant-destroy-callback");
+  TpAccountManager *account_mgr = g_object_get_data (G_OBJECT (cm_mgr),
+      "account-manager");
+  gboolean hidden = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (cm_mgr),
+        "hidden"));
+
+  if (!empathy_connection_managers_prepare_finish (cm_mgr, result, NULL))
+    goto out;
+
+  if (empathy_accounts_import (account_mgr, cm_mgr) &&
+      !hidden)
+    {
+      show_account_assistant (cm_mgr, assistant_destroy_cb);
+    }
+  else
+    {
+      if (assistant_destroy_cb)
+        assistant_destroy_cb ();
+    }
+
+out:
+  g_object_unref (cm_mgr);
+}
+
+void
+empathy_accounts_manager_ready_for_show_assistant (
+    TpAccountManager *account_mgr,
+    gboolean hidden)
+{
+  EmpathyConnectionManagers *cm_mgr;
+
+  cm_mgr = empathy_connection_managers_dup_singleton ();
+
+  g_object_set_data (G_OBJECT (cm_mgr), "assistant-destroy-callback",
+      g_object_get_data (G_OBJECT (account_mgr), "assistant-destroy-callback"));
+  g_object_set_data_full (G_OBJECT (cm_mgr), "account-manager",
+      g_object_ref (account_mgr), g_object_unref);
+  g_object_set_data (G_OBJECT (cm_mgr), "hidden", GUINT_TO_POINTER (hidden));
+
+  empathy_connection_managers_prepare_async (cm_mgr,
+      (GAsyncReadyCallback) connection_managers_prepare_cb, NULL);
+}
+
+static void
+connection_managers_prepare_for_accounts (GObject *source,
+    GAsyncResult *result,
+    gpointer user_data)
+{
+  EmpathyConnectionManagers *cm_mgr = EMPATHY_CONNECTION_MANAGERS (source);
+  GCallback assistant_destroy_cb = G_CALLBACK (user_data);
+
+  if (!empathy_connection_managers_prepare_finish (cm_mgr, result, NULL))
+    goto out;
+
+  show_account_assistant (cm_mgr, assistant_destroy_cb);
+  g_debug ("would show the account assistant");
+
+out:
+  g_object_unref (cm_mgr);
+}
+
+void
+empathy_accounts_show_accounts_ui (TpAccountManager *manager,
+    TpAccount *account,
+    GCallback window_destroyed_cb)
+{
+  g_return_if_fail (TP_IS_ACCOUNT_MANAGER (manager));
+  g_return_if_fail (!account || TP_IS_ACCOUNT (account));
+
+  if (empathy_accounts_has_non_salut_accounts (manager))
+    {
+      do_show_accounts_ui (manager, account, window_destroyed_cb);
+    }
+  else
+    {
+      EmpathyConnectionManagers *cm_mgr;
+
+      cm_mgr = empathy_connection_managers_dup_singleton ();
+
+      empathy_connection_managers_prepare_async (cm_mgr,
+          connection_managers_prepare_for_accounts, window_destroyed_cb);
+    }
+}
diff --git a/src/empathy-accounts-common.h b/src/empathy-accounts-common.h
new file mode 100644
index 0000000..6782d77
--- /dev/null
+++ b/src/empathy-accounts-common.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2010 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY 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, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA  02110-1301  USA
+ *
+ * Authors: Travis Reitter <travis reitter collabora co uk>
+ */
+
+#ifndef __EMPATHY_ACCOUNTS_COMMON_H__
+#define __EMPATHY_ACCOUNTS_COMMON_H__
+
+gboolean empathy_accounts_has_non_salut_accounts (TpAccountManager *manager);
+
+void empathy_accounts_show_accounts_ui (TpAccountManager *manager,
+    TpAccount *account,
+    GCallback window_destroyed_cb);
+
+void empathy_accounts_manager_ready_for_show_assistant (
+    TpAccountManager *account_mgr,
+    gboolean hidden);
+
+gboolean empathy_accounts_import (TpAccountManager *account_mgr,
+    EmpathyConnectionManagers *cm_mgr);
+
+
+#endif /* __EMPATHY_ACCOUNTS_COMMON_H__ */
diff --git a/src/empathy-accounts-dialog.c b/src/empathy-accounts-dialog.c
index 39e20d8..57456ba 100644
--- a/src/empathy-accounts-dialog.c
+++ b/src/empathy-accounts-dialog.c
@@ -33,6 +33,7 @@
 #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>
@@ -1890,6 +1891,8 @@ 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,
@@ -2207,3 +2210,56 @@ empathy_accounts_dialog_show (GtkWindow *parent,
 
   return GTK_WIDGET (dialog);
 }
+
+void
+empathy_accounts_dialog_show_application (GdkScreen *screen,
+    GChildWatchFunc application_exit_cb,
+    gpointer user_data,
+    TpAccount *selected_account,
+    gboolean try_import,
+    gboolean hidden)
+{
+  gint command_pid;
+  GError *error = NULL;
+  gchar *argv[4] = { NULL, };
+  gint i = 0;
+  gchar *account_option = NULL;
+
+  g_return_if_fail (GDK_IS_SCREEN (screen));
+  g_return_if_fail (!selected_account || TP_IS_ACCOUNT (selected_account));
+
+  argv[i++] = "empathy-accounts";
+
+  if (selected_account)
+    {
+      const gchar *account_path;
+
+      account_path = tp_proxy_get_object_path (TP_PROXY (selected_account));
+      account_option = g_strdup_printf ("--select-account=%s",
+          &account_path[strlen (TP_ACCOUNT_OBJECT_PATH_BASE)]);
+
+      argv[i++] = account_option;
+    }
+
+  if (try_import)
+    argv[i++] = "--import";
+
+  if (hidden)
+    argv[i++] = "--hidden";
+
+  gdk_spawn_on_screen (screen, NULL, argv, NULL,
+      G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL,
+      &command_pid, &error);
+  if (error)
+    {
+      g_warning ("Failed to open accounts dialog: %s", error->message);
+      g_error_free (error);
+    }
+
+  /* XXX: unportable cast to GPid; then again, gdk_spawn_on_screen() seems
+   * unportable since it always takes a gint* for the PID */
+  if (application_exit_cb)
+    g_child_watch_add ((GPid) command_pid, application_exit_cb, NULL);
+
+  g_free (account_option);
+}
diff --git a/src/empathy-accounts-dialog.h b/src/empathy-accounts-dialog.h
index 6decad7..dd9cd7d 100644
--- a/src/empathy-accounts-dialog.h
+++ b/src/empathy-accounts-dialog.h
@@ -56,6 +56,12 @@ typedef struct {
 GType empathy_accounts_dialog_get_type (void);
 GtkWidget *empathy_accounts_dialog_show (GtkWindow *parent,
     TpAccount *selected_account);
+void empathy_accounts_dialog_show_application (GdkScreen *screen,
+    GChildWatchFunc application_exit_cb,
+    gpointer user_data,
+    TpAccount *selected_account,
+    gboolean try_import,
+    gboolean hidden);
 
 G_END_DECLS
 
diff --git a/src/empathy-accounts-module.c b/src/empathy-accounts-module.c
new file mode 100644
index 0000000..b80cd4f
--- /dev/null
+++ b/src/empathy-accounts-module.c
@@ -0,0 +1,42 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Red Hat, Inc.
+ * Copyright (C) 2010 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <gmodule.h>
+#include <gio/gio.h>
+
+#include "cc-empathy-accounts-panel.h"
+
+void
+g_io_module_load (GIOModule *module)
+{
+  textdomain (GETTEXT_PACKAGE);
+
+  cc_empathy_accounts_panel_register (module);
+}
+
+void
+g_io_module_unload (GIOModule *module)
+{
+}
diff --git a/src/empathy-accounts.c b/src/empathy-accounts.c
new file mode 100644
index 0000000..942f6a4
--- /dev/null
+++ b/src/empathy-accounts.c
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2005-2007 Imendio AB
+ * Copyright (C) 2007-2010 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY 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, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA  02110-1301  USA
+ *
+ * Authors: Martyn Russell <martyn imendio com>
+ *          Xavier Claessens <xclaesse gmail com>
+ *          Cosimo Cecchi <cosimo cecchi collabora co uk>
+ *          Jonathan Tellier <jonathan tellier gmail com>
+ *          Travis Reitter <travis reitter collabora co uk>
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <unique/unique.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-gtk/empathy-ui-utils.h>
+
+#include "empathy-accounts.h"
+#include "empathy-accounts-common.h"
+#include "empathy-accounts-dialog.h"
+#include "empathy-account-assistant.h"
+#include "empathy-import-mc4-accounts.h"
+#include "empathy-auto-salut-account-helper.h"
+
+#define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT
+#include <libempathy/empathy-debug.h>
+
+#define EMPATHY_ACCOUNTS_DBUS_NAME "org.gnome.EmpathyAccounts"
+
+static gboolean try_import = FALSE;
+static gboolean hidden = FALSE;
+static gchar *selected_account_name = NULL;
+
+static void
+account_manager_ready_for_assistant_cb (GObject *source_object,
+    GAsyncResult *result,
+    gpointer user_data)
+{
+  TpAccountManager *account_mgr = TP_ACCOUNT_MANAGER (source_object);
+  GError *error = NULL;
+
+  if (!tp_account_manager_prepare_finish (account_mgr, result, &error))
+    {
+      DEBUG ("Failed to prepare account manager: %s", error->message);
+      g_error_free (error);
+      return;
+    }
+
+  g_object_set_data (G_OBJECT (account_mgr), "assistant-destroy-callback",
+      G_CALLBACK (gtk_main_quit));
+
+  empathy_accounts_manager_ready_for_show_assistant (account_mgr, hidden);
+}
+
+static void
+account_prepare_cb (GObject *source_object,
+    GAsyncResult *result,
+    gpointer user_data)
+{
+  TpAccountManager *manager = TP_ACCOUNT_MANAGER (user_data);
+  TpAccount *account = TP_ACCOUNT (source_object);
+  GError *error = NULL;
+
+  if (!tp_account_prepare_finish (account, result, &error))
+    {
+      DEBUG ("Failed to prepare account: %s", error->message);
+      g_error_free (error);
+
+      account = NULL;
+    }
+
+  empathy_accounts_show_accounts_ui (manager, account,
+      G_CALLBACK (gtk_main_quit));
+}
+
+static void
+account_manager_ready_for_accounts_cb (GObject *source_object,
+    GAsyncResult *result,
+    gpointer user_data)
+{
+  TpAccountManager *manager = TP_ACCOUNT_MANAGER (source_object);
+  const gchar *account_id = (const gchar*) user_data;
+  GError *error = NULL;
+
+  if (!tp_account_manager_prepare_finish (manager, result, &error))
+    {
+      DEBUG ("Failed to prepare account manager: %s", error->message);
+      g_clear_error (&error);
+      return;
+    }
+
+  if (account_id)
+    {
+      gchar *account_path;
+      TpAccount *account = NULL;
+      TpDBusDaemon *bus;
+
+      /* create and prep the corresponding TpAccount so it's fully ready by the
+       * time we try to select it in the accounts dialog */
+      account_path = g_strdup_printf ("%s%s", TP_ACCOUNT_OBJECT_PATH_BASE,
+          account_id);
+      bus = tp_dbus_daemon_dup (NULL);
+      if ((account = tp_account_new (bus, account_path, &error)))
+        {
+          tp_account_prepare_async (account, NULL, account_prepare_cb, manager);
+          return;
+        }
+      else
+        {
+          DEBUG ("Failed to find account with path %s: %s", account_path,
+              error->message);
+          g_clear_error (&error);
+        }
+
+      g_object_unref (bus);
+      g_free (account_path);
+    }
+  else
+    {
+      empathy_accounts_show_accounts_ui (manager, NULL,
+          G_CALLBACK (gtk_main_quit));
+    }
+}
+
+static UniqueResponse
+unique_app_message_cb (UniqueApp *unique_app,
+    gint command,
+    UniqueMessageData *data,
+    guint timestamp,
+    gpointer user_data)
+{
+  DEBUG ("Other instance launched, presenting the main window. "
+      "Command=%d, timestamp %u", command, timestamp);
+
+  if (command == UNIQUE_ACTIVATE)
+    {
+      TpAccountManager *account_manager;
+
+      account_manager = tp_account_manager_dup ();
+
+      empathy_accounts_show_accounts_ui (account_manager, NULL,
+          G_CALLBACK (gtk_main_quit));
+
+      g_object_unref (account_manager);
+    }
+  else
+    {
+      g_warning (G_STRLOC "unhandled unique app command %d", command);
+
+      return UNIQUE_RESPONSE_PASSTHROUGH;
+    }
+
+  return UNIQUE_RESPONSE_OK;
+}
+
+#define COMMAND_ACCOUNTS_DIALOG 1
+
+int
+main (int argc, char *argv[])
+{
+  TpAccountManager *account_manager;
+  GError *error = NULL;
+  TpDBusDaemon *dbus_daemon;
+  UniqueApp *unique_app;
+
+  GOptionContext *optcontext;
+  GOptionEntry options[] = {
+      { "import", 'i',
+        G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &try_import,
+        N_("Try to import any recognized accounts and display an assistant if "
+            "that fails"),
+        NULL },
+      { "hidden", 'h',
+        0, G_OPTION_ARG_NONE, &hidden,
+        N_("Don't display any dialogs; do any work (eg, importing) and exit"),
+        NULL },
+      { "select-account", 's',
+        G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_STRING, &selected_account_name,
+        N_("Initially select given account (eg, "
+            "gabble/jabber/foo_40example_2eorg0)"),
+        N_("<account-id>") },
+
+      { NULL }
+  };
+
+  g_thread_init (NULL);
+  empathy_init ();
+
+  optcontext = g_option_context_new (N_("- Empathy Accounts"));
+  g_option_context_add_group (optcontext, gtk_get_option_group (TRUE));
+  g_option_context_add_main_entries (optcontext, options, GETTEXT_PACKAGE);
+
+  if (!g_option_context_parse (optcontext, &argc, &argv, &error))
+    {
+      g_print ("%s\nRun '%s --help' to see a full list of available command line options.\n",
+          error->message, argv[0]);
+      g_warning ("Error in empathy init: %s", error->message);
+      return EXIT_FAILURE;
+    }
+
+  g_option_context_free (optcontext);
+
+  empathy_gtk_init ();
+
+  g_set_application_name (_(PACKAGE_NAME " Accounts"));
+
+  gtk_window_set_default_icon_name ("empathy");
+
+  unique_app = unique_app_new (EMPATHY_ACCOUNTS_DBUS_NAME, NULL);
+
+  if (unique_app_is_running (unique_app))
+    {
+      unique_app_send_message (unique_app, UNIQUE_ACTIVATE, NULL);
+
+      g_object_unref (unique_app);
+      return EXIT_SUCCESS;
+    }
+
+  /* Take well-known name */
+  dbus_daemon = tp_dbus_daemon_dup (&error);
+  if (error == NULL)
+    {
+      if (!tp_dbus_daemon_request_name (dbus_daemon,
+          EMPATHY_ACCOUNTS_DBUS_NAME, TRUE, &error))
+        {
+          DEBUG ("Failed to request well-known name: %s",
+                 error ? error->message : "no message");
+          g_clear_error (&error);
+        }
+      g_object_unref (dbus_daemon);
+    }
+  else
+    {
+      DEBUG ("Failed to dup dbus daemon: %s",
+             error ? error->message : "no message");
+      g_clear_error (&error);
+    }
+
+  account_manager = tp_account_manager_dup ();
+
+  if (try_import)
+    {
+      tp_account_manager_prepare_async (account_manager, NULL,
+          account_manager_ready_for_assistant_cb, NULL);
+    }
+  else
+    {
+      tp_account_manager_prepare_async (account_manager, NULL,
+          account_manager_ready_for_accounts_cb, selected_account_name);
+    }
+
+  g_signal_connect (unique_app, "message-received",
+      G_CALLBACK (unique_app_message_cb), NULL);
+
+  gtk_main ();
+
+  g_object_unref (account_manager);
+  g_object_unref (unique_app);
+
+  return EXIT_SUCCESS;
+}
diff --git a/src/empathy-accounts.h b/src/empathy-accounts.h
new file mode 100644
index 0000000..8c50cd6
--- /dev/null
+++ b/src/empathy-accounts.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2010 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY 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, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA  02110-1301  USA
+ *
+ * Authors: Travis Reitter <travis reitter collabora co uk>
+ */
+
+#ifndef __EMPATHY_ACCOUNTS_H__
+#define __EMPATHY_ACCOUNTS_H__
+
+#endif /* __EMPATHY_ACCOUNTS_H__ */
diff --git a/src/empathy-main-window.c b/src/empathy-main-window.c
index e9b1983..8d6413a 100644
--- a/src/empathy-main-window.c
+++ b/src/empathy-main-window.c
@@ -356,7 +356,10 @@ main_window_error_edit_clicked_cb (GtkButton *button,
 	TpAccount *account;
 
 	account = g_object_get_data (G_OBJECT (button), "account");
-	empathy_accounts_dialog_show (GTK_WINDOW (window->window), account);
+
+	empathy_accounts_dialog_show_application (
+			gtk_widget_get_screen (GTK_WIDGET (button)), NULL, NULL,
+			account, FALSE, FALSE);
 
 	main_window_remove_error (window, account);
 }
@@ -1059,7 +1062,8 @@ static void
 main_window_edit_accounts_cb (GtkAction         *action,
 			      EmpathyMainWindow *window)
 {
-	empathy_accounts_dialog_show (GTK_WINDOW (window->window), NULL);
+	empathy_accounts_dialog_show_application (gdk_screen_get_default (),
+			NULL, NULL, NULL, FALSE, FALSE);
 }
 
 static void
@@ -1107,7 +1111,9 @@ main_window_throbber_button_press_event_cb (GtkWidget         *throbber_ebox,
 		return FALSE;
 	}
 
-	empathy_accounts_dialog_show (GTK_WINDOW (window->window), NULL);
+	empathy_accounts_dialog_show_application (
+			gtk_widget_get_screen (GTK_WIDGET (throbber_ebox)),
+			NULL, NULL, NULL, FALSE, FALSE);
 
 	return FALSE;
 }
diff --git a/src/empathy.c b/src/empathy.c
index 197e801..6ae5522 100644
--- a/src/empathy.c
+++ b/src/empathy.c
@@ -62,15 +62,12 @@
 #include <libempathy-gtk/empathy-ui-utils.h>
 #include <libempathy-gtk/empathy-location-manager.h>
 
-#include "empathy-account-assistant.h"
-#include "empathy-accounts-dialog.h"
 #include "empathy-main-window.h"
+#include "empathy-accounts-dialog.h"
 #include "empathy-status-icon.h"
 #include "empathy-call-window.h"
 #include "empathy-chat-window.h"
 #include "empathy-ft-manager.h"
-#include "empathy-import-mc4-accounts.h"
-#include "empathy-auto-salut-account-helper.h"
 
 #include "extensions/extensions.h"
 
@@ -166,108 +163,6 @@ use_conn_notify_cb (EmpathyConf *conf,
     }
 }
 
-static gboolean
-has_non_salut_accounts (TpAccountManager *manager)
-{
-  gboolean ret = FALSE;
-  GList *accounts, *l;
-
-  accounts = tp_account_manager_get_valid_accounts (manager);
-
-  for (l = accounts ; l != NULL; l = g_list_next (l))
-    {
-      if (tp_strdiff (tp_account_get_protocol (l->data), "local-xmpp"))
-        {
-          ret = TRUE;
-          break;
-        }
-    }
-
-  g_list_free (accounts);
-
-  return ret;
-}
-
-/* Try to import accounts from MC4 and returns TRUE if we should display the
- * accounts assistant. */
-static gboolean
-should_show_account_assistant (TpAccountManager *account_mgr,
-    EmpathyConnectionManagers *cm_mgr)
-{
-  g_return_val_if_fail (tp_account_manager_is_prepared (account_mgr,
-      TP_ACCOUNT_MANAGER_FEATURE_CORE), FALSE);
-  g_return_val_if_fail (empathy_connection_managers_is_ready (cm_mgr), FALSE);
-
-  if (empathy_import_mc4_has_imported ())
-    return FALSE;
-
-  if (empathy_import_mc4_accounts (cm_mgr))
-    return FALSE;
-
-  if (start_hidden)
-    return FALSE;
-
-  if (has_non_salut_accounts (account_mgr))
-    return FALSE;
-
-  if (!should_create_salut_account (account_mgr))
-    return FALSE;
-
-  return TRUE;
-}
-
-static void
-connection_managers_prepare_cb (GObject *source,
-    GAsyncResult *result,
-    gpointer user_data)
-{
-  EmpathyConnectionManagers *cm_mgr = EMPATHY_CONNECTION_MANAGERS (source);
-  TpAccountManager *account_mgr = user_data;
-
-  if (!empathy_connection_managers_prepare_finish (cm_mgr, result, NULL))
-    goto out;
-
-  if (should_show_account_assistant (account_mgr, cm_mgr))
-    empathy_account_assistant_show (GTK_WINDOW (empathy_main_window_get ()),
-          cm_mgr);
-
-out:
-  g_object_unref (cm_mgr);
-  g_object_unref (account_mgr);
-}
-
-static void
-account_manager_ready_for_show_assistant (GObject *source_object,
-    GAsyncResult *result,
-    gpointer user_data)
-{
-  TpAccountManager *account_mgr = TP_ACCOUNT_MANAGER (source_object);
-  GError *error = NULL;
-  EmpathyConnectionManagers *cm_mgr;
-
-  if (!tp_account_manager_prepare_finish (account_mgr, result, &error))
-    {
-      DEBUG ("Failed to prepare account manager: %s", error->message);
-      g_error_free (error);
-      g_object_unref (account_mgr);
-      return;
-    }
-
-  cm_mgr = empathy_connection_managers_dup_singleton ();
-
-  empathy_connection_managers_prepare_async (cm_mgr,
-      connection_managers_prepare_cb, account_mgr);
-}
-
-static void
-maybe_show_account_assistant (void)
-{
-  TpAccountManager *account_mgr = tp_account_manager_dup ();
-
-  tp_account_manager_prepare_async (account_mgr, NULL,
-      account_manager_ready_for_show_assistant, NULL);
-}
-
 static void
 migrate_config_to_xdg_dir (void)
 {
@@ -337,83 +232,26 @@ migrate_config_to_xdg_dir (void)
 }
 
 static void
-connection_managers_prepare_for_accounts (GObject *source,
-    GAsyncResult *result,
-    gpointer user_data)
-{
-  EmpathyConnectionManagers *cm_mgr = EMPATHY_CONNECTION_MANAGERS (source);
-  GtkWidget *ui;
-
-  if (!empathy_connection_managers_prepare_finish (cm_mgr, result, NULL))
-    goto out;
-
-  ui = empathy_account_assistant_show (GTK_WINDOW (empathy_main_window_get ()),
-          cm_mgr);
-
-  if (account_dialog_only)
-    g_signal_connect (ui, "destroy", G_CALLBACK (gtk_main_quit), NULL);
-
-out:
-  g_object_unref (cm_mgr);
-}
-
-static void
-do_show_accounts_ui (GtkWindow *window,
-    TpAccountManager *manager)
+accounts_application_exited_cb (GPid pid,
+    gint status,
+    gpointer data)
 {
-  if (has_non_salut_accounts (manager))
+  if (status)
     {
-      GtkWidget *ui;
-
-      ui = empathy_accounts_dialog_show (window, NULL);
-
-      if (account_dialog_only)
-        g_signal_connect (ui, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+      g_warning ("accounts application exited with status %d: '%s'",
+          status, g_strerror (status));
     }
-  else
-    {
-      EmpathyConnectionManagers *cm_mgr;
-
-      cm_mgr = empathy_connection_managers_dup_singleton ();
 
-      empathy_connection_managers_prepare_async (cm_mgr,
-          connection_managers_prepare_for_accounts, NULL);
-    }
-}
-
-static void
-account_manager_ready_for_accounts_cb (GObject *source_object,
-    GAsyncResult *result,
-    gpointer user_data)
-{
-  TpAccountManager *manager = TP_ACCOUNT_MANAGER (source_object);
-  GError *error = NULL;
-
-  if (!tp_account_manager_prepare_finish (manager, result, &error))
-    {
-      DEBUG ("Failed to prepare account manager: %s", error->message);
-      g_error_free (error);
-      return;
-    }
-
-  do_show_accounts_ui (user_data, manager);
+  if (account_dialog_only)
+    gtk_main_quit ();
 }
 
 static void
-show_accounts_ui (GtkWindow *window,
-    gboolean force)
+show_accounts_ui (GdkScreen *screen,
+    gboolean try_import)
 {
-  TpAccountManager *manager;
-
-  if (!force)
-    return;
-
-  manager = tp_account_manager_dup ();
-
-  tp_account_manager_prepare_async (manager, NULL,
-      account_manager_ready_for_accounts_cb, window);
-
-  g_object_unref (manager);
+  empathy_accounts_dialog_show_application (screen,
+      accounts_application_exited_cb, NULL, NULL, try_import, start_hidden);
 }
 
 static UniqueResponse
@@ -430,17 +268,18 @@ unique_app_message_cb (UniqueApp *unique_app,
 
   if (command == COMMAND_ACCOUNTS_DIALOG)
     {
-      show_accounts_ui (NULL, TRUE);
+      show_accounts_ui (gdk_screen_get_default (), TRUE);
     }
   else
     {
+      /* XXX: the standalone app somewhat breaks this case, since
+       * communicating it would be a pain */
+
       /* We're requested to show stuff again, disable the start hidden global
        * in case the accounts wizard wants to pop up.
        */
       start_hidden = FALSE;
 
-      show_accounts_ui (window, FALSE);
-
       gtk_window_set_screen (GTK_WINDOW (window),
           unique_message_data_get_screen (data));
       gtk_window_set_startup_id (GTK_WINDOW (window),
@@ -563,7 +402,7 @@ account_manager_ready_cb (GObject *source_object,
       /* if current state is Offline, then put it online */
       empathy_idle_set_state (idle, TP_CONNECTION_PRESENCE_TYPE_AVAILABLE);
 
-  maybe_show_account_assistant ();
+  show_accounts_ui (gdk_screen_get_default (), TRUE);
 
   g_object_unref (idle);
   g_object_unref (connectivity);
@@ -845,7 +684,7 @@ main (int argc, char *argv[])
   if (account_dialog_only)
     {
       account_manager = tp_account_manager_dup ();
-      show_accounts_ui (NULL, TRUE);
+      show_accounts_ui (gdk_screen_get_default (), FALSE);
 
       gtk_main ();
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]