diff options
author | Sjoerd Simons <sjoerd.simons@collabora.co.uk> | 2009-08-25 18:18:05 +0800 |
---|---|---|
committer | Sjoerd Simons <sjoerd.simons@collabora.co.uk> | 2009-08-25 18:35:05 +0800 |
commit | 2e6d8132394680ea42a3ebdc1daad33ff5e07b86 (patch) | |
tree | 0bf9179a649dad69089a44270fcf49514a9c80e4 /src | |
parent | 7cfb268c7d96f929646c5eb093e6f07aa8b1abea (diff) | |
parent | d7f82b00ea09c62be272ed2d0c98e9120a722ca9 (diff) | |
download | gsoc2013-empathy-2e6d8132394680ea42a3ebdc1daad33ff5e07b86.tar gsoc2013-empathy-2e6d8132394680ea42a3ebdc1daad33ff5e07b86.tar.gz gsoc2013-empathy-2e6d8132394680ea42a3ebdc1daad33ff5e07b86.tar.bz2 gsoc2013-empathy-2e6d8132394680ea42a3ebdc1daad33ff5e07b86.tar.lz gsoc2013-empathy-2e6d8132394680ea42a3ebdc1daad33ff5e07b86.tar.xz gsoc2013-empathy-2e6d8132394680ea42a3ebdc1daad33ff5e07b86.tar.zst gsoc2013-empathy-2e6d8132394680ea42a3ebdc1daad33ff5e07b86.zip |
Merge branch 'mc5', fixes bug #590165
Diffstat (limited to 'src')
27 files changed, 4426 insertions, 2590 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 42485b7d1..6896c03f3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -31,6 +31,7 @@ BUILT_SOURCES= \ empathy_handwritten_source = \ empathy.c \ 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-call-window.c empathy-call-window.h \ empathy-call-window-fullscreen.c empathy-call-window-fullscreen.h \ @@ -38,9 +39,12 @@ empathy_handwritten_source = \ empathy-debug-dialog.c empathy-debug-dialog.h \ empathy-chat-window.c empathy-chat-window.h \ empathy-event-manager.c empathy-event-manager.h \ + empathy-import-mc4-accounts.c empathy-import-mc4-accounts.h \ empathy-ft-manager.c empathy-ft-manager.h \ empathy-import-dialog.c empathy-import-dialog.h \ + empathy-import-widget.c empathy-import-widget.h \ empathy-import-pidgin.c empathy-import-pidgin.h \ + empathy-import-utils.c empathy-import-utils.h \ empathy-main-window.c empathy-main-window.h \ empathy-misc.c empathy-misc.h \ empathy-new-chatroom-dialog.c empathy-new-chatroom-dialog.h \ @@ -51,7 +55,6 @@ empathy_handwritten_source = \ empathy_SOURCES = \ $(empathy_handwritten_source) \ - bacon-message-connection.c bacon-message-connection.h \ ephy-spinner.c ephy-spinner.h nodist_empathy_SOURCES = $(BUILT_SOURCES) diff --git a/src/bacon-message-connection.c b/src/bacon-message-connection.c deleted file mode 100644 index c9fda4aeb..000000000 --- a/src/bacon-message-connection.c +++ /dev/null @@ -1,412 +0,0 @@ -/* - * Copyright (C) 2003 Bastien Nocera <hadess@hadess.net> - * - * 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. - * - * The Totem project hereby grant permission for non-gpl compatible GStreamer - * plugins to be used and distributed together with GStreamer and Totem. This - * permission are above and beyond the permissions granted by the GPL license - * Totem is covered by. - * - * Monday 7th February 2005: Christian Schaller: Add excemption clause. - * See license_change file for details. - * - */ - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <errno.h> - -#include "bacon-message-connection.h" - -#ifndef UNIX_PATH_MAX -#define UNIX_PATH_MAX 108 -#endif - -struct BaconMessageConnection { - /* A server accepts connections */ - gboolean is_server; - - /* The socket path itself */ - char *path; - - /* File descriptor of the socket */ - int fd; - /* Channel to watch */ - GIOChannel *chan; - /* Event id returned by g_io_add_watch() */ - int conn_id; - - /* Connections accepted by this connection */ - GSList *accepted_connections; - - /* callback */ - void (*func) (const char *message, gpointer user_data); - gpointer data; -}; - -static gboolean -test_is_socket (const char *path) -{ - struct stat s; - - if (stat (path, &s) == -1) - return FALSE; - - if (S_ISSOCK (s.st_mode)) - return TRUE; - - return FALSE; -} - -static gboolean -is_owned_by_user_and_socket (const char *path) -{ - struct stat s; - - if (stat (path, &s) == -1) - return FALSE; - - if (s.st_uid != geteuid ()) - return FALSE; - - if ((s.st_mode & S_IFSOCK) != S_IFSOCK) - return FALSE; - - return TRUE; -} - -static gboolean server_cb (GIOChannel *source, - GIOCondition condition, gpointer data); - -static gboolean -setup_connection (BaconMessageConnection *conn) -{ - int fdflags; - - g_return_val_if_fail (conn->chan == NULL, FALSE); - - /* Add CLOEXEC flag on the fd to make sure the socket get closed - * if exec is called. */ - fdflags = fcntl (conn->fd, F_GETFD, 0); - if (fdflags >= 0) { - fdflags |= FD_CLOEXEC; - fcntl (conn->fd, F_SETFD, fdflags); - } - - conn->chan = g_io_channel_unix_new (conn->fd); - if (!conn->chan) { - return FALSE; - } - g_io_channel_set_line_term (conn->chan, "\n", 1); - conn->conn_id = g_io_add_watch (conn->chan, G_IO_IN, server_cb, conn); - - return TRUE; -} - -static void -accept_new_connection (BaconMessageConnection *server_conn) -{ - BaconMessageConnection *conn; - int alen; - - g_return_if_fail (server_conn->is_server); - - conn = g_new0 (BaconMessageConnection, 1); - conn->is_server = FALSE; - conn->func = server_conn->func; - conn->data = server_conn->data; - - conn->fd = accept (server_conn->fd, NULL, (guint *)&alen); - - server_conn->accepted_connections = - g_slist_prepend (server_conn->accepted_connections, conn); - - setup_connection (conn); -} - -static gboolean -server_cb (GIOChannel *source, GIOCondition condition, gpointer data) -{ - BaconMessageConnection *conn = (BaconMessageConnection *)data; - char *message, *subs, buf; - int cd, rc, offset; - gboolean finished; - - offset = 0; - if (conn->is_server && conn->fd == g_io_channel_unix_get_fd (source)) { - accept_new_connection (conn); - return TRUE; - } - message = g_malloc (1); - cd = conn->fd; - rc = read (cd, &buf, 1); - while (rc > 0 && buf != '\n') - { - message = g_realloc (message, rc + offset + 1); - message[offset] = buf; - offset = offset + rc; - rc = read (cd, &buf, 1); - } - if (rc <= 0) { - g_io_channel_shutdown (conn->chan, FALSE, NULL); - g_io_channel_unref (conn->chan); - conn->chan = NULL; - close (conn->fd); - conn->fd = -1; - g_free (message); - conn->conn_id = 0; - - return FALSE; - } - message[offset] = '\0'; - - subs = message; - finished = FALSE; - - while (finished == FALSE && *subs != '\0') - { - if (conn->func != NULL) - (*conn->func) (subs, conn->data); - - subs += strlen (subs) + 1; - if (subs - message >= offset) - finished = TRUE; - } - - g_free (message); - - return TRUE; -} - -static char * -find_file_with_pattern (const char *dir, const char *pattern) -{ - GDir *filedir; - char *found_filename; - const char *filename; - GPatternSpec *pat; - - filedir = g_dir_open (dir, 0, NULL); - if (filedir == NULL) - return NULL; - - pat = g_pattern_spec_new (pattern); - if (pat == NULL) - { - g_dir_close (filedir); - return NULL; - } - - found_filename = NULL; - - while ((filename = g_dir_read_name (filedir))) - { - if (g_pattern_match_string (pat, filename)) - { - char *tmp = g_build_filename (dir, filename, NULL); - if (is_owned_by_user_and_socket (tmp)) - found_filename = g_strdup (filename); - g_free (tmp); - } - - if (found_filename != NULL) - break; - } - - g_pattern_spec_free (pat); - g_dir_close (filedir); - - return found_filename; -} - -static char * -socket_filename (const char *prefix) -{ - char *pattern, *newfile, *path, *filename; - const char *tmpdir; - - pattern = g_strdup_printf ("%s.%s.*", prefix, g_get_user_name ()); - tmpdir = g_get_tmp_dir (); - filename = find_file_with_pattern (tmpdir, pattern); - if (filename == NULL) - { - newfile = g_strdup_printf ("%s.%s.%u", prefix, - g_get_user_name (), g_random_int ()); - path = g_build_filename (tmpdir, newfile, NULL); - g_free (newfile); - } else { - path = g_build_filename (tmpdir, filename, NULL); - g_free (filename); - } - - g_free (pattern); - return path; -} - -static gboolean -try_server (BaconMessageConnection *conn) -{ - struct sockaddr_un uaddr; - - uaddr.sun_family = AF_UNIX; - strncpy (uaddr.sun_path, conn->path, - MIN (strlen(conn->path)+1, UNIX_PATH_MAX)); - conn->fd = socket (PF_UNIX, SOCK_STREAM, 0); - if (bind (conn->fd, (struct sockaddr *) &uaddr, sizeof (uaddr)) == -1) - { - conn->fd = -1; - return FALSE; - } - listen (conn->fd, 5); - - return setup_connection (conn); -} - -static gboolean -try_client (BaconMessageConnection *conn) -{ - struct sockaddr_un uaddr; - - uaddr.sun_family = AF_UNIX; - strncpy (uaddr.sun_path, conn->path, - MIN(strlen(conn->path)+1, UNIX_PATH_MAX)); - conn->fd = socket (PF_UNIX, SOCK_STREAM, 0); - if (connect (conn->fd, (struct sockaddr *) &uaddr, - sizeof (uaddr)) == -1) - { - conn->fd = -1; - return FALSE; - } - - return setup_connection (conn); -} - -BaconMessageConnection * -bacon_message_connection_new (const char *prefix) -{ - BaconMessageConnection *conn; - - g_return_val_if_fail (prefix != NULL, NULL); - - conn = g_new0 (BaconMessageConnection, 1); - conn->path = socket_filename (prefix); - - if (test_is_socket (conn->path) == FALSE) - { - if (!try_server (conn)) - { - bacon_message_connection_free (conn); - return NULL; - } - - conn->is_server = TRUE; - return conn; - } - - if (try_client (conn) == FALSE) - { - unlink (conn->path); - try_server (conn); - if (conn->fd == -1) - { - bacon_message_connection_free (conn); - return NULL; - } - - conn->is_server = TRUE; - return conn; - } - - conn->is_server = FALSE; - return conn; -} - -void -bacon_message_connection_free (BaconMessageConnection *conn) -{ - GSList *child_conn; - - g_return_if_fail (conn != NULL); - /* Only servers can accept other connections */ - g_return_if_fail (conn->is_server != FALSE || - conn->accepted_connections == NULL); - - child_conn = conn->accepted_connections; - while (child_conn != NULL) { - bacon_message_connection_free (child_conn->data); - child_conn = g_slist_next (child_conn); - } - g_slist_free (conn->accepted_connections); - - if (conn->conn_id) { - g_source_remove (conn->conn_id); - conn->conn_id = 0; - } - if (conn->chan) { - g_io_channel_shutdown (conn->chan, FALSE, NULL); - g_io_channel_unref (conn->chan); - } - - if (conn->is_server != FALSE) { - unlink (conn->path); - } - if (conn->fd != -1) { - close (conn->fd); - } - - g_free (conn->path); - g_free (conn); -} - -void -bacon_message_connection_set_callback (BaconMessageConnection *conn, - BaconMessageReceivedFunc func, - gpointer user_data) -{ - g_return_if_fail (conn != NULL); - - conn->func = func; - conn->data = user_data; -} - -void -bacon_message_connection_send (BaconMessageConnection *conn, - const char *message) -{ - g_return_if_fail (conn != NULL); - g_return_if_fail (message != NULL); - - g_io_channel_write_chars (conn->chan, message, strlen (message), - NULL, NULL); - g_io_channel_write_chars (conn->chan, "\n", 1, NULL, NULL); - g_io_channel_flush (conn->chan, NULL); -} - -gboolean -bacon_message_connection_get_is_server (BaconMessageConnection *conn) -{ - g_return_val_if_fail (conn != NULL, FALSE); - - return conn->is_server; -} - diff --git a/src/bacon-message-connection.h b/src/bacon-message-connection.h deleted file mode 100644 index db4a91262..000000000 --- a/src/bacon-message-connection.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2003 Bastien Nocera <hadess@hadess.net> - * - * 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. - * - * The Totem project hereby grant permission for non-gpl compatible GStreamer - * plugins to be used and distributed together with GStreamer and Totem. This - * permission are above and beyond the permissions granted by the GPL license - * Totem is covered by. - * - * Monday 7th February 2005: Christian Schaller: Add excemption clause. - * See license_change file for details. - * - */ - -#ifndef BACON_MESSAGE_CONNECTION_H -#define BACON_MESSAGE_CONNECTION_H - -#include <glib.h> - -G_BEGIN_DECLS - -typedef void (*BaconMessageReceivedFunc) (const char *message, - gpointer user_data); - -typedef struct BaconMessageConnection BaconMessageConnection; - -BaconMessageConnection *bacon_message_connection_new (const char *prefix); -void bacon_message_connection_free (BaconMessageConnection *conn); -void bacon_message_connection_set_callback (BaconMessageConnection *conn, - BaconMessageReceivedFunc func, - gpointer user_data); -void bacon_message_connection_send (BaconMessageConnection *conn, - const char *message); -gboolean bacon_message_connection_get_is_server (BaconMessageConnection *conn); - -G_END_DECLS - -#endif /* BACON_MESSAGE_CONNECTION_H */ diff --git a/src/empathy-account-assistant.c b/src/empathy-account-assistant.c new file mode 100644 index 000000000..d8aa46f1d --- /dev/null +++ b/src/empathy-account-assistant.c @@ -0,0 +1,941 @@ +/* + * Copyright (C) 2009 Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> + */ + +/* empathy-account-assistant.c */ + +#include <glib/gi18n.h> +#include <telepathy-glib/util.h> +#include <gdk/gdkkeysyms.h> + +#include "empathy-account-assistant.h" +#include "empathy-import-widget.h" +#include "empathy-import-utils.h" + +#include <libempathy/empathy-account-settings.h> +#include <libempathy/empathy-utils.h> + +#include <libempathy-gtk/empathy-account-widget.h> +#include <libempathy-gtk/empathy-protocol-chooser.h> +#include <libempathy-gtk/empathy-ui-utils.h> + +G_DEFINE_TYPE (EmpathyAccountAssistant, empathy_account_assistant, + GTK_TYPE_ASSISTANT) + +#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyAccountAssistant) + +typedef enum { + RESPONSE_IMPORT = 1, + RESPONSE_ENTER_ACCOUNT = 2, + RESPONSE_CREATE_ACCOUNT = 3, + RESPONSE_SALUT_ONLY = 4 +} FirstPageResponse; + +typedef enum { + RESPONSE_CREATE_AGAIN = 1, + RESPONSE_CREATE_STOP = 2 +} CreateEnterPageResponse; + +enum { + PAGE_INTRO = 0, + PAGE_IMPORT = 1, + PAGE_ENTER_CREATE = 2, +}; + +enum { + PROP_PARENT = 1 +}; + +typedef struct { + FirstPageResponse first_resp; + CreateEnterPageResponse create_enter_resp; + gboolean enter_create_forward; + + /* enter or create page */ + GtkWidget *enter_or_create_page; + GtkWidget *current_account_widget; + EmpathyAccountWidget *current_widget_object; + GtkWidget *first_label; + GtkWidget *second_label; + GtkWidget *chooser; + GtkWidget *create_again_radio; + EmpathyAccountSettings *settings; + gboolean is_creating; + + /* import page */ + EmpathyImportWidget *iw; + + GtkWindow *parent_window; + + gboolean dispose_run; +} EmpathyAccountAssistantPriv; + +static GtkWidget * account_assistant_build_enter_or_create_page ( + EmpathyAccountAssistant *self); +static void account_assistant_finish_enter_or_create_page ( + EmpathyAccountAssistant *self, + gboolean is_enter); + +static GtkWidget * +account_assistant_build_error_page (EmpathyAccountAssistant *self, + GError *error, gint page_num) +{ + GtkWidget *main_vbox, *w, *hbox; + GString *str; + char *message; + PangoAttrList *list; + EmpathyAccountAssistantPriv *priv = GET_PRIV (self); + + main_vbox = gtk_vbox_new (FALSE, 12); + gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12); + gtk_widget_show (main_vbox); + + hbox = gtk_hbox_new (FALSE, 12); + gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0); + gtk_widget_show (hbox); + + w = gtk_image_new_from_stock (GTK_STOCK_DIALOG_ERROR, + GTK_ICON_SIZE_DIALOG); + gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0); + gtk_widget_show (w); + + /* translators: this is followed by the "while ..." strings some lines + * down this file. + */ + str = g_string_new (_("There has been an error ")); + + if (page_num == PAGE_IMPORT) + /* translators: this follows the "There has been an error " string */ + str = g_string_append (str, _("while importing the accounts.")); + else if (page_num >= PAGE_ENTER_CREATE && + priv->first_resp == RESPONSE_ENTER_ACCOUNT) + /* translators: this follows the "There has been an error " string */ + str = g_string_append (str, _("while parsing the account details.")); + else if (page_num >= PAGE_ENTER_CREATE && + priv->first_resp == RESPONSE_CREATE_ACCOUNT) + /* translators: this follows the "There has been an error " string */ + str = g_string_append (str, _("while creating the account.")); + + message = g_string_free (str, FALSE); + + w = gtk_label_new (message); + gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0); + list = pango_attr_list_new (); + pango_attr_list_insert (list, pango_attr_scale_new (PANGO_SCALE_LARGE)); + pango_attr_list_insert (list, pango_attr_weight_new (PANGO_WEIGHT_BOLD)); + gtk_label_set_attributes (GTK_LABEL (w), list); + gtk_misc_set_alignment (GTK_MISC (w), 0, 0.5); + gtk_label_set_line_wrap (GTK_LABEL (w), TRUE); + gtk_widget_show (w); + + g_free (message); + pango_attr_list_unref (list); + + message = g_markup_printf_escaped + (_("The error message was: <span style=\"italic\">%s</span>"), + error->message); + w = gtk_label_new (message); + gtk_label_set_use_markup (GTK_LABEL (w), TRUE); + gtk_box_pack_start (GTK_BOX (main_vbox), w, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (w), 0, 0.5); + gtk_widget_show (w); + + w = gtk_label_new (_("You can either go back and try to enter your " + "accounts' details again or quit this wizard and add accounts " + "later from the Edit menu.")); + gtk_box_pack_start (GTK_BOX (main_vbox), w, FALSE, FALSE, 6); + gtk_misc_set_alignment (GTK_MISC (w), 0, 0.5); + gtk_label_set_line_wrap (GTK_LABEL (w), TRUE); + gtk_widget_show (w); + + return main_vbox; +} + +static void +account_assistant_back_button_clicked_cb (GtkButton *button, + EmpathyAccountAssistant *self) +{ + gint page_num; + + page_num = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button), + "page-num")); + gtk_assistant_remove_action_widget (GTK_ASSISTANT (self), + GTK_WIDGET (button)); + gtk_assistant_set_current_page (GTK_ASSISTANT (self), page_num); +} + +static void +account_assistant_present_error_page (EmpathyAccountAssistant *self, + GError *error, gint page_num) +{ + GtkWidget *error_page, *back_button; + gint num; + + error_page = account_assistant_build_error_page (self, error, + page_num); + num = gtk_assistant_append_page (GTK_ASSISTANT (self), error_page); + gtk_assistant_set_page_title (GTK_ASSISTANT (self), error_page, + _("An error occurred")); + gtk_assistant_set_page_type (GTK_ASSISTANT (self), error_page, + GTK_ASSISTANT_PAGE_SUMMARY); + + back_button = gtk_button_new_from_stock (GTK_STOCK_GO_BACK); + gtk_assistant_add_action_widget (GTK_ASSISTANT (self), back_button); + g_object_set_data (G_OBJECT (back_button), + "page-num", GINT_TO_POINTER (page_num)); + g_signal_connect (back_button, "clicked", + G_CALLBACK (account_assistant_back_button_clicked_cb), self); + gtk_widget_show (back_button); + + gtk_assistant_set_current_page (GTK_ASSISTANT (self), num); +} + +static void +account_assistant_reset_enter_create_page (EmpathyAccountAssistant *self) +{ + EmpathyAccountAssistantPriv *priv = GET_PRIV (self); + GtkWidget *page; + gint idx; + + page = account_assistant_build_enter_or_create_page (self); + idx = gtk_assistant_append_page (GTK_ASSISTANT (self), page); + gtk_assistant_set_page_type (GTK_ASSISTANT (self), page, + GTK_ASSISTANT_PAGE_CONFIRM); + priv->enter_or_create_page = page; + + gtk_assistant_set_current_page (GTK_ASSISTANT (self), idx); + + account_assistant_finish_enter_or_create_page (self, + priv->first_resp == RESPONSE_ENTER_ACCOUNT ? + TRUE : FALSE); +} + +static void +account_assistant_account_enabled_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + GError *error = NULL; + EmpathyAccountAssistant *self = user_data; + EmpathyAccountAssistantPriv *priv = GET_PRIV (self); + + empathy_account_set_enabled_finish (EMPATHY_ACCOUNT (source), + result, &error); + + if (error) + { + g_warning ("Error enabling an account: %s", error->message); + g_error_free (error); + } + + if (priv->create_enter_resp == RESPONSE_CREATE_STOP) + g_signal_emit_by_name (self, "close"); + else + account_assistant_reset_enter_create_page (self); +} + +static void +account_assistant_apply_account_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + GError *error = NULL; + EmpathyAccountAssistant *self = user_data; + EmpathyAccountAssistantPriv *priv = GET_PRIV (self); + EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (source); + EmpathyAccount *account; + + empathy_account_settings_apply_finish (settings, result, &error); + + priv->is_creating = FALSE; + + if (error != NULL) + { + account_assistant_present_error_page (self, error, + gtk_assistant_get_current_page (GTK_ASSISTANT (self))); + g_error_free (error); + return; + } + + /* enable the newly created account */ + account = empathy_account_settings_get_account (settings); + empathy_account_set_enabled_async (account, TRUE, + account_assistant_account_enabled_cb, self); +} + +static void +account_assistant_apply_account_and_finish (EmpathyAccountAssistant *self) +{ + EmpathyAccountAssistantPriv *priv = GET_PRIV (self); + + if (priv->settings == NULL) + return; + + priv->is_creating = TRUE; + + empathy_account_settings_apply_async (priv->settings, + account_assistant_apply_account_cb, self); +} + +static void +account_assistant_handle_apply_cb (EmpathyAccountWidget *widget_object, + gboolean is_valid, + EmpathyAccountAssistant *self) +{ + EmpathyAccountAssistantPriv *priv = GET_PRIV (self); + + gtk_assistant_set_page_complete (GTK_ASSISTANT (self), + priv->enter_or_create_page, is_valid); +} + +static void +account_assistant_protocol_changed_cb (GtkComboBox *chooser, + EmpathyAccountAssistant *self) +{ + TpConnectionManager *cm; + TpConnectionManagerProtocol *proto; + EmpathyAccountSettings *settings; + EmpathyAccountAssistantPriv *priv; + char *str; + GtkWidget *account_widget; + EmpathyAccountWidget *widget_object = NULL; + + priv = GET_PRIV (self); + + cm = empathy_protocol_chooser_dup_selected ( + EMPATHY_PROTOCOL_CHOOSER (chooser), &proto); + + if (cm == NULL || proto == NULL) + /* we are not ready yet */ + return; + + /* Create account */ + /* To translator: %s is the protocol name */ + str = g_strdup_printf (_("New %s account"), proto->name); + + settings = empathy_account_settings_new (cm->name, proto->name, str); + + if (priv->first_resp == RESPONSE_CREATE_ACCOUNT) + empathy_account_settings_set_boolean (settings, "register", TRUE); + + widget_object = empathy_account_widget_new_for_protocol (proto->name, + settings, TRUE); + account_widget = empathy_account_widget_get_widget (widget_object); + + if (priv->current_account_widget != NULL) + { + g_signal_handlers_disconnect_by_func (priv->current_widget_object, + account_assistant_handle_apply_cb, self); + gtk_widget_destroy (priv->current_account_widget); + } + + priv->current_account_widget = account_widget; + priv->current_widget_object = widget_object; + + if (priv->settings != NULL) + g_object_unref (priv->settings); + + priv->settings = settings; + + g_signal_connect (priv->current_widget_object, "handle-apply", + G_CALLBACK (account_assistant_handle_apply_cb), self); + + gtk_box_pack_start (GTK_BOX (priv->enter_or_create_page), account_widget, + FALSE, FALSE, 0); + gtk_widget_show (account_widget); + + g_free (str); +} + +static gboolean +account_assistant_chooser_enter_details_filter_func ( + TpConnectionManager *cm, + TpConnectionManagerProtocol *protocol, + gpointer user_data) +{ + if (!tp_strdiff (protocol->name, "local-xmpp") || + !tp_strdiff (protocol->name, "irc")) + return FALSE; + + return TRUE; +} + +static gboolean +account_assistant_chooser_create_account_filter_func ( + TpConnectionManager *cm, + TpConnectionManagerProtocol *protocol, + gpointer user_data) +{ + return tp_connection_manager_protocol_can_register (protocol); +} + +static void +account_assistant_finish_enter_or_create_page (EmpathyAccountAssistant *self, + gboolean is_enter) +{ + EmpathyAccountAssistantPriv *priv = GET_PRIV (self); + + if (is_enter) + { + gtk_label_set_label (GTK_LABEL (priv->first_label), + _("What kind of chat account do you have?")); + /* gtk_label_set_label (GTK_LABEL (priv->second_label), + _("If you have other accounts to set up, you can do " + "that at any time from the Edit menu.")); + */ + gtk_label_set_label (GTK_LABEL (priv->second_label), + _("Do you have any other chat accounts you want to set up?")); + empathy_protocol_chooser_set_visible ( + EMPATHY_PROTOCOL_CHOOSER (priv->chooser), + account_assistant_chooser_enter_details_filter_func, self); + + gtk_assistant_set_page_title (GTK_ASSISTANT (self), + priv->enter_or_create_page, _("Enter your account details")); + } + else + { + gtk_label_set_label (GTK_LABEL (priv->first_label), + _("What kind of chat account do you want to create?")); + /* gtk_label_set_label (GTK_LABEL (priv->second_label), + _("You can register other accounts, or setup " + "an existing one at any time from the Edit menu.")); + */ + gtk_label_set_label (GTK_LABEL (priv->second_label), + _("Do you want to create other chat accounts?")); + empathy_protocol_chooser_set_visible ( + EMPATHY_PROTOCOL_CHOOSER (priv->chooser), + account_assistant_chooser_create_account_filter_func, self); + + gtk_assistant_set_page_title (GTK_ASSISTANT (self), + priv->enter_or_create_page, + _("Enter the details for the new account")); + } + + g_signal_connect (priv->chooser, "changed", + G_CALLBACK (account_assistant_protocol_changed_cb), self); + + /* trigger show the first account widget */ + account_assistant_protocol_changed_cb (GTK_COMBO_BOX (priv->chooser), self); +} + +static gint +account_assistant_page_forward_func (gint current_page, + gpointer user_data) +{ + EmpathyAccountAssistant *self = user_data; + EmpathyAccountAssistantPriv *priv = GET_PRIV (self); + gint retval; + + retval = current_page; + + if (current_page == PAGE_INTRO) + { + if (priv->first_resp == RESPONSE_ENTER_ACCOUNT || + priv->first_resp == RESPONSE_CREATE_ACCOUNT) + retval = PAGE_ENTER_CREATE; + if (priv->first_resp == RESPONSE_IMPORT) + retval = PAGE_IMPORT; + } + + if (current_page == PAGE_IMPORT || + current_page >= PAGE_ENTER_CREATE) + /* don't forward anymore */ + retval = -1; + + if (current_page >= PAGE_ENTER_CREATE && + priv->create_enter_resp == RESPONSE_CREATE_AGAIN) + { + priv->enter_create_forward = TRUE; + retval = current_page; + } + + return retval; +} + +static void +account_assistant_radio_choice_toggled_cb (GtkToggleButton *button, + EmpathyAccountAssistant *self) +{ + FirstPageResponse response; + EmpathyAccountAssistantPriv *priv = GET_PRIV (self); + GtkWidget *intro_page; + + response = GPOINTER_TO_INT (g_object_get_data + (G_OBJECT (button), "response")); + + priv->first_resp = response; + + intro_page = gtk_assistant_get_nth_page (GTK_ASSISTANT (self), + PAGE_INTRO); + + if (response == RESPONSE_SALUT_ONLY) + gtk_assistant_set_page_type (GTK_ASSISTANT (self), intro_page, + GTK_ASSISTANT_PAGE_SUMMARY); + else + gtk_assistant_set_page_type (GTK_ASSISTANT (self), intro_page, + GTK_ASSISTANT_PAGE_INTRO); +} + +static GtkWidget * +account_assistant_build_introduction_page (EmpathyAccountAssistant *self) +{ + EmpathyAccountAssistantPriv *priv = GET_PRIV (self); + GtkWidget *main_vbox, *hbox_1, *w, *vbox_1; + GtkWidget *radio = NULL; + GdkPixbuf *pix; + const gchar *str; + + main_vbox = gtk_vbox_new (FALSE, 12); + gtk_widget_show (main_vbox); + gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12); + + hbox_1 = gtk_hbox_new (FALSE, 12); + gtk_box_pack_start (GTK_BOX (main_vbox), hbox_1, TRUE, TRUE, 0); + gtk_widget_show (hbox_1); + + w = gtk_label_new ( + _("With Empathy you can chat with people " + "online nearby and with friends and colleagues " + "who use Google Talk, AIM, Windows Live " + "and many other chat programs. With a microphone " + "or a webcam you can also have audio or video calls.")); + gtk_misc_set_alignment (GTK_MISC (w), 0, 0.5); + gtk_label_set_line_wrap (GTK_LABEL (w), TRUE); + gtk_box_pack_start (GTK_BOX (hbox_1), w, FALSE, FALSE, 0); + gtk_widget_show (w); + + pix = empathy_pixbuf_from_icon_name_sized ("empathy", 80); + w = gtk_image_new_from_pixbuf (pix); + gtk_box_pack_start (GTK_BOX (hbox_1), w, FALSE, FALSE, 6); + gtk_widget_show (w); + + g_object_unref (pix); + + w = gtk_label_new (_("Do you have an account you've been using " + "with another chat program?")); + gtk_misc_set_alignment (GTK_MISC (w), 0, 0); + gtk_label_set_line_wrap (GTK_LABEL (w), TRUE); + gtk_box_pack_start (GTK_BOX (main_vbox), w, FALSE, FALSE, 0); + gtk_widget_show (w); + + w = gtk_alignment_new (0, 0, 0, 0); + gtk_alignment_set_padding (GTK_ALIGNMENT (w), 0, 0, 12, 0); + gtk_box_pack_start (GTK_BOX (main_vbox), w, TRUE, TRUE, 0); + gtk_widget_show (w); + + vbox_1 = gtk_vbox_new (TRUE, 0); + gtk_container_add (GTK_CONTAINER (w), vbox_1); + gtk_widget_show (vbox_1); + + if (empathy_import_accounts_to_import ()) + { + hbox_1 = gtk_hbox_new (FALSE, 0); + gtk_box_pack_start (GTK_BOX (vbox_1), hbox_1, TRUE, TRUE, 0); + gtk_widget_show (hbox_1); + + radio = gtk_radio_button_new_with_label (NULL, + _("Yes, import my account details from ")); + gtk_box_pack_start (GTK_BOX (hbox_1), radio, TRUE, TRUE, 0); + g_object_set_data (G_OBJECT (radio), "response", + GINT_TO_POINTER (RESPONSE_IMPORT)); + gtk_widget_show (radio); + + w = gtk_combo_box_new_text (); + gtk_combo_box_append_text (GTK_COMBO_BOX (w), "Pidgin"); + gtk_box_pack_start (GTK_BOX (hbox_1), w, TRUE, TRUE, 0); + gtk_combo_box_set_active (GTK_COMBO_BOX (w), 0); + gtk_widget_show (w); + + g_signal_connect (radio, "clicked", + G_CALLBACK (account_assistant_radio_choice_toggled_cb), self); + priv->first_resp = RESPONSE_IMPORT; + } + else + { + priv->first_resp = RESPONSE_ENTER_ACCOUNT; + } + + str = _("Yes, I'll enter my account details now"); + + if (radio == NULL) + { + radio = gtk_radio_button_new_with_label (NULL, str); + w = radio; + } + else + { + w = gtk_radio_button_new_with_label_from_widget ( + GTK_RADIO_BUTTON (radio), str); + } + + gtk_box_pack_start (GTK_BOX (vbox_1), w, TRUE, TRUE, 0); + g_object_set_data (G_OBJECT (w), "response", + GINT_TO_POINTER (RESPONSE_ENTER_ACCOUNT)); + gtk_widget_show (w); + + g_signal_connect (w, "clicked", + G_CALLBACK (account_assistant_radio_choice_toggled_cb), self); + + w = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio), + _("No, I want a new account")); + gtk_box_pack_start (GTK_BOX (vbox_1), w, TRUE, TRUE, 0); + g_object_set_data (G_OBJECT (w), "response", + GINT_TO_POINTER (RESPONSE_CREATE_ACCOUNT)); + gtk_widget_show (w); + + g_signal_connect (w, "clicked", + G_CALLBACK (account_assistant_radio_choice_toggled_cb), self); + + w = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio), + _("No, I just want to see people online nearby for now")); + gtk_box_pack_start (GTK_BOX (vbox_1), w, TRUE, TRUE, 0); + g_object_set_data (G_OBJECT (w), "response", + GINT_TO_POINTER (RESPONSE_SALUT_ONLY)); + gtk_widget_show (w); + + g_signal_connect (w, "clicked", + G_CALLBACK (account_assistant_radio_choice_toggled_cb), self); + + return main_vbox; +} + +static GtkWidget * +account_assistant_build_import_page (EmpathyAccountAssistant *self) +{ + GtkWidget *main_vbox, *w, *import; + EmpathyImportWidget *iw; + EmpathyAccountAssistantPriv *priv = GET_PRIV (self); + + main_vbox = gtk_vbox_new (FALSE, 12); + gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12); + w = gtk_label_new (_("Select the accounts you want to import:")); + gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.5); + gtk_widget_show (w); + gtk_box_pack_start (GTK_BOX (main_vbox), w, FALSE, FALSE, 6); + + w = gtk_alignment_new (0, 0, 0, 0); + gtk_alignment_set_padding (GTK_ALIGNMENT (w), 0, 0, 12, 0); + gtk_box_pack_start (GTK_BOX (main_vbox), w, FALSE, FALSE, 0); + gtk_widget_show (w); + + /* NOTE: this is hardcoded as we support pidgin only */ + iw = empathy_import_widget_new (EMPATHY_IMPORT_APPLICATION_PIDGIN); + import = empathy_import_widget_get_widget (iw); + gtk_container_add (GTK_CONTAINER (w), import); + gtk_widget_show (import); + + priv->iw = iw; + + gtk_widget_show (main_vbox); + + return main_vbox; +} + +static void +account_assistant_radio_create_again_clicked_cb (GtkButton *button, + EmpathyAccountAssistant *self) +{ + CreateEnterPageResponse response; + EmpathyAccountAssistantPriv *priv = GET_PRIV (self); + + response = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button), + "response")); + + priv->create_enter_resp = response; + + gtk_assistant_set_page_type (GTK_ASSISTANT (self), + priv->enter_or_create_page, + (response == RESPONSE_CREATE_AGAIN) ? + GTK_ASSISTANT_PAGE_CONTENT : GTK_ASSISTANT_PAGE_CONFIRM); +} + +static GtkWidget * +account_assistant_build_enter_or_create_page (EmpathyAccountAssistant *self) +{ + EmpathyAccountAssistantPriv *priv = GET_PRIV (self); + GtkWidget *main_vbox, *w, *chooser, *vbox, *hbox, *radio; + + main_vbox = gtk_vbox_new (FALSE, 12); + gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12); + gtk_widget_show (main_vbox); + + w = gtk_label_new (NULL); + gtk_misc_set_alignment (GTK_MISC (w), 0, 0); + gtk_box_pack_start (GTK_BOX (main_vbox), w, FALSE, FALSE, 0); + gtk_widget_show (w); + priv->first_label = w; + + w = gtk_alignment_new (0, 0, 0, 0); + gtk_alignment_set_padding (GTK_ALIGNMENT (w), 0, 0, 12, 0); + gtk_box_pack_start (GTK_BOX (main_vbox), w, FALSE, FALSE, 0); + gtk_widget_show (w); + + chooser = empathy_protocol_chooser_new (); + gtk_container_add (GTK_CONTAINER (w), chooser); + gtk_widget_show (chooser); + priv->chooser = chooser; + + vbox = gtk_vbox_new (FALSE, 6); + gtk_box_pack_end (GTK_BOX (main_vbox), vbox, FALSE, FALSE, 0); + gtk_widget_show (vbox); + + w = gtk_label_new (NULL); + gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 0); + gtk_label_set_line_wrap (GTK_LABEL (w), TRUE); + gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.5); + gtk_widget_show (w); + priv->second_label = w; + + w = gtk_alignment_new (0, 0, 0, 0); + gtk_alignment_set_padding (GTK_ALIGNMENT (w), 0, 0, 12, 0); + gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 0); + gtk_widget_show (w); + + hbox = gtk_hbox_new (FALSE, 6); + gtk_container_add (GTK_CONTAINER (w), hbox); + gtk_widget_show (hbox); + + radio = gtk_radio_button_new_with_label (NULL, _("Yes")); + gtk_box_pack_start (GTK_BOX (hbox), radio, FALSE, FALSE, 0); + g_object_set_data (G_OBJECT (radio), "response", + GINT_TO_POINTER (RESPONSE_CREATE_AGAIN)); + gtk_widget_show (radio); + + w = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio), + _("No, that's all for now")); + gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0); + g_object_set_data (G_OBJECT (w), "response", + GINT_TO_POINTER (RESPONSE_CREATE_STOP)); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), TRUE); + priv->create_enter_resp = RESPONSE_CREATE_STOP; + priv->create_again_radio = w; + gtk_widget_show (w); + + g_signal_connect (w, "clicked", + G_CALLBACK (account_assistant_radio_create_again_clicked_cb), self); + g_signal_connect (radio, "clicked", + G_CALLBACK (account_assistant_radio_create_again_clicked_cb), self); + + return main_vbox; +} + +static void +account_assistant_close_cb (GtkAssistant *assistant, + gpointer user_data) +{ + EmpathyAccountAssistantPriv *priv = GET_PRIV (assistant); + + if (priv->is_creating) + return; + + gtk_widget_destroy (GTK_WIDGET (assistant)); +} + +static void +impl_signal_apply (GtkAssistant *assistant) +{ + EmpathyAccountAssistant *self = EMPATHY_ACCOUNT_ASSISTANT (assistant); + EmpathyAccountAssistantPriv *priv = GET_PRIV (self); + gint current_page; + + current_page = gtk_assistant_get_current_page (assistant); + + if (current_page >= PAGE_ENTER_CREATE) + account_assistant_apply_account_and_finish (self); + + if (current_page == PAGE_IMPORT) + empathy_import_widget_add_selected_accounts (priv->iw); +} + +static void +impl_signal_cancel (GtkAssistant *assistant) +{ + gtk_widget_destroy (GTK_WIDGET (assistant)); +} + +static void +impl_signal_prepare (GtkAssistant *assistant, + GtkWidget *current_page) +{ + EmpathyAccountAssistant *self = EMPATHY_ACCOUNT_ASSISTANT (assistant); + EmpathyAccountAssistantPriv *priv = GET_PRIV (self); + gint current_idx; + + current_idx = gtk_assistant_get_current_page (assistant); + + if (current_idx >= PAGE_ENTER_CREATE) + { + if (!priv->enter_create_forward) + { + account_assistant_finish_enter_or_create_page (self, + priv->first_resp == RESPONSE_ENTER_ACCOUNT ? + TRUE : FALSE); + } + else + { + priv->enter_create_forward = FALSE; + account_assistant_apply_account_and_finish (self); + } + } +} + +static void +do_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + EmpathyAccountAssistantPriv *priv = GET_PRIV (object); + + switch (property_id) + { + case PROP_PARENT: + g_value_set_object (value, priv->parent_window); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +do_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + EmpathyAccountAssistantPriv *priv = GET_PRIV (object); + + switch (property_id) + { + case PROP_PARENT: + priv->parent_window = g_value_get_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +do_constructed (GObject *object) +{ + EmpathyAccountAssistantPriv *priv = GET_PRIV (object); + + /* set us as transient for the parent window if any */ + if (priv->parent_window) + gtk_window_set_transient_for (GTK_WINDOW (object), + priv->parent_window); + + /* set the dialog hint, so this will be centered over the parent window */ + gtk_window_set_type_hint (GTK_WINDOW (object), GDK_WINDOW_TYPE_HINT_DIALOG); +} + +static void +do_dispose (GObject *obj) +{ + EmpathyAccountAssistantPriv *priv = GET_PRIV (obj); + + if (priv->dispose_run) + return; + + priv->dispose_run = TRUE; + + if (priv->settings != NULL) + { + g_object_unref (priv->settings); + priv->settings = NULL; + } + + if (G_OBJECT_CLASS (empathy_account_assistant_parent_class)->dispose != NULL) + G_OBJECT_CLASS (empathy_account_assistant_parent_class)->dispose (obj); +} + +static void +empathy_account_assistant_class_init (EmpathyAccountAssistantClass *klass) +{ + GObjectClass *oclass = G_OBJECT_CLASS (klass); + GtkAssistantClass *gtkclass = GTK_ASSISTANT_CLASS (klass); + GParamSpec *param_spec; + + oclass->get_property = do_get_property; + oclass->set_property = do_set_property; + oclass->constructed = do_constructed; + oclass->dispose = do_dispose; + + gtkclass->apply = impl_signal_apply; + gtkclass->prepare = impl_signal_prepare; + gtkclass->cancel = impl_signal_cancel; + + param_spec = g_param_spec_object ("parent-window", + "parent-window", "The parent window", + GTK_TYPE_WINDOW, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (oclass, PROP_PARENT, param_spec); + + g_type_class_add_private (klass, sizeof (EmpathyAccountAssistantPriv)); +} + +static void +empathy_account_assistant_init (EmpathyAccountAssistant *self) +{ + EmpathyAccountAssistantPriv *priv; + GtkAssistant *assistant = GTK_ASSISTANT (self); + GtkWidget *page; + + priv = G_TYPE_INSTANCE_GET_PRIVATE (self, EMPATHY_TYPE_ACCOUNT_ASSISTANT, + EmpathyAccountAssistantPriv); + self->priv = priv; + + g_signal_connect (self, "close", + G_CALLBACK (account_assistant_close_cb), NULL); + + gtk_assistant_set_forward_page_func (assistant, + account_assistant_page_forward_func, self, NULL); + + /* first page (introduction) */ + page = account_assistant_build_introduction_page (self); + gtk_assistant_append_page (assistant, page); + gtk_assistant_set_page_title (assistant, page, + _("Welcome to Empathy")); + gtk_assistant_set_page_type (assistant, page, + GTK_ASSISTANT_PAGE_INTRO); + gtk_assistant_set_page_complete (assistant, page, TRUE); + + /* second page (import accounts) */ + page = account_assistant_build_import_page (self); + gtk_assistant_append_page (assistant, page); + gtk_assistant_set_page_title (assistant, page, + _("Import your existing accounts")); + gtk_assistant_set_page_complete (assistant, page, TRUE); + gtk_assistant_set_page_type (assistant, page, GTK_ASSISTANT_PAGE_CONFIRM); + + /* third page (enter account details) */ + page = account_assistant_build_enter_or_create_page (self); + gtk_assistant_append_page (assistant, page); + gtk_assistant_set_page_type (assistant, page, GTK_ASSISTANT_PAGE_CONFIRM); + priv->enter_or_create_page = page; + + gtk_window_set_resizable (GTK_WINDOW (self), FALSE); +} + +GtkWidget * +empathy_account_assistant_new (GtkWindow *window) +{ + return g_object_new (EMPATHY_TYPE_ACCOUNT_ASSISTANT, "parent-window", + window, NULL); +} diff --git a/src/empathy-account-assistant.h b/src/empathy-account-assistant.h new file mode 100644 index 000000000..857460201 --- /dev/null +++ b/src/empathy-account-assistant.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2009 Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> + */ + +/* empathy-account-assistant.h */ + +#ifndef __EMPATHY_ACCOUNT_ASSISTANT_H__ +#define __EMPATHY_ACCOUNT_ASSISTANT_H__ + +#include <glib-object.h> +#include <gtk/gtk.h> + +G_BEGIN_DECLS + +#define EMPATHY_TYPE_ACCOUNT_ASSISTANT empathy_account_assistant_get_type() +#define EMPATHY_ACCOUNT_ASSISTANT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), EMPATHY_TYPE_ACCOUNT_ASSISTANT,\ + EmpathyAccountAssistant)) +#define EMPATHY_ACCOUNT_ASSISTANT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), EMPATHY_TYPE_ACCOUNT_ASSISTANT,\ + EmpathyAccountAssistantClass)) +#define EMPATHY_IS_ACCOUNT_ASSISTANT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EMPATHY_TYPE_ACCOUNT_ASSISTANT)) +#define EMPATHY_IS_ACCOUNT_ASSISTANT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), EMPATHY_TYPE_ACCOUNT_ASSISTANT)) +#define EMPATHY_ACCOUNT_ASSISTANT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_ACCOUNT_ASSISTANT,\ + EmpathyAccountAssistantClass)) + +typedef struct { + GtkAssistant parent; + + /* private */ + gpointer priv; +} EmpathyAccountAssistant; + +typedef struct { + GtkAssistantClass parent_class; +} EmpathyAccountAssistantClass; + +GType empathy_account_assistant_get_type (void); + +GtkWidget *empathy_account_assistant_new (GtkWindow *parent); + +G_END_DECLS + +#endif /* __EMPATHY_ACCOUNT_ASSISTANT_H__ */ diff --git a/src/empathy-accounts-dialog.c b/src/empathy-accounts-dialog.c index 5948a58ff..40f46e49e 100644 --- a/src/empathy-accounts-dialog.c +++ b/src/empathy-accounts-dialog.c @@ -1,7 +1,6 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * Copyright (C) 2005-2007 Imendio AB - * Copyright (C) 2007-2008 Collabora Ltd. + * Copyright (C) 2007-2009 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 @@ -20,6 +19,8 @@ * * Authors: Martyn Russell <martyn@imendio.com> * Xavier Claessens <xclaesse@gmail.com> + * Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> + * Jonathan Tellier <jonathan.tellier@gmail.com> */ #include <config.h> @@ -31,20 +32,24 @@ #include <glib/gi18n.h> #include <dbus/dbus-glib.h> -#include <libmissioncontrol/mc-profile.h> #include <telepathy-glib/util.h> #include <libempathy/empathy-utils.h> #include <libempathy/empathy-account-manager.h> +#include <libempathy/empathy-connection-managers.h> #include <libempathy-gtk/empathy-ui-utils.h> -#include <libempathy-gtk/empathy-profile-chooser.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-conf.h> +#include <libempathy-gtk/empathy-images.h> #include "empathy-accounts-dialog.h" #include "empathy-import-dialog.h" +#include "empathy-import-utils.h" #define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT #include <libempathy/empathy-debug.h> @@ -52,1125 +57,1414 @@ /* Flashing delay for icons (milliseconds). */ #define FLASH_TIMEOUT 500 +#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyAccountsDialog) +G_DEFINE_TYPE (EmpathyAccountsDialog, empathy_accounts_dialog, G_TYPE_OBJECT); + +static EmpathyAccountsDialog *dialog_singleton = NULL; + typedef struct { - GtkWidget *window; + GtkWidget *window; + + GtkWidget *alignment_settings; + + GtkWidget *vbox_details; + GtkWidget *frame_no_protocol; - GtkWidget *alignment_settings; + GtkWidget *treeview; - GtkWidget *vbox_details; - GtkWidget *frame_no_profile; + GtkWidget *button_add; - GtkWidget *treeview; + GtkWidget *frame_new_account; + GtkWidget *combobox_protocol; + GtkWidget *hbox_type; + GtkWidget *button_create; + GtkWidget *button_back; + GtkWidget *radiobutton_reuse; + GtkWidget *radiobutton_register; - GtkWidget *button_add; - GtkWidget *button_remove; - GtkWidget *button_import; + GtkWidget *image_type; + GtkWidget *label_name; + GtkWidget *label_type; + GtkWidget *settings_widget; - GtkWidget *frame_new_account; - GtkWidget *combobox_profile; - GtkWidget *hbox_type; - GtkWidget *button_create; - GtkWidget *button_back; - GtkWidget *radiobutton_reuse; - GtkWidget *radiobutton_register; + gboolean connecting_show; + guint connecting_id; - GtkWidget *image_type; - GtkWidget *label_name; - GtkWidget *label_type; - GtkWidget *settings_widget; + gulong settings_ready_id; + EmpathyAccountSettings *settings_ready; - gboolean connecting_show; - guint connecting_id; + EmpathyAccountManager *account_manager; + EmpathyConnectionManagers *cms; - EmpathyAccountManager *account_manager; - MissionControl *mc; -} EmpathyAccountsDialog; + GtkWindow *parent_window; + EmpathyAccount *initial_selection; +} EmpathyAccountsDialogPriv; enum { - COL_ENABLED, - COL_NAME, - COL_STATUS, - COL_ACCOUNT_POINTER, - COL_COUNT + COL_NAME, + COL_STATUS, + COL_ACCOUNT_POINTER, + COL_ACCOUNT_SETTINGS_POINTER, + COL_COUNT }; -static void accounts_dialog_update_account (EmpathyAccountsDialog *dialog, - EmpathyAccount *account); -static void accounts_dialog_model_setup (EmpathyAccountsDialog *dialog); -static void accounts_dialog_model_add_columns (EmpathyAccountsDialog *dialog); -static void accounts_dialog_name_editing_started_cb (GtkCellRenderer *renderer, - GtkCellEditable *editable, - gchar *path, - EmpathyAccountsDialog *dialog); -static void accounts_dialog_model_select_first (EmpathyAccountsDialog *dialog); -static void accounts_dialog_model_pixbuf_data_func (GtkTreeViewColumn *tree_column, - GtkCellRenderer *cell, - GtkTreeModel *model, - GtkTreeIter *iter, - EmpathyAccountsDialog *dialog); -static EmpathyAccount *accounts_dialog_model_get_selected (EmpathyAccountsDialog *dialog); -static void accounts_dialog_model_set_selected (EmpathyAccountsDialog *dialog, - EmpathyAccount *account); -static gboolean accounts_dialog_model_remove_selected (EmpathyAccountsDialog *dialog); -static void accounts_dialog_model_selection_changed (GtkTreeSelection *selection, - EmpathyAccountsDialog *dialog); -static void accounts_dialog_add_or_update_account (EmpathyAccountsDialog *dialog, - EmpathyAccount *account); -static void accounts_dialog_account_added_cb (EmpathyAccountManager *manager, - EmpathyAccount *account, - EmpathyAccountsDialog *dialog); -static void accounts_dialog_account_removed_cb (EmpathyAccountManager *manager, - EmpathyAccount *account, - EmpathyAccountsDialog *dialog); -static gboolean accounts_dialog_row_changed_foreach (GtkTreeModel *model, - GtkTreePath *path, - GtkTreeIter *iter, - gpointer user_data); -static gboolean accounts_dialog_flash_connecting_cb (EmpathyAccountsDialog *dialog); -static void accounts_dialog_connection_changed_cb (EmpathyAccountManager *manager, - EmpathyAccount *account, - TpConnectionStatusReason reason, - TpConnectionStatus current, - TpConnectionStatus previous, - EmpathyAccountsDialog *dialog); -static void accounts_dialog_button_create_clicked_cb (GtkWidget *button, - EmpathyAccountsDialog *dialog); -static void accounts_dialog_button_back_clicked_cb (GtkWidget *button, - EmpathyAccountsDialog *dialog); -static void accounts_dialog_button_add_clicked_cb (GtkWidget *button, - EmpathyAccountsDialog *dialog); -static void accounts_dialog_button_help_clicked_cb (GtkWidget *button, - EmpathyAccountsDialog *dialog); -static void accounts_dialog_button_remove_clicked_cb (GtkWidget *button, - EmpathyAccountsDialog *dialog); -static void accounts_dialog_button_import_clicked_cb (GtkWidget *button, - EmpathyAccountsDialog *dialog); -static void accounts_dialog_response_cb (GtkWidget *widget, - gint response, - EmpathyAccountsDialog *dialog); -static void accounts_dialog_destroy_cb (GtkWidget *widget, - EmpathyAccountsDialog *dialog); +enum { + PROP_PARENT = 1 +}; + +static EmpathyAccountSettings * accounts_dialog_model_get_selected_settings ( + EmpathyAccountsDialog *dialog); + +static void accounts_dialog_model_select_first (EmpathyAccountsDialog *dialog); + +static void accounts_dialog_update (EmpathyAccountsDialog *dialog, + EmpathyAccountSettings *settings); + +static void accounts_dialog_update_settings (EmpathyAccountsDialog *dialog, + EmpathyAccountSettings *settings); static void accounts_dialog_update_name_label (EmpathyAccountsDialog *dialog, - EmpathyAccount *account) + const gchar *display_name) { - gchar *text; + gchar *text; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); - text = g_markup_printf_escaped ("<big><b>%s</b></big>", - empathy_account_get_display_name (account)); - gtk_label_set_markup (GTK_LABEL (dialog->label_name), text); + text = g_markup_printf_escaped ("<big><b>%s</b></big>", display_name); + gtk_label_set_markup (GTK_LABEL (priv->label_name), text); - g_free (text); + g_free (text); } static void -accounts_dialog_update_account (EmpathyAccountsDialog *dialog, - EmpathyAccount *account) +empathy_account_dialog_widget_cancelled_cb (EmpathyAccountWidget *widget_object, + EmpathyAccountsDialog *dialog) { - McProfile *profile; - const gchar *config_ui; - - if (!account) { - GtkTreeView *view; - GtkTreeModel *model; - - view = GTK_TREE_VIEW (dialog->treeview); - model = gtk_tree_view_get_model (view); - - if (gtk_tree_model_iter_n_children (model, NULL) > 0) { - /* We have configured accounts, select the first one */ - accounts_dialog_model_select_first (dialog); - return; - } - if (empathy_profile_chooser_n_profiles ( - EMPATHY_PROFILE_CHOOSER (dialog->combobox_profile)) > 0) { - /* We have no account configured but we have some - * profiles instsalled. The user obviously wants to add - * an account. Click on the Add button for him. */ - accounts_dialog_button_add_clicked_cb (dialog->button_add, - dialog); - return; - } - - /* No account and no profile, warn the user */ - gtk_widget_hide (dialog->vbox_details); - gtk_widget_hide (dialog->frame_new_account); - gtk_widget_show (dialog->frame_no_profile); - gtk_widget_set_sensitive (dialog->button_add, FALSE); - gtk_widget_set_sensitive (dialog->button_remove, FALSE); - return; - } - - /* We have an account selected, destroy old settings and create a new - * one for the account selected */ - gtk_widget_hide (dialog->frame_new_account); - gtk_widget_hide (dialog->frame_no_profile); - gtk_widget_show (dialog->vbox_details); - gtk_widget_set_sensitive (dialog->button_add, TRUE); - gtk_widget_set_sensitive (dialog->button_remove, TRUE); - - if (dialog->settings_widget) { - gtk_widget_destroy (dialog->settings_widget); - dialog->settings_widget = NULL; - } - - profile = empathy_account_get_profile (account); - config_ui = mc_profile_get_configuration_ui (profile); - if (!tp_strdiff (config_ui, "jabber")) { - dialog->settings_widget = - empathy_account_widget_jabber_new (account); - } - else if (!tp_strdiff (config_ui, "msn")) { - dialog ->settings_widget = - empathy_account_widget_msn_new (account); - } - else if (!tp_strdiff (config_ui, "local-xmpp")) { - dialog->settings_widget = - empathy_account_widget_salut_new (account); - } - else if (!tp_strdiff (config_ui, "irc")) { - dialog->settings_widget = - empathy_account_widget_irc_new (account); - } - else if (!tp_strdiff (config_ui, "icq")) { - dialog->settings_widget = - empathy_account_widget_icq_new (account); - } - else if (!tp_strdiff (config_ui, "aim")) { - dialog->settings_widget = - empathy_account_widget_aim_new (account); - } - else if (!tp_strdiff (config_ui, "yahoo")) { - dialog->settings_widget = - empathy_account_widget_yahoo_new (account); - } - else if (!tp_strdiff (config_ui, "sofiasip")) { - dialog->settings_widget = - empathy_account_widget_sip_new (account); - } - else if (!tp_strdiff (config_ui, "groupwise")) { - dialog->settings_widget = - empathy_account_widget_groupwise_new (account); - } - else { - dialog->settings_widget = - empathy_account_widget_generic_new (account); - } - - gtk_container_add (GTK_CONTAINER (dialog->alignment_settings), - dialog->settings_widget); - gtk_widget_show (dialog->settings_widget); - - - gtk_image_set_from_icon_name (GTK_IMAGE (dialog->image_type), - mc_profile_get_icon_name (profile), - GTK_ICON_SIZE_DIALOG); - gtk_widget_set_tooltip_text (dialog->image_type, - mc_profile_get_display_name (profile)); - - accounts_dialog_update_name_label (dialog, account); - - g_object_unref (profile); + GtkTreeView *view; + GtkTreeModel *model; + GtkTreeSelection *selection; + GtkTreeIter iter; + EmpathyAccountSettings *settings; + EmpathyAccount *account; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + view = GTK_TREE_VIEW (priv->treeview); + selection = gtk_tree_view_get_selection (view); + + if (!gtk_tree_selection_get_selected (selection, &model, &iter)) + return; + + gtk_tree_model_get (model, &iter, + COL_ACCOUNT_SETTINGS_POINTER, &settings, + COL_ACCOUNT_POINTER, &account, -1); + + empathy_account_settings_discard_changes (settings); + + if (account == NULL) + { + /* We were creating an account. We remove the selected row */ + gtk_list_store_remove (GTK_LIST_STORE (model), &iter); + } + else + { + /* We were modifying an account. We discard the changes by reloading the + * settings and the UI. */ + accounts_dialog_update_settings (dialog, settings); + g_object_unref (account); + } + + if (settings != NULL) + g_object_unref (settings); } static void -accounts_dialog_model_setup (EmpathyAccountsDialog *dialog) +empathy_account_dialog_account_created_cb (EmpathyAccountWidget *widget_object, + EmpathyAccountsDialog *dialog) { - GtkListStore *store; - GtkTreeSelection *selection; + EmpathyAccountSettings *settings = + accounts_dialog_model_get_selected_settings (dialog); + accounts_dialog_update_settings (dialog, settings); - store = gtk_list_store_new (COL_COUNT, - G_TYPE_BOOLEAN, /* enabled */ - G_TYPE_STRING, /* name */ - G_TYPE_UINT, /* status */ - EMPATHY_TYPE_ACCOUNT); /* account */ + if (settings) + g_object_unref (settings); +} - gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->treeview), - GTK_TREE_MODEL (store)); +static GtkWidget * +get_account_setup_widget (EmpathyAccountSettings *settings, + EmpathyAccountWidget **widget_object) +{ + const gchar *proto = empathy_account_settings_get_protocol (settings); + EmpathyConnectionManagers *cm = + empathy_connection_managers_dup_singleton (); + GList *cms = empathy_connection_managers_get_cms (cm); + GList *l; + + for (l = cms; l; l = l->next) + { + TpConnectionManager *tp_cm = l->data; + if (tp_connection_manager_has_protocol (tp_cm, proto)) + { + g_object_unref (cm); + *widget_object = empathy_account_widget_new_for_protocol (proto, + settings, FALSE); + return empathy_account_widget_get_widget (*widget_object); + } + } + + g_object_unref (cm); + *widget_object = empathy_account_widget_new_for_protocol ("generic", settings, + FALSE); + return empathy_account_widget_get_widget (*widget_object); +} + +static void +account_dialog_create_settings_widget (EmpathyAccountsDialog *dialog, + EmpathyAccountSettings *settings) +{ + EmpathyAccountWidget *widget_object = NULL; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + gchar *icon_name; - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->treeview)); - gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); + priv->settings_widget = get_account_setup_widget (settings, &widget_object); + g_signal_connect (widget_object, "account-created", + G_CALLBACK (empathy_account_dialog_account_created_cb), dialog); + g_signal_connect (widget_object, "cancelled", + G_CALLBACK (empathy_account_dialog_widget_cancelled_cb), dialog); - g_signal_connect (selection, "changed", - G_CALLBACK (accounts_dialog_model_selection_changed), - dialog); + gtk_container_add (GTK_CONTAINER (priv->alignment_settings), + priv->settings_widget); + gtk_widget_show (priv->settings_widget); - gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), - COL_NAME, GTK_SORT_ASCENDING); + icon_name = empathy_account_settings_get_icon_name (settings); - accounts_dialog_model_add_columns (dialog); + gtk_image_set_from_icon_name (GTK_IMAGE (priv->image_type), + icon_name, GTK_ICON_SIZE_DIALOG); + gtk_widget_set_tooltip_text (priv->image_type, + empathy_account_settings_get_protocol (settings)); - g_object_unref (store); + accounts_dialog_update_name_label (dialog, + empathy_account_settings_get_display_name (settings)); } static void -accounts_dialog_name_edited_cb (GtkCellRendererText *renderer, - gchar *path, - gchar *new_text, - EmpathyAccountsDialog *dialog) +account_dialog_settings_ready_cb (EmpathyAccountSettings *settings, + GParamSpec *spec, + EmpathyAccountsDialog *dialog) { - EmpathyAccount *account; - GtkTreeModel *model; - GtkTreePath *treepath; - GtkTreeIter iter; - - if (empathy_account_manager_get_connecting_accounts (dialog->account_manager) > 0) { - dialog->connecting_id = g_timeout_add (FLASH_TIMEOUT, - (GSourceFunc) accounts_dialog_flash_connecting_cb, - dialog); - } - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview)); - treepath = gtk_tree_path_new_from_string (path); - gtk_tree_model_get_iter (model, &iter, treepath); - gtk_tree_model_get (model, &iter, - COL_ACCOUNT_POINTER, &account, - -1); - gtk_list_store_set (GTK_LIST_STORE (model), &iter, - COL_NAME, new_text, - -1); - gtk_tree_path_free (treepath); - - empathy_account_set_display_name (account, new_text); - g_object_unref (account); + if (empathy_account_settings_is_ready (settings)) + account_dialog_create_settings_widget (dialog, settings); } static void -accounts_dialog_enable_toggled_cb (GtkCellRendererToggle *cell_renderer, - gchar *path, - EmpathyAccountsDialog *dialog) +accounts_dialog_model_select_first (EmpathyAccountsDialog *dialog) { - EmpathyAccount *account; - GtkTreeModel *model; - GtkTreePath *treepath; - GtkTreeIter iter; - gboolean enabled; - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview)); - treepath = gtk_tree_path_new_from_string (path); - gtk_tree_model_get_iter (model, &iter, treepath); - gtk_tree_model_get (model, &iter, - COL_ACCOUNT_POINTER, &account, - -1); - gtk_tree_path_free (treepath); - - enabled = empathy_account_is_enabled (account); - empathy_account_set_enabled (account, !enabled); - - DEBUG ("%s account %s", enabled ? "Disabled" : "Enable", - empathy_account_get_display_name (account)); - - g_object_unref (account); + GtkTreeView *view; + GtkTreeModel *model; + GtkTreeSelection *selection; + GtkTreeIter iter; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + /* select first */ + view = GTK_TREE_VIEW (priv->treeview); + model = gtk_tree_view_get_model (view); + + if (gtk_tree_model_get_iter_first (model, &iter)) + { + selection = gtk_tree_view_get_selection (view); + gtk_tree_selection_select_iter (selection, &iter); + } + else + { + accounts_dialog_update_settings (dialog, NULL); + } } static void -accounts_dialog_name_editing_started_cb (GtkCellRenderer *renderer, - GtkCellEditable *editable, - gchar *path, - EmpathyAccountsDialog *dialog) +accounts_dialog_protocol_changed_cb (GtkWidget *widget, + EmpathyAccountsDialog *dialog) { - if (dialog->connecting_id) { - g_source_remove (dialog->connecting_id); - } - DEBUG ("Editing account name started; stopping flashing"); + TpConnectionManager *cm; + TpConnectionManagerProtocol *proto; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + cm = empathy_protocol_chooser_dup_selected ( + EMPATHY_PROTOCOL_CHOOSER (priv->combobox_protocol), &proto); + + if (tp_connection_manager_protocol_can_register (proto)) + { + gtk_widget_show (priv->radiobutton_register); + gtk_widget_show (priv->radiobutton_reuse); + } + else + { + gtk_widget_hide (priv->radiobutton_register); + gtk_widget_hide (priv->radiobutton_reuse); + } + g_object_unref (cm); } static void -accounts_dialog_model_add_columns (EmpathyAccountsDialog *dialog) +accounts_dialog_button_add_clicked_cb (GtkWidget *button, + EmpathyAccountsDialog *dialog) { - GtkTreeView *view; - GtkTreeViewColumn *column; - GtkCellRenderer *cell; - - view = GTK_TREE_VIEW (dialog->treeview); - gtk_tree_view_set_headers_visible (view, TRUE); - - /* Enabled column */ - cell = gtk_cell_renderer_toggle_new (); - gtk_tree_view_insert_column_with_attributes (view, -1, - _("Enabled"), - cell, - "active", COL_ENABLED, - NULL); - g_signal_connect (cell, "toggled", - G_CALLBACK (accounts_dialog_enable_toggled_cb), - dialog); - - /* Account column */ - column = gtk_tree_view_column_new (); - gtk_tree_view_column_set_title (column, _("Accounts")); - gtk_tree_view_column_set_expand (column, TRUE); - gtk_tree_view_append_column (view, column); - - /* Icon renderer */ - cell = gtk_cell_renderer_pixbuf_new (); - gtk_tree_view_column_pack_start (column, cell, FALSE); - gtk_tree_view_column_set_cell_data_func (column, cell, - (GtkTreeCellDataFunc) - accounts_dialog_model_pixbuf_data_func, - dialog, - NULL); - - /* Name renderer */ - cell = gtk_cell_renderer_text_new (); - g_object_set (cell, - "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", - G_CALLBACK (accounts_dialog_name_edited_cb), - dialog); - g_signal_connect (cell, "editing-started", - G_CALLBACK (accounts_dialog_name_editing_started_cb), - dialog); + GtkTreeView *view; + GtkTreeModel *model; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + view = GTK_TREE_VIEW (priv->treeview); + model = gtk_tree_view_get_model (view); + + gtk_widget_set_sensitive (priv->button_add, FALSE); + gtk_widget_hide (priv->vbox_details); + gtk_widget_hide (priv->frame_no_protocol); + gtk_widget_show (priv->frame_new_account); + + /* If we have no account, no need of a back button */ + if (gtk_tree_model_iter_n_children (model, NULL) > 0) + gtk_widget_show (priv->button_back); + else + gtk_widget_hide (priv->button_back); + + accounts_dialog_protocol_changed_cb (priv->radiobutton_register, dialog); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->radiobutton_reuse), + TRUE); + gtk_combo_box_set_active (GTK_COMBO_BOX (priv->combobox_protocol), 0); + gtk_widget_grab_focus (priv->combobox_protocol); } static void -accounts_dialog_model_select_first (EmpathyAccountsDialog *dialog) +accounts_dialog_update_settings (EmpathyAccountsDialog *dialog, + EmpathyAccountSettings *settings) { - GtkTreeView *view; - GtkTreeModel *model; - GtkTreeSelection *selection; - GtkTreeIter iter; - - /* select first */ - view = GTK_TREE_VIEW (dialog->treeview); - model = gtk_tree_view_get_model (view); - - if (gtk_tree_model_get_iter_first (model, &iter)) { - selection = gtk_tree_view_get_selection (view); - gtk_tree_selection_select_iter (selection, &iter); - } else { - accounts_dialog_update_account (dialog, NULL); - } + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + if (priv->settings_ready != NULL) + { + g_signal_handler_disconnect (priv->settings_ready, + priv->settings_ready_id); + priv->settings_ready = NULL; + priv->settings_ready_id = 0; + } + + if (!settings) + { + GtkTreeView *view; + GtkTreeModel *model; + + view = GTK_TREE_VIEW (priv->treeview); + model = gtk_tree_view_get_model (view); + + if (gtk_tree_model_iter_n_children (model, NULL) > 0) + { + /* We have configured accounts, select the first one */ + accounts_dialog_model_select_first (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 */ + gtk_widget_hide (priv->vbox_details); + gtk_widget_hide (priv->frame_new_account); + gtk_widget_show (priv->frame_no_protocol); + gtk_widget_set_sensitive (priv->button_add, FALSE); + return; + } + + /* We have an account selected, destroy old settings and create a new + * one for the account selected */ + gtk_widget_hide (priv->frame_new_account); + gtk_widget_hide (priv->frame_no_protocol); + gtk_widget_show (priv->vbox_details); + gtk_widget_set_sensitive (priv->button_add, TRUE); + + if (priv->settings_widget) + { + gtk_widget_destroy (priv->settings_widget); + priv->settings_widget = NULL; + } + + if (empathy_account_settings_is_ready (settings)) + { + account_dialog_create_settings_widget (dialog, settings); + } + else + { + priv->settings_ready = settings; + priv->settings_ready_id = + g_signal_connect (settings, "notify::ready", + G_CALLBACK (account_dialog_settings_ready_cb), dialog); + } + } static void -accounts_dialog_model_pixbuf_data_func (GtkTreeViewColumn *tree_column, - GtkCellRenderer *cell, - GtkTreeModel *model, - GtkTreeIter *iter, - EmpathyAccountsDialog *dialog) +accounts_dialog_name_editing_started_cb (GtkCellRenderer *renderer, + GtkCellEditable *editable, + gchar *path, + EmpathyAccountsDialog *dialog) { - EmpathyAccount *account; - const gchar *icon_name; - GdkPixbuf *pixbuf; - TpConnectionStatus status; - - gtk_tree_model_get (model, iter, - COL_STATUS, &status, - COL_ACCOUNT_POINTER, &account, - -1); - - icon_name = empathy_icon_name_from_account (account); - pixbuf = empathy_pixbuf_from_icon_name (icon_name, GTK_ICON_SIZE_BUTTON); - - if (pixbuf) { - if (status == TP_CONNECTION_STATUS_DISCONNECTED || - (status == TP_CONNECTION_STATUS_CONNECTING && - !dialog->connecting_show)) { - GdkPixbuf *modded_pixbuf; - - modded_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, - TRUE, - 8, - gdk_pixbuf_get_width (pixbuf), - gdk_pixbuf_get_height (pixbuf)); - - gdk_pixbuf_saturate_and_pixelate (pixbuf, - modded_pixbuf, - 1.0, - TRUE); - g_object_unref (pixbuf); - pixbuf = modded_pixbuf; - } - } - - g_object_set (cell, - "visible", TRUE, - "pixbuf", pixbuf, - NULL); - - g_object_unref (account); - if (pixbuf) { - g_object_unref (pixbuf); - } + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + if (priv->connecting_id) + g_source_remove (priv->connecting_id); + + DEBUG ("Editing account name started; stopping flashing"); +} + +static void +accounts_dialog_model_pixbuf_data_func (GtkTreeViewColumn *tree_column, + GtkCellRenderer *cell, + GtkTreeModel *model, + GtkTreeIter *iter, + EmpathyAccountsDialog *dialog) +{ + EmpathyAccountSettings *settings; + gchar *icon_name; + GdkPixbuf *pixbuf; + TpConnectionStatus status; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + gtk_tree_model_get (model, iter, + COL_STATUS, &status, + COL_ACCOUNT_SETTINGS_POINTER, &settings, + -1); + + icon_name = empathy_account_settings_get_icon_name (settings); + pixbuf = empathy_pixbuf_from_icon_name (icon_name, GTK_ICON_SIZE_BUTTON); + + if (pixbuf) + { + if (status == TP_CONNECTION_STATUS_DISCONNECTED || + (status == TP_CONNECTION_STATUS_CONNECTING && + !priv->connecting_show)) + { + GdkPixbuf *modded_pixbuf; + + modded_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, + TRUE, + 8, + gdk_pixbuf_get_width (pixbuf), + gdk_pixbuf_get_height (pixbuf)); + + gdk_pixbuf_saturate_and_pixelate (pixbuf, + modded_pixbuf, + 1.0, + TRUE); + g_object_unref (pixbuf); + pixbuf = modded_pixbuf; + } + } + + g_object_set (cell, + "visible", TRUE, + "pixbuf", pixbuf, + NULL); + + g_object_unref (settings); + + if (pixbuf) + g_object_unref (pixbuf); } static gboolean -accounts_dialog_get_account_iter (EmpathyAccountsDialog *dialog, - EmpathyAccount *account, - GtkTreeIter *iter) +accounts_dialog_row_changed_foreach (GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + gpointer user_data) { - GtkTreeView *view; - GtkTreeSelection *selection; - GtkTreeModel *model; - gboolean ok; - - /* Update the status in the model */ - view = GTK_TREE_VIEW (dialog->treeview); - selection = gtk_tree_view_get_selection (view); - 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)) { - EmpathyAccount *this_account; - gboolean equal; - - gtk_tree_model_get (model, iter, - COL_ACCOUNT_POINTER, &this_account, - -1); - - equal = empathy_account_equal (this_account, account); - g_object_unref (this_account); - - if (equal) { - return TRUE; - } - } - - return FALSE; + gtk_tree_model_row_changed (model, path, iter); + + return FALSE; } -static EmpathyAccount * -accounts_dialog_model_get_selected (EmpathyAccountsDialog *dialog) +static gboolean +accounts_dialog_flash_connecting_cb (EmpathyAccountsDialog *dialog) { - GtkTreeView *view; - GtkTreeModel *model; - GtkTreeSelection *selection; - GtkTreeIter iter; - EmpathyAccount *account; + GtkTreeView *view; + GtkTreeModel *model; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); - view = GTK_TREE_VIEW (dialog->treeview); - selection = gtk_tree_view_get_selection (view); + priv->connecting_show = !priv->connecting_show; - if (!gtk_tree_selection_get_selected (selection, &model, &iter)) { - return NULL; - } + view = GTK_TREE_VIEW (priv->treeview); + model = gtk_tree_view_get_model (view); - gtk_tree_model_get (model, &iter, COL_ACCOUNT_POINTER, &account, -1); + gtk_tree_model_foreach (model, accounts_dialog_row_changed_foreach, NULL); - return account; + return TRUE; } static void -accounts_dialog_model_set_selected (EmpathyAccountsDialog *dialog, - EmpathyAccount *account) +accounts_dialog_name_edited_cb (GtkCellRendererText *renderer, + gchar *path, + gchar *new_text, + EmpathyAccountsDialog *dialog) +{ + EmpathyAccountSettings *settings; + GtkTreeModel *model; + GtkTreePath *treepath; + GtkTreeIter iter; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + if (empathy_account_manager_get_connecting_accounts + (priv->account_manager) > 0) + { + priv->connecting_id = g_timeout_add (FLASH_TIMEOUT, + (GSourceFunc) accounts_dialog_flash_connecting_cb, + dialog); + } + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview)); + treepath = gtk_tree_path_new_from_string (path); + gtk_tree_model_get_iter (model, &iter, treepath); + gtk_tree_model_get (model, &iter, + COL_ACCOUNT_SETTINGS_POINTER, &settings, + -1); + gtk_list_store_set (GTK_LIST_STORE (model), &iter, + COL_NAME, new_text, + -1); + gtk_tree_path_free (treepath); + + empathy_account_settings_set_display_name_async (settings, new_text, + NULL, NULL); + g_object_set (settings, "display-name-overridden", TRUE, NULL); + g_object_unref (settings); +} + +static void +accounts_dialog_delete_account_response_cb (GtkDialog *message_dialog, + gint response_id, + gpointer user_data) { - GtkTreeSelection *selection; - GtkTreeIter iter; + EmpathyAccount *account; + GtkTreeModel *model; + GtkTreeIter iter; + GtkTreeSelection *selection; + EmpathyAccountsDialog *account_dialog = EMPATHY_ACCOUNTS_DIALOG (user_data); + EmpathyAccountsDialogPriv *priv = GET_PRIV (account_dialog); + + if (response_id == GTK_RESPONSE_YES) + { + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview)); + + if (!gtk_tree_selection_get_selected (selection, &model, &iter)) + return; - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->treeview)); - if (accounts_dialog_get_account_iter (dialog, account, &iter)) { - gtk_tree_selection_select_iter (selection, &iter); - } + gtk_tree_model_get (model, &iter, COL_ACCOUNT_POINTER, &account, -1); + + if (account != NULL) + { + empathy_account_remove_async (account, NULL, NULL); + g_object_unref (account); + } + + gtk_list_store_remove (GTK_LIST_STORE (model), &iter); + accounts_dialog_model_select_first (account_dialog); + } + + gtk_widget_destroy (GTK_WIDGET (message_dialog)); } -static gboolean -accounts_dialog_model_remove_selected (EmpathyAccountsDialog *dialog) +static void +accounts_dialog_view_delete_activated_cb (EmpathyCellRendererActivatable *cell, + const gchar *path_string, + EmpathyAccountsDialog *dialog) +{ + EmpathyAccount *account; + GtkTreeModel *model; + GtkTreeIter iter; + GtkWidget *message_dialog; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview)); + + if (!gtk_tree_model_get_iter_from_string (model, &iter, path_string)) + return; + + gtk_tree_model_get (model, &iter, COL_ACCOUNT_POINTER, &account, -1); + + if (account == NULL || !empathy_account_is_valid (account)) + { + gtk_list_store_remove (GTK_LIST_STORE (model), &iter); + accounts_dialog_model_select_first (dialog); + return; + } + + message_dialog = gtk_message_dialog_new + (GTK_WINDOW (priv->window), + GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_NONE, + _("You are about to remove your %s account!\n" + "Are you sure you want to proceed?"), + empathy_account_get_display_name (account)); + + gtk_message_dialog_format_secondary_text + (GTK_MESSAGE_DIALOG (message_dialog), + _("Any associated conversations and chat rooms will NOT be " + "removed if you decide to proceed.\n" + "\n" + "Should you decide to add the account back at a later time, " + "they will still be available.")); + + gtk_dialog_add_button (GTK_DIALOG (message_dialog), + GTK_STOCK_CANCEL, + GTK_RESPONSE_NO); + gtk_dialog_add_button (GTK_DIALOG (message_dialog), + GTK_STOCK_REMOVE, + GTK_RESPONSE_YES); + + g_signal_connect (message_dialog, "response", + G_CALLBACK (accounts_dialog_delete_account_response_cb), dialog); + + gtk_widget_show (message_dialog); + + if (account != NULL) + g_object_unref (account); +} + +static void +accounts_dialog_model_add_columns (EmpathyAccountsDialog *dialog) +{ + GtkTreeView *view; + GtkTreeViewColumn *column; + GtkCellRenderer *cell; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + view = GTK_TREE_VIEW (priv->treeview); + gtk_tree_view_set_headers_visible (view, FALSE); + + /* Account column */ + column = gtk_tree_view_column_new (); + gtk_tree_view_column_set_expand (column, TRUE); + gtk_tree_view_append_column (view, column); + + /* Icon renderer */ + cell = gtk_cell_renderer_pixbuf_new (); + gtk_tree_view_column_pack_start (column, cell, FALSE); + gtk_tree_view_column_set_cell_data_func (column, cell, + (GtkTreeCellDataFunc) + accounts_dialog_model_pixbuf_data_func, + dialog, + NULL); + + /* Name renderer */ + cell = gtk_cell_renderer_text_new (); + g_object_set (cell, + "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", + G_CALLBACK (accounts_dialog_name_edited_cb), + dialog); + g_signal_connect (cell, "editing-started", + G_CALLBACK (accounts_dialog_name_editing_started_cb), + dialog); + + /* 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, + NULL); + + g_signal_connect (cell, "path-activated", + G_CALLBACK (accounts_dialog_view_delete_activated_cb), + dialog); +} + +static EmpathyAccountSettings * +accounts_dialog_model_get_selected_settings (EmpathyAccountsDialog *dialog) { - GtkTreeView *view; - GtkTreeModel *model; - GtkTreeSelection *selection; - GtkTreeIter iter; + GtkTreeView *view; + GtkTreeModel *model; + GtkTreeSelection *selection; + GtkTreeIter iter; + EmpathyAccountSettings *settings; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); - view = GTK_TREE_VIEW (dialog->treeview); - selection = gtk_tree_view_get_selection (view); + view = GTK_TREE_VIEW (priv->treeview); + selection = gtk_tree_view_get_selection (view); - if (!gtk_tree_selection_get_selected (selection, &model, &iter)) { - return FALSE; - } + if (!gtk_tree_selection_get_selected (selection, &model, &iter)) + return NULL; - return gtk_list_store_remove (GTK_LIST_STORE (model), &iter); + gtk_tree_model_get (model, &iter, + COL_ACCOUNT_SETTINGS_POINTER, &settings, -1); + + return settings; } static void -accounts_dialog_model_selection_changed (GtkTreeSelection *selection, - EmpathyAccountsDialog *dialog) +accounts_dialog_model_selection_changed (GtkTreeSelection *selection, + EmpathyAccountsDialog *dialog) { - EmpathyAccount *account; - GtkTreeModel *model; - GtkTreeIter iter; - gboolean is_selection; + EmpathyAccountSettings *settings; + GtkTreeModel *model; + GtkTreeIter iter; + gboolean is_selection; + + is_selection = gtk_tree_selection_get_selected (selection, &model, &iter); + + settings = accounts_dialog_model_get_selected_settings (dialog); - is_selection = gtk_tree_selection_get_selected (selection, &model, &iter); + if (settings != NULL) + empathy_account_settings_discard_changes (settings); - account = accounts_dialog_model_get_selected (dialog); - accounts_dialog_update_account (dialog, account); + accounts_dialog_update_settings (dialog, settings); - if (account) { - g_object_unref (account); - } + if (settings != NULL) + g_object_unref (settings); } static void -accounts_dialog_add_or_update_account (EmpathyAccountsDialog *dialog, - EmpathyAccount *account) +accounts_dialog_model_setup (EmpathyAccountsDialog *dialog) { - GtkTreeModel *model; - GtkTreeIter iter; - TpConnectionStatus status; - const gchar *name; - gboolean enabled; - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview)); - g_object_get (account, "status", &status, NULL); - name = empathy_account_get_display_name (account); - enabled = empathy_account_is_enabled (account); - - if (!accounts_dialog_get_account_iter (dialog, account, &iter)) { - DEBUG ("Adding new account"); - gtk_list_store_append (GTK_LIST_STORE (model), &iter); - } - - gtk_list_store_set (GTK_LIST_STORE (model), &iter, - COL_ENABLED, enabled, - COL_NAME, name, - COL_STATUS, status, - COL_ACCOUNT_POINTER, account, - -1); - - accounts_dialog_connection_changed_cb (dialog->account_manager, - account, - TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED, - status, - TP_CONNECTION_STATUS_DISCONNECTED, - dialog); + GtkListStore *store; + GtkTreeSelection *selection; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + store = gtk_list_store_new (COL_COUNT, + G_TYPE_STRING, /* name */ + G_TYPE_UINT, /* status */ + EMPATHY_TYPE_ACCOUNT, /* account */ + EMPATHY_TYPE_ACCOUNT_SETTINGS); /* settings */ + + gtk_tree_view_set_model (GTK_TREE_VIEW (priv->treeview), + GTK_TREE_MODEL (store)); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview)); + gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); + + g_signal_connect (selection, "changed", + G_CALLBACK (accounts_dialog_model_selection_changed), + dialog); + + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), + COL_NAME, GTK_SORT_ASCENDING); + + accounts_dialog_model_add_columns (dialog); + + g_object_unref (store); +} + +static gboolean +accounts_dialog_get_settings_iter (EmpathyAccountsDialog *dialog, + EmpathyAccountSettings *settings, + GtkTreeIter *iter) +{ + GtkTreeView *view; + GtkTreeSelection *selection; + GtkTreeModel *model; + gboolean ok; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + /* Update the status in the model */ + view = GTK_TREE_VIEW (priv->treeview); + selection = gtk_tree_view_get_selection (view); + 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_POINTER, &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, + EmpathyAccount *account, + GtkTreeIter *iter) +{ + GtkTreeView *view; + GtkTreeSelection *selection; + GtkTreeModel *model; + gboolean ok; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + /* Update the status in the model */ + view = GTK_TREE_VIEW (priv->treeview); + selection = gtk_tree_view_get_selection (view); + 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 *settings; + gboolean equal; + + gtk_tree_model_get (model, iter, + COL_ACCOUNT_SETTINGS_POINTER, &settings, + -1); + + equal = empathy_account_settings_has_account (settings, account); + g_object_unref (settings); + + if (equal) + return TRUE; + } + + return FALSE; +} + +static void +accounts_dialog_model_set_selected (EmpathyAccountsDialog *dialog, + EmpathyAccountSettings *settings) +{ + GtkTreeSelection *selection; + GtkTreeIter iter; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview)); + if (accounts_dialog_get_settings_iter (dialog, settings, &iter)) + gtk_tree_selection_select_iter (selection, &iter); +} +static void +accounts_dialog_add (EmpathyAccountsDialog *dialog, + EmpathyAccountSettings *settings) +{ + 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); + + gtk_list_store_set (GTK_LIST_STORE (model), &iter, + COL_NAME, name, + COL_STATUS, TP_CONNECTION_STATUS_DISCONNECTED, + COL_ACCOUNT_SETTINGS_POINTER, settings, + -1); +} + +static void +accounts_dialog_connection_changed_cb (EmpathyAccountManager *manager, + EmpathyAccount *account, + TpConnectionStatusReason reason, + TpConnectionStatus current, + TpConnectionStatus previous, + EmpathyAccountsDialog *dialog) +{ + GtkTreeModel *model; + GtkTreeIter iter; + gboolean found; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + /* Update the status in the model */ + model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview)); + + if (accounts_dialog_get_account_iter (dialog, account, &iter)) + { + GtkTreePath *path; + + gtk_list_store_set (GTK_LIST_STORE (model), &iter, + COL_STATUS, current, + -1); + + path = gtk_tree_model_get_path (model, &iter); + gtk_tree_model_row_changed (model, path, &iter); + gtk_tree_path_free (path); + } + + found = (empathy_account_manager_get_connecting_accounts (manager) > 0); + + if (!found && priv->connecting_id) + { + g_source_remove (priv->connecting_id); + priv->connecting_id = 0; + } + + if (found && !priv->connecting_id) + priv->connecting_id = g_timeout_add (FLASH_TIMEOUT, + (GSourceFunc) accounts_dialog_flash_connecting_cb, + dialog); +} + +static void +accounts_dialog_add_account (EmpathyAccountsDialog *dialog, + EmpathyAccount *account) +{ + EmpathyAccountSettings *settings; + GtkTreeModel *model; + GtkTreeIter iter; + TpConnectionStatus status; + const gchar *name; + gboolean enabled; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview)); + g_object_get (account, "connection-status", &status, NULL); + name = empathy_account_get_display_name (account); + enabled = empathy_account_is_enabled (account); + + if (!accounts_dialog_get_account_iter (dialog, account, &iter)) + gtk_list_store_append (GTK_LIST_STORE (model), &iter); + + settings = empathy_account_settings_new_for_account (account); + + gtk_list_store_set (GTK_LIST_STORE (model), &iter, + COL_NAME, name, + COL_STATUS, status, + COL_ACCOUNT_POINTER, account, + COL_ACCOUNT_SETTINGS_POINTER, settings, + -1); + + accounts_dialog_connection_changed_cb (priv->account_manager, + account, + TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED, + status, + TP_CONNECTION_STATUS_DISCONNECTED, + dialog); + + g_object_unref (settings); +} + +static void +accounts_dialog_update (EmpathyAccountsDialog *dialog, + EmpathyAccountSettings *settings) +{ + GtkTreeModel *model; + GtkTreeIter iter; + TpConnectionStatus status = TP_CONNECTION_STATUS_DISCONNECTED; + const gchar *name; + gboolean enabled = FALSE; + EmpathyAccount *account; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview)); + name = empathy_account_settings_get_display_name (settings); + + account = empathy_account_settings_get_account (settings); + if (account != NULL) + { + enabled = empathy_account_is_enabled (account); + g_object_get (account, "connection-status", &status, NULL); + } + + accounts_dialog_get_settings_iter (dialog, settings, &iter); + gtk_list_store_set (GTK_LIST_STORE (model), &iter, + COL_NAME, name, + COL_STATUS, status, + COL_ACCOUNT_POINTER, account, + COL_ACCOUNT_SETTINGS_POINTER, settings, + -1); } static void accounts_dialog_account_added_cb (EmpathyAccountManager *manager, - EmpathyAccount *account, - EmpathyAccountsDialog *dialog) + EmpathyAccount *account, + EmpathyAccountsDialog *dialog) { - const gchar *current_name; - gchar *account_param = NULL; - - accounts_dialog_add_or_update_account (dialog, account); - - /* Change the display name to "%s (%s)" % (protocol, account). - * - The protocol is the display name of the profile. - * - The account should be the normalized name of the EmpathyAccount but - * it's not set until first connection, so we get the "account" - * parameter for CM that have it. */ - current_name = empathy_account_get_display_name (account); - account_param = empathy_account_get_param_string (account, "account"); - if (!EMP_STR_EMPTY (account_param)) { - McProfile *profile; - const gchar *profile_name; - gchar *new_name; - - profile = empathy_account_get_profile (account); - profile_name = mc_profile_get_display_name (profile); - new_name = g_strdup_printf ("%s (%s)", profile_name, - account_param); - - DEBUG ("Setting new display name for account %s: '%s'", - empathy_account_get_unique_name (account), new_name); - - empathy_account_set_display_name (account, new_name); - g_free (new_name); - g_object_unref (profile); - } else { - /* FIXME: This CM has no account parameter, what can be done? */ - } - g_free (account_param); + accounts_dialog_add_account (dialog, account); } + static void accounts_dialog_account_removed_cb (EmpathyAccountManager *manager, - EmpathyAccount *account, - EmpathyAccountsDialog *dialog) + EmpathyAccount *account, + EmpathyAccountsDialog *dialog) { + GtkTreeIter iter; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); - accounts_dialog_model_set_selected (dialog, account); - accounts_dialog_model_remove_selected (dialog); + if (accounts_dialog_get_account_iter (dialog, account, &iter)) + gtk_list_store_remove (GTK_LIST_STORE ( + gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview))), &iter); } -static gboolean -accounts_dialog_row_changed_foreach (GtkTreeModel *model, - GtkTreePath *path, - GtkTreeIter *iter, - gpointer user_data) +static void +enable_or_disable_account (EmpathyAccountsDialog *dialog, + EmpathyAccount *account, + gboolean enabled) { - gtk_tree_model_row_changed (model, path, iter); + GtkTreeModel *model; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + /* Update the status in the model */ + model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview)); - return FALSE; + DEBUG ("Account %s is now %s", + empathy_account_get_display_name (account), + enabled ? "enabled" : "disabled"); } -static gboolean -accounts_dialog_flash_connecting_cb (EmpathyAccountsDialog *dialog) +static void +accounts_dialog_account_disabled_cb (EmpathyAccountManager *manager, + EmpathyAccount *account, + EmpathyAccountsDialog *dialog) { - GtkTreeView *view; - GtkTreeModel *model; + enable_or_disable_account (dialog, account, FALSE); +} - dialog->connecting_show = !dialog->connecting_show; +static void +accounts_dialog_account_enabled_cb (EmpathyAccountManager *manager, + EmpathyAccount *account, + EmpathyAccountsDialog *dialog) +{ + enable_or_disable_account (dialog, account, TRUE); +} - view = GTK_TREE_VIEW (dialog->treeview); - model = gtk_tree_view_get_model (view); +static void +accounts_dialog_account_changed_cb (EmpathyAccountManager *manager, + EmpathyAccount *account, + EmpathyAccountsDialog *dialog) +{ + EmpathyAccountSettings *settings, *selected_settings; + GtkTreeModel *model; + GtkTreeIter iter; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview)); + + if (!accounts_dialog_get_account_iter (dialog, account, &iter)) + return; + + gtk_tree_model_get (model, &iter, + COL_ACCOUNT_SETTINGS_POINTER, &settings, + -1); - gtk_tree_model_foreach (model, accounts_dialog_row_changed_foreach, NULL); + accounts_dialog_update (dialog, settings); + selected_settings = accounts_dialog_model_get_selected_settings (dialog); - return TRUE; + if (settings == selected_settings) + accounts_dialog_update_name_label (dialog, + empathy_account_settings_get_display_name (settings)); + + if (settings) + g_object_unref (settings); + + if (selected_settings) + g_object_unref (selected_settings); } static void -accounts_dialog_connection_changed_cb (EmpathyAccountManager *manager, - EmpathyAccount *account, - TpConnectionStatusReason reason, - TpConnectionStatus current, - TpConnectionStatus previous, - EmpathyAccountsDialog *dialog) +accounts_dialog_button_create_clicked_cb (GtkWidget *button, + EmpathyAccountsDialog *dialog) { - GtkTreeModel *model; - GtkTreeIter iter; - gboolean found; + EmpathyAccountSettings *settings; + gchar *str; + TpConnectionManager *cm; + TpConnectionManagerProtocol *proto; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); - /* Update the status in the model */ - model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview)); + cm = empathy_protocol_chooser_dup_selected ( + EMPATHY_PROTOCOL_CHOOSER (priv->combobox_protocol), &proto); - if (accounts_dialog_get_account_iter (dialog, account, &iter)) { - GtkTreePath *path; + /* Create account */ + /* To translator: %s is the protocol name */ + str = g_strdup_printf (_("New %s account"), proto->name); - gtk_list_store_set (GTK_LIST_STORE (model), &iter, - COL_STATUS, current, - -1); + settings = empathy_account_settings_new (cm->name, proto->name, str); - path = gtk_tree_model_get_path (model, &iter); - gtk_tree_model_row_changed (model, path, &iter); - gtk_tree_path_free (path); - } + g_free (str); - found = (empathy_account_manager_get_connecting_accounts (manager) > 0); + if (tp_connection_manager_protocol_can_register (proto)) + { + gboolean active; - if (!found && dialog->connecting_id) { - g_source_remove (dialog->connecting_id); - dialog->connecting_id = 0; - } + active = gtk_toggle_button_get_active + (GTK_TOGGLE_BUTTON (priv->radiobutton_register)); + if (active) + empathy_account_settings_set_boolean (settings, "register", TRUE); + } - if (found && !dialog->connecting_id) { - dialog->connecting_id = g_timeout_add (FLASH_TIMEOUT, - (GSourceFunc) accounts_dialog_flash_connecting_cb, - dialog); - } + accounts_dialog_add (dialog, settings); + accounts_dialog_model_set_selected (dialog, settings); + + g_object_unref (settings); + g_object_unref (cm); } static void -enable_or_disable_account (EmpathyAccountsDialog *dialog, - EmpathyAccount *account, - gboolean enabled) +accounts_dialog_button_back_clicked_cb (GtkWidget *button, + EmpathyAccountsDialog *dialog) { - GtkTreeModel *model; - GtkTreeIter iter; + EmpathyAccountSettings *settings; - /* Update the status in the model */ - model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview)); + settings = accounts_dialog_model_get_selected_settings (dialog); + accounts_dialog_update_settings (dialog, settings); - DEBUG ("Account %s is now %s", - empathy_account_get_display_name (account), - enabled ? "enabled" : "disabled"); - - if (accounts_dialog_get_account_iter (dialog, account, &iter)) { - gtk_list_store_set (GTK_LIST_STORE (model), &iter, - COL_ENABLED, enabled, - -1); - } + if (settings) + g_object_unref (settings); } static void -accounts_dialog_account_disabled_cb (EmpathyAccountManager *manager, - EmpathyAccount *account, - EmpathyAccountsDialog *dialog) +accounts_dialog_button_help_clicked_cb (GtkWidget *button, + EmpathyAccountsDialog *dialog) { - enable_or_disable_account (dialog, account, FALSE); + empathy_url_show (button, "ghelp:empathy?empathy-create-account"); } static void -accounts_dialog_account_enabled_cb (EmpathyAccountManager *manager, - EmpathyAccount *account, - EmpathyAccountsDialog *dialog) +accounts_dialog_response_cb (GtkWidget *widget, + gint response, + EmpathyAccountsDialog *dialog) { - enable_or_disable_account (dialog, account, TRUE); + if (response == GTK_RESPONSE_CLOSE) + gtk_widget_destroy (widget); } static void -accounts_dialog_account_changed_cb (EmpathyAccountManager *manager, - EmpathyAccount *account, - EmpathyAccountsDialog *dialog) +accounts_dialog_destroy_cb (GtkObject *obj, + EmpathyAccountsDialog *dialog) { - EmpathyAccount *selected_account; + DEBUG ("%p", obj); - accounts_dialog_add_or_update_account (dialog, account); - selected_account = accounts_dialog_model_get_selected (dialog); - if (empathy_account_equal (account, selected_account)) { - accounts_dialog_update_name_label (dialog, account); - } + g_object_unref (dialog); } static void -accounts_dialog_button_create_clicked_cb (GtkWidget *button, - EmpathyAccountsDialog *dialog) +accounts_dialog_set_selected_account (EmpathyAccountsDialog *dialog, + EmpathyAccount *account) { - McProfile *profile; - EmpathyAccount *account; - gchar *str; - McProfileCapabilityFlags cap; - - profile = empathy_profile_chooser_dup_selected ( - EMPATHY_PROFILE_CHOOSER (dialog->combobox_profile)); - - /* Create account */ - account = empathy_account_manager_create (dialog->account_manager, profile); - if (account == NULL) { - /* We can't display an error to the user as MC doesn't give us - * any clue about the reason of the failure... */ - g_object_unref (profile); - return; - } - - /* To translator: %s is the protocol name */ - str = g_strdup_printf (_("New %s account"), - mc_profile_get_display_name (profile)); - empathy_account_set_display_name (account, str); - g_free (str); - - cap = mc_profile_get_capabilities (profile); - if (cap & MC_PROFILE_CAPABILITY_REGISTRATION_UI) { - gboolean active; - - active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->radiobutton_register)); - if (active) { - empathy_account_set_param_boolean (account, "register", TRUE); - } - } - - accounts_dialog_add_or_update_account (dialog, account); - accounts_dialog_model_set_selected (dialog, account); - - g_object_unref (account); - g_object_unref (profile); + GtkTreeSelection *selection; + GtkTreeIter iter; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview)); + if (accounts_dialog_get_account_iter (dialog, account, &iter)) + gtk_tree_selection_select_iter (selection, &iter); } static void -accounts_dialog_button_back_clicked_cb (GtkWidget *button, - EmpathyAccountsDialog *dialog) +accounts_dialog_cms_ready_cb (EmpathyConnectionManagers *cms, + GParamSpec *pspec, + EmpathyAccountsDialog *dialog) { - EmpathyAccount *account; - - account = accounts_dialog_model_get_selected (dialog); - accounts_dialog_update_account (dialog, account); + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + if (empathy_connection_managers_is_ready (cms)) + { + accounts_dialog_update_settings (dialog, NULL); + + if (priv->initial_selection != NULL) + { + accounts_dialog_set_selected_account + (dialog, priv->initial_selection); + g_object_unref (priv->initial_selection); + priv->initial_selection = NULL; + } + } } static void -accounts_dialog_profile_changed_cb (GtkWidget *widget, - EmpathyAccountsDialog *dialog) +accounts_dialog_build_ui (EmpathyAccountsDialog *dialog) { - McProfile *profile; - McProfileCapabilityFlags cap; - - profile = empathy_profile_chooser_dup_selected ( - EMPATHY_PROFILE_CHOOSER (dialog->combobox_profile)); - cap = mc_profile_get_capabilities (profile); - - if (cap & MC_PROFILE_CAPABILITY_REGISTRATION_UI) { - gtk_widget_show (dialog->radiobutton_register); - gtk_widget_show (dialog->radiobutton_reuse); - } else { - gtk_widget_hide (dialog->radiobutton_register); - gtk_widget_hide (dialog->radiobutton_reuse); - } - g_object_unref (profile); + GtkBuilder *gui; + gchar *filename; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + filename = empathy_file_lookup ("empathy-accounts-dialog.ui", "src"); + + gui = empathy_builder_get_file (filename, + "accounts_dialog", &priv->window, + "vbox_details", &priv->vbox_details, + "frame_no_protocol", &priv->frame_no_protocol, + "alignment_settings", &priv->alignment_settings, + "treeview", &priv->treeview, + "frame_new_account", &priv->frame_new_account, + "hbox_type", &priv->hbox_type, + "button_create", &priv->button_create, + "button_back", &priv->button_back, + "radiobutton_reuse", &priv->radiobutton_reuse, + "radiobutton_register", &priv->radiobutton_register, + "image_type", &priv->image_type, + "label_name", &priv->label_name, + "button_add", &priv->button_add, + NULL); + g_free (filename); + + empathy_builder_connect (gui, dialog, + "accounts_dialog", "response", accounts_dialog_response_cb, + "accounts_dialog", "destroy", accounts_dialog_destroy_cb, + "button_create", "clicked", accounts_dialog_button_create_clicked_cb, + "button_back", "clicked", accounts_dialog_button_back_clicked_cb, + "button_add", "clicked", accounts_dialog_button_add_clicked_cb, + "button_help", "clicked", accounts_dialog_button_help_clicked_cb, + NULL); + + g_object_unref (gui); + + priv->combobox_protocol = empathy_protocol_chooser_new (); + gtk_box_pack_start (GTK_BOX (priv->hbox_type), + priv->combobox_protocol, + TRUE, TRUE, 0); + gtk_widget_show (priv->combobox_protocol); + 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 (priv->window), + priv->parent_window); } static void -accounts_dialog_button_add_clicked_cb (GtkWidget *button, - EmpathyAccountsDialog *dialog) +do_dispose (GObject *obj) +{ + EmpathyAccountsDialog *dialog = EMPATHY_ACCOUNTS_DIALOG (obj); + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + /* Disconnect signals */ + g_signal_handlers_disconnect_by_func (priv->account_manager, + accounts_dialog_account_added_cb, + dialog); + g_signal_handlers_disconnect_by_func (priv->account_manager, + accounts_dialog_account_removed_cb, + dialog); + g_signal_handlers_disconnect_by_func (priv->account_manager, + accounts_dialog_account_enabled_cb, + dialog); + g_signal_handlers_disconnect_by_func (priv->account_manager, + accounts_dialog_account_disabled_cb, + dialog); + g_signal_handlers_disconnect_by_func (priv->account_manager, + accounts_dialog_account_changed_cb, + dialog); + g_signal_handlers_disconnect_by_func (priv->account_manager, + accounts_dialog_connection_changed_cb, + dialog); + + if (priv->connecting_id) + g_source_remove (priv->connecting_id); + + if (priv->account_manager != NULL) + { + g_object_unref (priv->account_manager); + priv->account_manager = NULL; + } + + if (priv->cms != NULL) + { + g_object_unref (priv->cms); + priv->cms = NULL; + } + + if (priv->initial_selection != NULL) + g_object_unref (priv->initial_selection); + priv->initial_selection = NULL; + + G_OBJECT_CLASS (empathy_accounts_dialog_parent_class)->dispose (obj); +} + +static GObject * +do_constructor (GType type, + guint n_props, + GObjectConstructParam *props) { - GtkTreeView *view; - GtkTreeSelection *selection; - GtkTreeModel *model; - - view = GTK_TREE_VIEW (dialog->treeview); - model = gtk_tree_view_get_model (view); - selection = gtk_tree_view_get_selection (view); - gtk_tree_selection_unselect_all (selection); - - gtk_widget_set_sensitive (dialog->button_add, FALSE); - gtk_widget_set_sensitive (dialog->button_remove, FALSE); - gtk_widget_hide (dialog->vbox_details); - gtk_widget_hide (dialog->frame_no_profile); - gtk_widget_show (dialog->frame_new_account); - - /* If we have no account, no need of a back button */ - if (gtk_tree_model_iter_n_children (model, NULL) > 0) { - gtk_widget_show (dialog->button_back); - } else { - gtk_widget_hide (dialog->button_back); - } - - accounts_dialog_profile_changed_cb (dialog->radiobutton_register, dialog); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->radiobutton_reuse), - TRUE); - gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->combobox_profile), 0); - gtk_widget_grab_focus (dialog->combobox_profile); + GObject *retval; + + if (dialog_singleton) + { + retval = G_OBJECT (dialog_singleton); + g_object_ref (retval); + } + else + { + retval = + G_OBJECT_CLASS (empathy_accounts_dialog_parent_class)->constructor + (type, n_props, props); + + dialog_singleton = EMPATHY_ACCOUNTS_DIALOG (retval); + g_object_add_weak_pointer (retval, (gpointer) &dialog_singleton); + } + + return retval; } static void -accounts_dialog_button_help_clicked_cb (GtkWidget *button, - EmpathyAccountsDialog *dialog) +do_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) { - empathy_url_show (button, "ghelp:empathy#add-account"); + EmpathyAccountsDialogPriv *priv = GET_PRIV (object); + + switch (property_id) + { + case PROP_PARENT: + g_value_set_object (value, priv->parent_window); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } } static void -accounts_dialog_button_remove_clicked_cb (GtkWidget *button, - EmpathyAccountsDialog *dialog) +do_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) { - EmpathyAccount *account; - GtkWidget *message_dialog; - gint res; - - account = accounts_dialog_model_get_selected (dialog); - - if (!empathy_account_is_valid (account)) { - accounts_dialog_model_remove_selected (dialog); - accounts_dialog_model_select_first (dialog); - return; - } - message_dialog = gtk_message_dialog_new - (GTK_WINDOW (dialog->window), - GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_QUESTION, - GTK_BUTTONS_NONE, - _("You are about to remove your %s account!\n" - "Are you sure you want to proceed?"), - empathy_account_get_display_name (account)); - - gtk_message_dialog_format_secondary_text - (GTK_MESSAGE_DIALOG (message_dialog), - _("Any associated conversations and chat rooms will NOT be " - "removed if you decide to proceed.\n" - "\n" - "Should you decide to add the account back at a later time, " - "they will still be available.")); - - gtk_dialog_add_button (GTK_DIALOG (message_dialog), - GTK_STOCK_CANCEL, - GTK_RESPONSE_NO); - gtk_dialog_add_button (GTK_DIALOG (message_dialog), - GTK_STOCK_REMOVE, - GTK_RESPONSE_YES); - - gtk_widget_show (message_dialog); - res = gtk_dialog_run (GTK_DIALOG (message_dialog)); - - if (res == GTK_RESPONSE_YES) { - empathy_account_manager_remove (dialog->account_manager, account); - accounts_dialog_model_select_first (dialog); - } - gtk_widget_destroy (message_dialog); + EmpathyAccountsDialogPriv *priv = GET_PRIV (object); + + switch (property_id) + { + case PROP_PARENT: + priv->parent_window = g_value_get_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } } static void -accounts_dialog_button_import_clicked_cb (GtkWidget *button, - EmpathyAccountsDialog *dialog) +do_constructed (GObject *object) { - empathy_import_dialog_show (GTK_WINDOW (dialog->window), TRUE); + EmpathyAccountsDialog *dialog = EMPATHY_ACCOUNTS_DIALOG (object); + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + GList *accounts, *l; + gboolean import_asked; + + accounts_dialog_build_ui (dialog); + + /* Set up signalling */ + priv->account_manager = empathy_account_manager_dup_singleton (); + + g_signal_connect (priv->account_manager, "account-created", + G_CALLBACK (accounts_dialog_account_added_cb), + dialog); + g_signal_connect (priv->account_manager, "account-deleted", + G_CALLBACK (accounts_dialog_account_removed_cb), + dialog); + g_signal_connect (priv->account_manager, "account-enabled", + G_CALLBACK (accounts_dialog_account_enabled_cb), + dialog); + g_signal_connect (priv->account_manager, "account-disabled", + G_CALLBACK (accounts_dialog_account_disabled_cb), + dialog); + g_signal_connect (priv->account_manager, "account-changed", + G_CALLBACK (accounts_dialog_account_changed_cb), + dialog); + g_signal_connect (priv->account_manager, "account-connection-changed", + G_CALLBACK (accounts_dialog_connection_changed_cb), + dialog); + + accounts_dialog_model_setup (dialog); + + /* Add existing accounts */ + accounts = empathy_account_manager_dup_accounts (priv->account_manager); + for (l = accounts; l; l = l->next) + { + accounts_dialog_add_account (dialog, l->data); + g_object_unref (l->data); + } + g_list_free (accounts); + + priv->cms = empathy_connection_managers_dup_singleton (); + if (!empathy_connection_managers_is_ready (priv->cms)) + g_signal_connect (priv->cms, "notify::ready", + G_CALLBACK (accounts_dialog_cms_ready_cb), dialog); + + accounts_dialog_model_select_first (dialog); + + empathy_conf_get_bool (empathy_conf_get (), + EMPATHY_PREFS_IMPORT_ASKED, &import_asked); + + + if (empathy_import_accounts_to_import ()) + { + + if (!import_asked) + { + GtkWidget *import_dialog; + + empathy_conf_set_bool (empathy_conf_get (), + EMPATHY_PREFS_IMPORT_ASKED, TRUE); + import_dialog = empathy_import_dialog_new (GTK_WINDOW (priv->window), + FALSE); + gtk_widget_show (import_dialog); + } + } } static void -accounts_dialog_response_cb (GtkWidget *widget, - gint response, - EmpathyAccountsDialog *dialog) +empathy_accounts_dialog_class_init (EmpathyAccountsDialogClass *klass) { - if (response == GTK_RESPONSE_CLOSE) { - gtk_widget_destroy (widget); - } + GObjectClass *oclass = G_OBJECT_CLASS (klass); + GParamSpec *param_spec; + + oclass->constructor = do_constructor; + oclass->dispose = do_dispose; + oclass->constructed = do_constructed; + oclass->set_property = do_set_property; + oclass->get_property = do_get_property; + + param_spec = g_param_spec_object ("parent", + "parent", "The parent window", + GTK_TYPE_WINDOW, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (oclass, PROP_PARENT, param_spec); + + g_type_class_add_private (klass, sizeof (EmpathyAccountsDialogPriv)); } static void -accounts_dialog_destroy_cb (GtkWidget *widget, - EmpathyAccountsDialog *dialog) +empathy_accounts_dialog_init (EmpathyAccountsDialog *dialog) { - GList *accounts, *l; - - /* Disconnect signals */ - g_signal_handlers_disconnect_by_func (dialog->account_manager, - accounts_dialog_account_added_cb, - dialog); - g_signal_handlers_disconnect_by_func (dialog->account_manager, - accounts_dialog_account_removed_cb, - dialog); - g_signal_handlers_disconnect_by_func (dialog->account_manager, - accounts_dialog_account_enabled_cb, - dialog); - g_signal_handlers_disconnect_by_func (dialog->account_manager, - accounts_dialog_account_disabled_cb, - dialog); - g_signal_handlers_disconnect_by_func (dialog->account_manager, - accounts_dialog_account_changed_cb, - dialog); - g_signal_handlers_disconnect_by_func (dialog->account_manager, - accounts_dialog_connection_changed_cb, - dialog); - - /* Delete incomplete accounts */ - accounts = empathy_account_manager_dup_accounts (dialog->account_manager); - for (l = accounts; l; l = l->next) { - EmpathyAccount *account; - - account = l->data; - if (!empathy_account_is_valid (account)) { - /* FIXME: Warn the user the account is not complete - * and is going to be removed. */ - empathy_account_manager_remove (dialog->account_manager, account); - } - - g_object_unref (account); - } - g_list_free (accounts); - - if (dialog->connecting_id) { - g_source_remove (dialog->connecting_id); - } - - g_object_unref (dialog->account_manager); - g_object_unref (dialog->mc); - - g_free (dialog); + EmpathyAccountsDialogPriv *priv; + + priv = G_TYPE_INSTANCE_GET_PRIVATE ((dialog), + EMPATHY_TYPE_ACCOUNTS_DIALOG, + EmpathyAccountsDialogPriv); + dialog->priv = priv; } +/* public methods */ + GtkWidget * empathy_accounts_dialog_show (GtkWindow *parent, - EmpathyAccount *selected_account) + EmpathyAccount *selected_account) { - static EmpathyAccountsDialog *dialog = NULL; - GtkBuilder *gui; - gchar *filename; - GList *accounts, *l; - gboolean import_asked; - - if (dialog) { - gtk_window_present (GTK_WINDOW (dialog->window)); - return dialog->window; - } - - dialog = g_new0 (EmpathyAccountsDialog, 1); - - filename = empathy_file_lookup ("empathy-accounts-dialog.ui", - "src"); - gui = empathy_builder_get_file (filename, - "accounts_dialog", &dialog->window, - "vbox_details", &dialog->vbox_details, - "frame_no_profile", &dialog->frame_no_profile, - "alignment_settings", &dialog->alignment_settings, - "treeview", &dialog->treeview, - "frame_new_account", &dialog->frame_new_account, - "hbox_type", &dialog->hbox_type, - "button_create", &dialog->button_create, - "button_back", &dialog->button_back, - "radiobutton_reuse", &dialog->radiobutton_reuse, - "radiobutton_register", &dialog->radiobutton_register, - "image_type", &dialog->image_type, - "label_name", &dialog->label_name, - "button_add", &dialog->button_add, - "button_remove", &dialog->button_remove, - "button_import", &dialog->button_import, - NULL); - g_free (filename); - - empathy_builder_connect (gui, dialog, - "accounts_dialog", "destroy", accounts_dialog_destroy_cb, - "accounts_dialog", "response", accounts_dialog_response_cb, - "button_create", "clicked", accounts_dialog_button_create_clicked_cb, - "button_back", "clicked", accounts_dialog_button_back_clicked_cb, - "button_add", "clicked", accounts_dialog_button_add_clicked_cb, - "button_remove", "clicked", accounts_dialog_button_remove_clicked_cb, - "button_import", "clicked", accounts_dialog_button_import_clicked_cb, - "button_help", "clicked", accounts_dialog_button_help_clicked_cb, - NULL); - - g_object_add_weak_pointer (G_OBJECT (dialog->window), (gpointer) &dialog); - - g_object_unref (gui); - - /* Create profile chooser */ - dialog->combobox_profile = empathy_profile_chooser_new (); - gtk_box_pack_end (GTK_BOX (dialog->hbox_type), - dialog->combobox_profile, - TRUE, TRUE, 0); - gtk_widget_show (dialog->combobox_profile); - g_signal_connect (dialog->combobox_profile, "changed", - G_CALLBACK (accounts_dialog_profile_changed_cb), - dialog); - - /* Set up signalling */ - dialog->account_manager = empathy_account_manager_dup_singleton (); - dialog->mc = empathy_mission_control_dup_singleton (); - - g_signal_connect (dialog->account_manager, "account-created", - G_CALLBACK (accounts_dialog_account_added_cb), - dialog); - g_signal_connect (dialog->account_manager, "account-deleted", - G_CALLBACK (accounts_dialog_account_removed_cb), - dialog); - g_signal_connect (dialog->account_manager, "account-enabled", - G_CALLBACK (accounts_dialog_account_enabled_cb), - dialog); - g_signal_connect (dialog->account_manager, "account-disabled", - G_CALLBACK (accounts_dialog_account_disabled_cb), - dialog); - g_signal_connect (dialog->account_manager, "account-changed", - G_CALLBACK (accounts_dialog_account_changed_cb), - dialog); - g_signal_connect (dialog->account_manager, "account-connection-changed", - G_CALLBACK (accounts_dialog_connection_changed_cb), - dialog); - - accounts_dialog_model_setup (dialog); - - /* Add existing accounts */ - accounts = empathy_account_manager_dup_accounts (dialog->account_manager); - for (l = accounts; l; l = l->next) { - accounts_dialog_add_or_update_account (dialog, l->data); - g_object_unref (l->data); - } - g_list_free (accounts); - - if (selected_account) { - accounts_dialog_model_set_selected (dialog, selected_account); - } else { - accounts_dialog_model_select_first (dialog); - } - - if (parent) { - gtk_window_set_transient_for (GTK_WINDOW (dialog->window), - GTK_WINDOW (parent)); - } - - gtk_widget_show (dialog->window); - - empathy_conf_get_bool (empathy_conf_get (), - EMPATHY_PREFS_IMPORT_ASKED, &import_asked); - - - if (empathy_import_dialog_accounts_to_import ()) { - - if (!import_asked) { - empathy_conf_set_bool (empathy_conf_get (), - EMPATHY_PREFS_IMPORT_ASKED, TRUE); - empathy_import_dialog_show (GTK_WINDOW (dialog->window), - FALSE); - } - } else { - gtk_widget_set_sensitive (dialog->button_import, FALSE); - } - - return dialog->window; -} + EmpathyAccountsDialog *dialog; + EmpathyAccountsDialogPriv *priv; + + dialog = g_object_new (EMPATHY_TYPE_ACCOUNTS_DIALOG, + "parent", parent, NULL); + priv = GET_PRIV (dialog); + + if (selected_account) + { + if (empathy_connection_managers_is_ready (priv->cms)) + accounts_dialog_set_selected_account (dialog, selected_account); + else + /* save the selection to set it later when the cms + * becomes ready. + */ + priv->initial_selection = g_object_ref (selected_account); + } + + gtk_window_present (GTK_WINDOW (priv->window)); + + return priv->window; +} diff --git a/src/empathy-accounts-dialog.h b/src/empathy-accounts-dialog.h index 11e237c8f..aa8f7c06b 100644 --- a/src/empathy-accounts-dialog.h +++ b/src/empathy-accounts-dialog.h @@ -1,4 +1,3 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * Copyright (C) 2005-2007 Imendio AB * Copyright (C) 2007-2008 Collabora Ltd. @@ -31,8 +30,32 @@ G_BEGIN_DECLS +#define EMPATHY_TYPE_ACCOUNTS_DIALOG empathy_accounts_dialog_get_type() +#define EMPATHY_ACCOUNTS_DIALOG(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), EMPATHY_TYPE_ACCOUNTS_DIALOG, EmpathyAccountsDialog)) +#define EMPATHY_ACCOUNTS_DIALOG_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), EMPATHY_TYPE_ACCOUNTS_DIALOG, EmpathyAccountsDialogClass)) +#define EMPATHY_IS_ACCOUNTS_DIALOG(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EMPATHY_TYPE_ACCOUNTS_DIALOG)) +#define EMPATHY_IS_ACCOUNTS_DIALOG_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), EMPATHY_TYPE_ACCOUNTS_DIALOG)) +#define EMPATHY_ACCOUNTS_DIALOG_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_ACCOUNTS_DIALOG, EmpathyAccountsDialogClass)) + +typedef struct { + GObject parent; + + /* private */ + gpointer priv; +} EmpathyAccountsDialog; + +typedef struct { + GObjectClass parent_class; +} EmpathyAccountsDialogClass; + +GType empathy_accounts_dialog_get_type (void); GtkWidget *empathy_accounts_dialog_show (GtkWindow *parent, - EmpathyAccount *selected_account); + EmpathyAccount *selected_account); G_END_DECLS diff --git a/src/empathy-accounts-dialog.ui b/src/empathy-accounts-dialog.ui index da00f45d7..e5226b270 100644 --- a/src/empathy-accounts-dialog.ui +++ b/src/empathy-accounts-dialog.ui @@ -2,14 +2,11 @@ <interface> <requires lib="gtk+" version="2.16"/> <!-- interface-naming-policy toplevel-contextual --> - <object class="GtkImage" id="add_image"> - <property name="stock">gtk-add</property> - <property name="icon-size">4</property> - </object> <object class="GtkDialog" id="accounts_dialog"> <property name="border_width">5</property> <property name="title" translatable="yes">Accounts</property> <property name="role">accounts</property> + <property name="default_width">640</property> <property name="type_hint">dialog</property> <property name="has_separator">False</property> <child internal-child="vbox"> @@ -46,62 +43,18 @@ </packing> </child> <child> - <object class="GtkVBox" id="vbox1"> + <object class="GtkButton" id="button_add"> + <property name="label" translatable="yes">_Add...</property> <property name="visible">True</property> - <property name="spacing">6</property> - <property name="homogeneous">True</property> - <child> - <object class="GtkHBox" id="hbox148"> - <property name="visible">True</property> - <property name="spacing">6</property> - <property name="homogeneous">True</property> - <child> - <object class="GtkButton" id="button_add"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="image">add_image</property> - <property name="label" translatable="yes">_Add...</property> - <property name="use_underline">True</property> - </object> - <packing> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkButton" id="button_remove"> - <property name="label">gtk-remove</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_stock">True</property> - </object> - <packing> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkButton" id="button_import"> - <property name="label" translatable="yes">Import Accounts...</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - </object> - <packing> - <property name="position">1</property> - </packing> - </child> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="image">add_image</property> + <property name="use_underline">True</property> </object> <packing> <property name="expand">False</property> - <property name="position">1</property> + <property name="fill">False</property> + <property name="position">2</property> </packing> </child> </object> @@ -127,12 +80,11 @@ <object class="GtkLabel" id="label_name"> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="label" translatable="yes">Gmail</property> + <property name="selectable">True</property> <attributes> <attribute name="weight" value="bold"/> - <attribute name="scale" value="1.2"/> + <attribute name="scale" value="1.200000"/> </attributes> - <property name="selectable">True</property> </object> <packing> <property name="position">0</property> @@ -159,28 +111,12 @@ </packing> </child> <child> - <object class="GtkFrame" id="frame2"> + <object class="GtkAlignment" id="alignment_settings"> <property name="visible">True</property> - <property name="label_xalign">0</property> - <property name="shadow_type">none</property> + <property name="top_padding">6</property> + <property name="left_padding">20</property> <child> - <object class="GtkAlignment" id="alignment_settings"> - <property name="visible">True</property> - <property name="top_padding">6</property> - <property name="left_padding">20</property> - <child> - <placeholder/> - </child> - </object> - </child> - <child type="label"> - <object class="GtkLabel" id="label599"> - <property name="visible">True</property> - <property name="label" translatable="yes">Settings</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> + <placeholder/> </child> </object> <packing> @@ -206,29 +142,6 @@ <property name="visible">True</property> <property name="spacing">12</property> <child> - <object class="GtkHBox" id="hbox_type"> - <property name="visible">True</property> - <property name="spacing">6</property> - <child> - <object class="GtkLabel" id="label645"> - <property name="visible">True</property> - <property name="label" translatable="yes">Type:</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <placeholder/> - </child> - </object> - <packing> - <property name="position">0</property> - </packing> - </child> - <child> <object class="GtkVBox" id="vbox2"> <property name="visible">True</property> <property name="orientation">vertical</property> @@ -347,12 +260,45 @@ </object> </child> <child type="label"> - <object class="GtkLabel" id="label643"> + <object class="GtkHBox" id="hbox_add_account"> <property name="visible">True</property> - <property name="label" translatable="yes">Add Account</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> + <child> + <object class="GtkLabel" id="label643"> + <property name="visible">True</property> + <property name="label" translatable="yes">Add new</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="padding">5</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkHBox" id="hbox_type"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <placeholder/> + </child> + <child> + <object class="GtkLabel" id="label645"> + <property name="visible">True</property> + <property name="label" translatable="yes">account</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="pack_type">end</property> + <property name="position">0</property> + </packing> + </child> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> </object> </child> </object> @@ -362,7 +308,7 @@ </packing> </child> <child> - <object class="GtkFrame" id="frame_no_profile"> + <object class="GtkFrame" id="frame_no_protocol"> <property name="label_xalign">0</property> <property name="shadow_type">none</property> <child> @@ -454,4 +400,7 @@ <action-widget response="-7">button_close</action-widget> </action-widgets> </object> + <object class="GtkImage" id="add_image"> + <property name="stock">gtk-add</property> + </object> </interface> diff --git a/src/empathy-chat-window.c b/src/empathy-chat-window.c index fb5a5c796..5f81ac167 100644 --- a/src/empathy-chat-window.c +++ b/src/empathy-chat-window.c @@ -35,7 +35,6 @@ #include <libnotify/notification.h> #include <telepathy-glib/util.h> -#include <libmissioncontrol/mission-control.h> #include <libempathy/empathy-contact.h> #include <libempathy/empathy-message.h> @@ -1268,7 +1267,7 @@ chat_window_drag_data_received (GtkWidget *widget, strv = g_strsplit (id, "/", 2); account_id = strv[0]; contact_id = strv[1]; - account = empathy_account_manager_lookup (account_manager, account_id); + account = empathy_account_manager_get_account (account_manager, account_id); chat = empathy_chat_window_find_chat (account, contact_id); if (!chat) { @@ -1281,11 +1280,9 @@ chat_window_drag_data_received (GtkWidget *widget, connection, contact_id, NULL, NULL); } - g_object_unref (account); g_strfreev (strv); return; } - g_object_unref (account); g_object_unref (account_manager); g_strfreev (strv); @@ -1777,7 +1774,7 @@ empathy_chat_window_find_chat (EmpathyAccount *account, chat = ll->data; - if (empathy_account_equal (account, empathy_chat_get_account (chat)) && + if (account == empathy_chat_get_account (chat) && !tp_strdiff (id, empathy_chat_get_id (chat))) { return chat; } diff --git a/src/empathy-chatrooms-window.c b/src/empathy-chatrooms-window.c index 3b5dd1f77..4ec71ec49 100644 --- a/src/empathy-chatrooms-window.c +++ b/src/empathy-chatrooms-window.c @@ -514,7 +514,7 @@ chatrooms_window_chatroom_added_cb (EmpathyChatroomManager *manager, if (!account) { chatrooms_window_model_add (window, chatroom, FALSE); } else { - if (empathy_account_equal (account, empathy_chatroom_get_account (chatroom))) { + if (account == empathy_chatroom_get_account (chatroom)) { chatrooms_window_model_add (window, chatroom, FALSE); } diff --git a/src/empathy-debug-dialog.c b/src/empathy-debug-dialog.c index 9d047bab1..d71542db0 100644 --- a/src/empathy-debug-dialog.c +++ b/src/empathy-debug-dialog.c @@ -284,7 +284,6 @@ debug_dialog_cm_chooser_changed_cb (GtkComboBox *cm_chooser, EmpathyDebugDialog *debug_dialog) { EmpathyDebugDialogPriv *priv = GET_PRIV (debug_dialog); - MissionControl *mc; TpDBusDaemon *dbus; GError *error = NULL; gchar *bus_name; @@ -302,13 +301,11 @@ debug_dialog_cm_chooser_changed_cb (GtkComboBox *cm_chooser, return; } - mc = empathy_mission_control_dup_singleton (); dbus = tp_dbus_daemon_dup (&error); if (error != NULL) { DEBUG ("Failed at duping the dbus daemon: %s", error->message); - g_object_unref (mc); } gtk_tree_model_get (GTK_TREE_MODEL (priv->cms), &iter, @@ -344,7 +341,6 @@ debug_dialog_cm_chooser_changed_cb (GtkComboBox *cm_chooser, debug_dialog_get_messages_cb, debug_dialog, NULL, NULL); g_object_unref (dbus); - g_object_unref (mc); } typedef struct diff --git a/src/empathy-event-manager.c b/src/empathy-event-manager.c index 1a7ec09cb..1be3ff7ce 100644 --- a/src/empathy-event-manager.c +++ b/src/empathy-event-manager.c @@ -25,6 +25,7 @@ #include <glib/gi18n.h> #include <telepathy-glib/util.h> +#include <telepathy-glib/interfaces.h> #include <libempathy/empathy-account-manager.h> #include <libempathy/empathy-dispatcher.h> diff --git a/src/empathy-import-dialog.c b/src/empathy-import-dialog.c index 1e135892d..94c6fd765 100644 --- a/src/empathy-import-dialog.c +++ b/src/empathy-import-dialog.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Collabora Ltd. + * Copyright (C) 2008-2009 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 @@ -17,12 +17,11 @@ * Boston, MA 02110-1301 USA * * Authors: Jonny Lamb <jonny.lamb@collabora.co.uk> - * */ + * Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> + */ #include <config.h> -#include <string.h> - #include <glib.h> #include <gtk/gtk.h> #include <glib/gi18n.h> @@ -31,401 +30,210 @@ #include "empathy-import-dialog.h" #include "empathy-import-pidgin.h" +#include "empathy-import-widget.h" #define DEBUG_FLAG EMPATHY_DEBUG_OTHER #include <libempathy/empathy-debug.h> #include <libempathy/empathy-utils.h> -#include <libempathy/empathy-account-manager.h> - #include <libempathy-gtk/empathy-ui-utils.h> -typedef struct -{ - GtkWidget *window; - GtkWidget *treeview; - GtkWidget *button_ok; - GtkWidget *button_cancel; - GList *accounts; -} EmpathyImportDialog; - -enum -{ - COL_IMPORT = 0, - COL_PROTOCOL, - COL_NAME, - COL_SOURCE, - COL_ACCOUNT_DATA, - COL_COUNT +enum { + PROP_PARENT = 1, + PROP_SHOW_WARNING }; -EmpathyImportAccountData * -empathy_import_account_data_new (const gchar *source) -{ - EmpathyImportAccountData *data; +typedef struct { + GtkWindow *parent_window; - g_return_val_if_fail (!EMP_STR_EMPTY (source), NULL); + EmpathyImportWidget *iw; - data = g_slice_new0 (EmpathyImportAccountData); - data->settings = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, - (GDestroyNotify) tp_g_value_slice_free); - data->source = g_strdup (source); + gboolean show_warning; +} EmpathyImportDialogPriv; - return data; -} - -void -empathy_import_account_data_free (EmpathyImportAccountData *data) -{ - if (data == NULL) - return; - if (data->profile != NULL) - g_object_unref (data->profile); - if (data->settings != NULL) - g_hash_table_destroy (data->settings); - if (data->source != NULL) - g_free (data->source); - - g_slice_free (EmpathyImportAccountData, data); -} +G_DEFINE_TYPE (EmpathyImportDialog, empathy_import_dialog, GTK_TYPE_DIALOG) +#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyImportDialog) static void -import_dialog_add_account (EmpathyImportAccountData *data) +import_dialog_add_import_widget (EmpathyImportDialog *self) { - EmpathyAccountManager *account_manager; - EmpathyAccount *account; - GHashTableIter iter; - gpointer key, value; - gchar *display_name; - GValue *username; - - account_manager = empathy_account_manager_dup_singleton (); - account = empathy_account_manager_create (account_manager, data->profile); - g_object_unref (account_manager); - if (account == NULL) - { - DEBUG ("Failed to create account"); - return; - } + EmpathyImportWidget *iw; + EmpathyImportDialogPriv *priv = GET_PRIV (self); + GtkWidget *widget, *area; - g_hash_table_iter_init (&iter, data->settings); - while (g_hash_table_iter_next (&iter, &key, &value)) - { - const gchar *param = key; - GValue *gvalue = value; + area = gtk_dialog_get_content_area (GTK_DIALOG (self)); - switch (G_VALUE_TYPE (gvalue)) - { - case G_TYPE_STRING: - DEBUG ("Set param '%s' to '%s' (string)", - param, g_value_get_string (gvalue)); - empathy_account_set_param_string (account, - param, g_value_get_string (gvalue)); - break; - - case G_TYPE_BOOLEAN: - DEBUG ("Set param '%s' to %s (boolean)", - param, g_value_get_boolean (gvalue) ? "TRUE" : "FALSE"); - empathy_account_set_param_boolean (account, - param, g_value_get_boolean (gvalue)); - break; - - case G_TYPE_INT: - DEBUG ("Set param '%s' to '%i' (integer)", - param, g_value_get_int (gvalue)); - empathy_account_set_param_int (account, - param, g_value_get_int (gvalue)); - break; - } - } + iw = empathy_import_widget_new (EMPATHY_IMPORT_APPLICATION_ALL); + widget = empathy_import_widget_get_widget (iw); + gtk_box_pack_start (GTK_BOX (area), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); - /* Set the display name of the account */ - username = g_hash_table_lookup (data->settings, "account"); - display_name = g_strdup_printf ("%s (%s)", - mc_profile_get_display_name (data->profile), - g_value_get_string (username)); - empathy_account_set_display_name (account, display_name); + priv->iw = iw; - g_free (display_name); - g_object_unref (account); -} - -static gboolean -import_dialog_account_id_in_list (GList *accounts, - const gchar *account_id) -{ - GList *l; - - for (l = accounts; l; l = l->next) - { - McAccount *account = l->data; - gchar *value = NULL; - gboolean result; - - mc_account_get_param_string (account, "account", &value); - - if (value == NULL) - continue; - - result = tp_strdiff (value, account_id); - - g_free (value); - - if (!result) - return TRUE; - } - - return FALSE; + gtk_dialog_add_buttons (GTK_DIALOG (self), GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); } static void -import_dialog_add_accounts_to_model (EmpathyImportDialog *dialog) +import_dialog_show_warning_message (EmpathyImportDialog *self) { - GtkTreeModel *model; - GtkTreeIter iter; - GList *l; + GtkWidget *hbox, *vbox, *w; - model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview)); + vbox = gtk_vbox_new (FALSE, 12); + hbox = gtk_hbox_new (FALSE, 12); - for (l = dialog->accounts; l; l = l->next) - { - GValue *value; - EmpathyImportAccountData *data = l->data; - gboolean import; - GList *accounts; + w = gtk_label_new (_("No accounts to import could be found. Empathy " + "currently only supports importing accounts from Pidgin.")); + gtk_label_set_line_wrap (GTK_LABEL (w), TRUE); + gtk_label_set_selectable (GTK_LABEL (w), TRUE); + gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.0); + gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 0); - value = g_hash_table_lookup (data->settings, "account"); + w = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, + GTK_ICON_SIZE_DIALOG); + gtk_misc_set_alignment (GTK_MISC (w), 0.5, 0.0); + gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0); - accounts = mc_accounts_list_by_profile (data->profile); + gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0); - /* Only set the "Import" cell to be active if there isn't already an - * account set up with the same account id. */ - import = !import_dialog_account_id_in_list (accounts, - g_value_get_string (value)); + w = gtk_dialog_get_content_area (GTK_DIALOG (self)); + gtk_box_pack_start (GTK_BOX (w), hbox, FALSE, FALSE, 0); - mc_accounts_list_free (accounts); + gtk_box_set_spacing (GTK_BOX (w), 14); /* 14 + 2 * 5 = 24 */ - gtk_list_store_append (GTK_LIST_STORE (model), &iter); + gtk_dialog_add_button (GTK_DIALOG (self), GTK_STOCK_CLOSE, + GTK_RESPONSE_CLOSE); - gtk_list_store_set (GTK_LIST_STORE (model), &iter, - COL_IMPORT, import, - COL_PROTOCOL, mc_profile_get_display_name (data->profile), - COL_NAME, g_value_get_string (value), - COL_SOURCE, data->source, - COL_ACCOUNT_DATA, data, - -1); - } + gtk_widget_show_all (w); } static void -import_dialog_cell_toggled_cb (GtkCellRendererToggle *cell_renderer, - const gchar *path_str, - EmpathyImportDialog *dialog) +impl_signal_response (GtkDialog *dialog, + gint response_id) { - GtkTreeModel *model; - GtkTreeIter iter; - GtkTreePath *path; + EmpathyImportDialogPriv *priv = GET_PRIV (dialog); - path = gtk_tree_path_new_from_string (path_str); - model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview)); + if (response_id == GTK_RESPONSE_OK) + empathy_import_widget_add_selected_accounts (priv->iw); - gtk_tree_model_get_iter (model, &iter, path); - - gtk_list_store_set (GTK_LIST_STORE (model), &iter, - COL_IMPORT, !gtk_cell_renderer_toggle_get_active (cell_renderer), - -1); - - gtk_tree_path_free (path); + gtk_widget_destroy (GTK_WIDGET (dialog)); } static void -import_dialog_set_up_account_list (EmpathyImportDialog *dialog) -{ - GtkListStore *store; - GtkTreeView *view; - GtkTreeViewColumn *column; - GtkCellRenderer *cell; - - store = gtk_list_store_new (COL_COUNT, G_TYPE_BOOLEAN, G_TYPE_STRING, - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER); - - gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->treeview), - GTK_TREE_MODEL (store)); - - g_object_unref (store); - - view = GTK_TREE_VIEW (dialog->treeview); - gtk_tree_view_set_headers_visible (view, TRUE); - - /* Import column */ - cell = gtk_cell_renderer_toggle_new (); - gtk_tree_view_insert_column_with_attributes (view, -1, - /* Translators: this is the header of a treeview column */ - _("Import"), cell, - "active", COL_IMPORT, - NULL); - - g_signal_connect (cell, "toggled", - G_CALLBACK (import_dialog_cell_toggled_cb), dialog); - - /* Protocol column */ - column = gtk_tree_view_column_new (); - gtk_tree_view_column_set_title (column, _("Protocol")); - gtk_tree_view_column_set_expand (column, TRUE); - gtk_tree_view_append_column (view, column); - - cell = gtk_cell_renderer_text_new (); - g_object_set (cell, - "editable", FALSE, - NULL); - gtk_tree_view_column_pack_start (column, cell, TRUE); - gtk_tree_view_column_add_attribute (column, cell, "text", COL_PROTOCOL); - - /* Account column */ - column = gtk_tree_view_column_new (); - gtk_tree_view_column_set_title (column, _("Account")); - gtk_tree_view_column_set_expand (column, TRUE); - gtk_tree_view_append_column (view, column); - - cell = gtk_cell_renderer_text_new (); - g_object_set (cell, - "editable", FALSE, - NULL); - gtk_tree_view_column_pack_start (column, cell, TRUE); - gtk_tree_view_column_add_attribute (column, cell, "text", COL_NAME); - - /* Source column */ - column = gtk_tree_view_column_new (); - gtk_tree_view_column_set_title (column, _("Source")); - gtk_tree_view_column_set_expand (column, TRUE); - gtk_tree_view_append_column (view, column); - - cell = gtk_cell_renderer_text_new (); - g_object_set (cell, - "editable", FALSE, - NULL); - gtk_tree_view_column_pack_start (column, cell, TRUE); - gtk_tree_view_column_add_attribute (column, cell, "text", COL_SOURCE); - - import_dialog_add_accounts_to_model (dialog); -} - -static gboolean -import_dialog_tree_model_foreach (GtkTreeModel *model, - GtkTreePath *path, - GtkTreeIter *iter, - gpointer user_data) +do_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) { - gboolean to_import; - EmpathyImportAccountData *data; - - gtk_tree_model_get (model, iter, - COL_IMPORT, &to_import, - COL_ACCOUNT_DATA, &data, - -1); - - if (to_import) - import_dialog_add_account (data); - - return FALSE; -} + EmpathyImportDialogPriv *priv = GET_PRIV (object); -static void -import_dialog_response_cb (GtkWidget *widget, - gint response, - EmpathyImportDialog *dialog) -{ - if (response == GTK_RESPONSE_OK) + switch (property_id) { - GtkTreeModel *model; - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview)); - gtk_tree_model_foreach (model, import_dialog_tree_model_foreach, dialog); + case PROP_PARENT: + g_value_set_object (value, priv->parent_window); + break; + case PROP_SHOW_WARNING: + g_value_set_boolean (value, priv->show_warning); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } - - gtk_widget_destroy (dialog->window); } static void -import_dialog_destroy_cb (GtkWidget *widget, - EmpathyImportDialog *dialog) +do_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) { - g_list_foreach (dialog->accounts, (GFunc) empathy_import_account_data_free, - NULL); - g_list_free (dialog->accounts); - g_slice_free (EmpathyImportDialog, dialog); -} + EmpathyImportDialogPriv *priv = GET_PRIV (object); -gboolean -empathy_import_dialog_accounts_to_import (void) -{ - return empathy_import_pidgin_accounts_to_import (); + switch (property_id) + { + case PROP_PARENT: + priv->parent_window = g_value_get_object (value); + break; + case PROP_SHOW_WARNING: + priv->show_warning = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } } -void -empathy_import_dialog_show (GtkWindow *parent, - gboolean warning) +static void +do_constructed (GObject *obj) { - static EmpathyImportDialog *dialog = NULL; - GtkBuilder *gui; - gchar *filename; - GList *accounts = NULL; - - /* This window is a singleton. If it already exist, present it */ - if (dialog) - { - gtk_window_present (GTK_WINDOW (dialog->window)); - return; - } + EmpathyImportDialog *self = EMPATHY_IMPORT_DIALOG (obj); + EmpathyImportDialogPriv *priv = GET_PRIV (self); + gboolean have_accounts; - /* Load all accounts from all supported applications */ - accounts = g_list_concat (accounts, empathy_import_pidgin_load ()); + have_accounts = empathy_import_accounts_to_import (); - /* Check if we have accounts to import before creating the window */ - if (!accounts) + if (!have_accounts) { - GtkWidget *message; - - if (warning) + if (priv->show_warning) { - message = gtk_message_dialog_new (parent, - GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE, - _("No accounts to import could be found. Empathy currently only " - "supports importing accounts from Pidgin.")); - - gtk_dialog_run (GTK_DIALOG (message)); - gtk_widget_destroy (message); + import_dialog_show_warning_message (self); } else DEBUG ("No accounts to import; closing dialog silently."); - - return; + } + else + { + import_dialog_add_import_widget (self); } - /* We have accounts, let's display the window with them */ - dialog = g_slice_new0 (EmpathyImportDialog); - dialog->accounts = accounts; - - filename = empathy_file_lookup ("empathy-import-dialog.ui", "src"); - gui = empathy_builder_get_file (filename, - "import_dialog", &dialog->window, - "treeview", &dialog->treeview, - NULL); - - empathy_builder_connect (gui, dialog, - "import_dialog", "destroy", import_dialog_destroy_cb, - "import_dialog", "response", import_dialog_response_cb, - NULL); - - g_object_add_weak_pointer (G_OBJECT (dialog->window), (gpointer) &dialog); + if (priv->parent_window) + gtk_window_set_transient_for (GTK_WINDOW (self), priv->parent_window); +} - g_free (filename); - g_object_unref (gui); +static void +empathy_import_dialog_init (EmpathyImportDialog *self) +{ + EmpathyImportDialogPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, + EMPATHY_TYPE_IMPORT_DIALOG, EmpathyImportDialogPriv); - if (parent) - gtk_window_set_transient_for (GTK_WINDOW (dialog->window), parent); + self->priv = priv; - import_dialog_set_up_account_list (dialog); + gtk_container_set_border_width (GTK_CONTAINER (self), 5); + gtk_window_set_title (GTK_WINDOW (self), _("Import Accounts")); + gtk_window_set_modal (GTK_WINDOW (self), TRUE); + gtk_dialog_set_has_separator (GTK_DIALOG (self), FALSE); +} - gtk_widget_show (dialog->window); +static void +empathy_import_dialog_class_init (EmpathyImportDialogClass *klass) +{ + GObjectClass *oclass = G_OBJECT_CLASS (klass); + GtkDialogClass *gtkclass = GTK_DIALOG_CLASS (klass); + GParamSpec *param_spec; + + oclass->constructed = do_constructed; + oclass->get_property = do_get_property; + oclass->set_property = do_set_property; + + gtkclass->response = impl_signal_response; + + param_spec = g_param_spec_object ("parent-window", + "parent-window", "The parent window", + GTK_TYPE_WINDOW, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (oclass, PROP_PARENT, param_spec); + + param_spec = g_param_spec_boolean ("show-warning", + "show-warning", "Whether a warning should be shown when there are no " + "sources for importing accounts.", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (oclass, PROP_SHOW_WARNING, param_spec); + + g_type_class_add_private (klass, sizeof (EmpathyImportDialogPriv)); } +GtkWidget * +empathy_import_dialog_new (GtkWindow *parent, + gboolean warning) +{ + return g_object_new (EMPATHY_TYPE_IMPORT_DIALOG, "parent-window", + parent, "show-warning", warning, NULL); +} diff --git a/src/empathy-import-dialog.h b/src/empathy-import-dialog.h index 0e3fd148f..0e9d225c4 100644 --- a/src/empathy-import-dialog.h +++ b/src/empathy-import-dialog.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Collabora Ltd. + * Copyright (C) 2008-2009 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 @@ -17,30 +17,46 @@ * Boston, MA 02110-1301 USA * * Authors: Jonny Lamb <jonny.lamb@collabora.co.uk> + * Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> */ #include <gtk/gtk.h> -#include <libmissioncontrol/mc-profile.h> #ifndef __EMPATHY_IMPORT_DIALOG_H__ #define __EMPATHY_IMPORT_DIALOG_H__ G_BEGIN_DECLS -typedef struct -{ - /* Table mapping CM param string to a GValue */ - GHashTable *settings; - /* The profile to use for this account */ - McProfile *profile; - /* The name of the account import source */ - gchar *source; -} EmpathyImportAccountData; - -EmpathyImportAccountData *empathy_import_account_data_new (const gchar *source); -void empathy_import_account_data_free (EmpathyImportAccountData *data); -gboolean empathy_import_dialog_accounts_to_import (void); -void empathy_import_dialog_show (GtkWindow *parent, gboolean warning); +#define EMPATHY_TYPE_IMPORT_DIALOG empathy_import_dialog_get_type() +#define EMPATHY_IMPORT_DIALOG(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), EMPATHY_TYPE_IMPORT_DIALOG,\ + EmpathyImportDialog)) +#define EMPATHY_IMPORT_DIALOG_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), EMPATHY_TYPE_IMPORT_DIALOG,\ + EmpathyImportDialogClass)) +#define EMPATHY_IS_IMPORT_DIALOG(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EMPATHY_TYPE_IMPORT_DIALOG)) +#define EMPATHY_IS_IMPORT_DIALOG_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), EMPATHY_TYPE_IMPORT_DIALOG)) +#define EMPATHY_IMPORT_DIALOG_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_IMPORT_DIALOG,\ + EmpathyImportDialogClass)) + +typedef struct { + GtkDialog parent; + + /* private */ + gpointer priv; +} EmpathyImportDialog; + +typedef struct { + GtkDialogClass parent_class; +} EmpathyImportDialogClass; + +GType empathy_import_dialog_get_type (void); + +GtkWidget* empathy_import_dialog_new (GtkWindow *parent_window, + gboolean show_warning); G_END_DECLS diff --git a/src/empathy-import-dialog.ui b/src/empathy-import-dialog.ui index 38ba434e4..ce7a56a74 100644 --- a/src/empathy-import-dialog.ui +++ b/src/empathy-import-dialog.ui @@ -1,73 +1,29 @@ <?xml version="1.0"?> -<!--Generated with glade3 3.4.5 on Fri Oct 17 11:01:30 2008 --> <interface> - <object class="GtkDialog" id="import_dialog"> - <property name="border_width">5</property> - <property name="title" translatable="yes">Import Accounts</property> - <property name="modal">True</property> - <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property> - <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> - <property name="has_separator">False</property> - <child internal-child="vbox"> - <object class="GtkVBox" id="dialog-vbox1"> + <!-- interface-requires gtk+ 2.12 --> + <!-- interface-naming-policy toplevel-contextual --> + <object class="GtkVBox" id="widget_vbox"> + <property name="visible">True</property> + <property name="spacing">2</property> + <child> + <object class="GtkScrolledWindow" id="scrolledwindow17"> <property name="visible">True</property> - <property name="spacing">2</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">never</property> + <property name="vscrollbar_policy">automatic</property> + <property name="shadow_type">in</property> <child> - <object class="GtkScrolledWindow" id="scrolledwindow17"> + <object class="GtkTreeView" id="treeview"> + <property name="height_request">200</property> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="hscrollbar_policy">GTK_POLICY_NEVER</property> - <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <property name="shadow_type">GTK_SHADOW_IN</property> - <child> - <object class="GtkTreeView" id="treeview"> - <property name="height_request">200</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="enable_search">False</property> - </object> - </child> + <property name="enable_search">False</property> </object> - <packing> - <property name="position">1</property> - </packing> - </child> - <child internal-child="action_area"> - <object class="GtkHButtonBox" id="dialog-action_area1"> - <property name="visible">True</property> - <property name="layout_style">GTK_BUTTONBOX_END</property> - <child> - <object class="GtkButton" id="button_cancel"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="label">gtk-cancel</property> - <property name="use_stock">True</property> - </object> - </child> - <child> - <object class="GtkButton" id="button_ok"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="label">gtk-ok</property> - <property name="use_stock">True</property> - </object> - <packing> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="pack_type">GTK_PACK_END</property> - </packing> </child> </object> + <packing> + <property name="position">1</property> + </packing> </child> - <action-widgets> - <action-widget response="0">button_cancel</action-widget> - <action-widget response="-5">button_ok</action-widget> - </action-widgets> </object> </interface> diff --git a/src/empathy-import-mc4-accounts.c b/src/empathy-import-mc4-accounts.c new file mode 100644 index 000000000..968293bd2 --- /dev/null +++ b/src/empathy-import-mc4-accounts.c @@ -0,0 +1,531 @@ +/* + * Copyright (C) 2009 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: Arnaud Maillet <arnaud.maillet@collabora.co.uk> + */ + +#include <stdio.h> +#include <string.h> +#include <glib.h> +#include <glib/gi18n.h> +#include <gconf/gconf-client.h> +#include <telepathy-glib/util.h> +#include <telepathy-glib/defs.h> +#include <dbus/dbus-protocol.h> +#include <gnome-keyring.h> +#include <libempathy/empathy-account-manager.h> +#include <libempathy/empathy-account-settings.h> +#include <libempathy/empathy-connection-managers.h> + +#include "empathy-import-mc4-accounts.h" + +#define DEBUG_FLAG EMPATHY_DEBUG_IMPORT_MC4_ACCOUNTS +#include <libempathy/empathy-debug.h> + +#define MC_ACCOUNTS_GCONF_BASE "/apps/telepathy/mc/accounts" +#define IMPORTED_MC4_ACCOUNTS "/apps/empathy/accounts/imported_mc4_accounts" + +typedef struct +{ + gchar *profile; + gchar *protocol; +} ProfileProtocolMapItem; + +static ProfileProtocolMapItem profile_protocol_map[] = +{ + { "ekiga", "sip" }, + { "fwd", "sip" }, + { "gtalk", "jabber" }, + { "msn-haze", "msn" }, + { "salut", "local-xmpp" }, + { "sipphone", "sip" }, + { "sofiasip", "sip" }, +}; + +typedef struct { + gchar *account_name; + gboolean enable; +} Misc; + +static gchar * +_account_name_from_key (const gchar *key) +{ + guint base_len = strlen (MC_ACCOUNTS_GCONF_BASE); + const gchar *base, *slash; + + g_assert (g_str_has_prefix (key, MC_ACCOUNTS_GCONF_BASE)); + g_assert (strlen (key) > base_len + 1); + + base = key + base_len + 1; + slash = strchr (base, '/'); + + if (slash == NULL) + return g_strdup (base); + else + return g_strndup (base, slash - base); +} + +static gchar * +_param_name_from_key (const gchar *key) +{ + const gchar *base, *slash; + gchar *account_name; + gchar *ret; + + account_name = _account_name_from_key (key); + base = strstr (key, account_name); + slash = strchr (base, '/'); + + ret = g_strdup (slash+1); + g_free (account_name); + + return ret; +} + +static gchar * +_create_default_display_name (const gchar *protocol) +{ + if (!tp_strdiff (protocol, "local-xmpp")) + return g_strdup (_("People Nearby")); + + return g_strdup_printf (_("%s account"), protocol); +} + +static const gchar * +_get_manager_for_protocol (EmpathyConnectionManagers *managers, + const gchar *protocol) +{ + GList *cms = empathy_connection_managers_get_cms (managers); + GList *l; + TpConnectionManager *haze = NULL; + TpConnectionManager *cm = NULL; + + for (l = cms; l; l = l->next) + { + TpConnectionManager *tp_cm = l->data; + + /* Only use haze if no other cm provides this protocol */ + if (!tp_strdiff (tp_connection_manager_get_name (tp_cm), "haze")) + { + haze = tp_cm; + continue; + } + + if (tp_connection_manager_has_protocol (tp_cm, protocol)) + { + cm = tp_cm; + goto out; + } + } + + if (haze != NULL && tp_connection_manager_has_protocol (haze, protocol)) + return tp_connection_manager_get_name (haze); + +out: + return cm != NULL ? tp_connection_manager_get_name (cm) : NULL; +} + +static void +_move_contents (const gchar *old, const gchar *new) +{ + GDir *source; + const gchar *f; + int ret; + + ret = g_mkdir_with_parents (new, 0777); + if (ret == -1) + return; + + source = g_dir_open (old, 0, NULL); + if (source == NULL) + return; + + while ((f = g_dir_read_name (source)) != NULL) + { + gchar *old_path; + gchar *new_path; + + old_path = g_build_path (G_DIR_SEPARATOR_S, old, f, NULL); + new_path = g_build_path (G_DIR_SEPARATOR_S, new, f, NULL); + + if (g_file_test (old_path, G_FILE_TEST_IS_DIR)) + { + _move_contents (old_path, new_path); + } + else + { + GFile *f_old, *f_new; + + f_old = g_file_new_for_path (old_path); + f_new = g_file_new_for_path (new_path); + + g_file_move (f_old, f_new, G_FILE_COPY_NONE, + NULL, NULL, NULL, NULL); + + g_object_unref (f_old); + g_object_unref (f_new); + } + + g_free (old_path); + g_free (new_path); + } + + g_dir_close (source); +} + +static void +_move_logs (EmpathyAccount *account, const gchar *account_name) +{ + gchar *old_path, *new_path, *escaped; + const gchar *name; + + name = empathy_account_get_unique_name (account); + if (g_str_has_prefix (name, TP_ACCOUNT_OBJECT_PATH_BASE)) + name += strlen (TP_ACCOUNT_OBJECT_PATH_BASE); + + escaped = g_strdelimit (g_strdup (name), "/", '_'); + new_path = g_build_path (G_DIR_SEPARATOR_S, g_get_user_data_dir (), + PACKAGE_NAME, "logs", escaped, NULL); + g_free (escaped); + + old_path = g_build_path (G_DIR_SEPARATOR_S, + g_get_home_dir (), + ".gnome2", PACKAGE_NAME, "logs", account_name, NULL); + + _move_contents (old_path, new_path); +} + +static void +_create_account_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + EmpathyAccount *account; + GError *error = NULL; + Misc *misc = (Misc *) user_data; + + if (!empathy_account_settings_apply_finish ( + EMPATHY_ACCOUNT_SETTINGS (source), result, &error)) + { + DEBUG ("Failed to create account: %s", error->message); + g_error_free (error); + goto out; + } + + DEBUG ("account created\n"); + account = empathy_account_settings_get_account ( + EMPATHY_ACCOUNT_SETTINGS (source)); + + _move_logs (account, misc->account_name); + + empathy_account_set_enabled_async (account, + misc->enable, NULL, NULL); + + g_free (misc->account_name); + g_slice_free (Misc, misc); + +out: + g_object_unref (source); +} + +static gchar * +_get_protocol_from_profile (const gchar *profile) +{ + gint i; + + DEBUG ("profile: %s\n", profile); + + for (i = 0; i < G_N_ELEMENTS (profile_protocol_map); i++) + if (!tp_strdiff (profile, profile_protocol_map[i].profile)) + return g_strdup (profile_protocol_map[i].protocol); + + return g_strdup (profile); +} + +static void +_set_password_from_keyring (EmpathyAccountSettings *settings, + const gchar *account_name, const gchar *key) +{ + GnomeKeyringResult res; + gchar *password; + GnomeKeyringPasswordSchema keyring_schema = { + GNOME_KEYRING_ITEM_GENERIC_SECRET, + { + { "account", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, + { "param", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, + { NULL, 0 } + } + }; + + res = gnome_keyring_find_password_sync (&keyring_schema, + &password, + "account", account_name, + "param", key, + NULL); + + if (res == GNOME_KEYRING_RESULT_OK) + { + empathy_account_settings_set_string (settings, key, password); + gnome_keyring_free_password (password); + } +} + +static void +_handle_entry (EmpathyAccountSettings *settings, const gchar *account_name, + const gchar *key, + GConfEntry *entry) +{ + const gchar *signature; + + signature = empathy_account_settings_get_dbus_signature (settings, key); + if (signature == NULL) + { + DEBUG ("Parameter %s is unknown", signature); + return; + } + + switch ((int)*signature) + { + case DBUS_TYPE_INT16: + case DBUS_TYPE_INT32: + { + gint v = gconf_value_get_int (gconf_entry_get_value (entry)); + empathy_account_settings_set_int32 (settings, key, v); + break; + } + case DBUS_TYPE_UINT16: + case DBUS_TYPE_UINT32: + { + gint v = gconf_value_get_int (gconf_entry_get_value (entry)); + empathy_account_settings_set_uint32 (settings, key, v); + break; + } + case DBUS_TYPE_STRING: + { + const gchar *v = gconf_value_get_string ( + gconf_entry_get_value (entry)); + + /* MC 4 would put password in the keyring and leave the password in + * gconf keyring */ + + if (!tp_strdiff (key, "password") && !tp_strdiff (v, "keyring")) + _set_password_from_keyring (settings, account_name, key); + else + empathy_account_settings_set_string (settings, key, v); + break; + } + case DBUS_TYPE_BOOLEAN: + { + gboolean v = gconf_value_get_bool ( + gconf_entry_get_value (entry)); + + empathy_account_settings_set_boolean (settings, key, v); + break; + } + default: + DEBUG ("Unsupported type in signature: %s", signature); + } +} + +static void +_recurse_account (GSList *entries, EmpathyAccountSettings *settings, + const gchar *account_name) +{ + GSList *tmp; + + for (tmp = entries; tmp != NULL; tmp = tmp->next) + { + + GConfEntry *entry; + gchar *param; + + entry = (GConfEntry *) tmp->data; + param = _param_name_from_key (gconf_entry_get_key (entry)); + + if (g_str_has_prefix (param, "param-")) + { + _handle_entry (settings, account_name, param + strlen ("param-"), + entry); + } + + g_free (param); + gconf_entry_unref (entry); + } +} + +static gboolean +import_one_account (const char *path, + EmpathyConnectionManagers *managers, + GConfClient *client) +{ + gchar *account_name = _account_name_from_key (path); + EmpathyAccountSettings *settings; + GError *error = NULL; + GSList *entries = NULL; + gchar *profile = NULL; + gchar *protocol = NULL; + const gchar *manager; + gchar *display_name; + gchar *key; + gboolean enabled = FALSE; + gboolean ret = FALSE; + Misc *misc; + + DEBUG ("Starting import of %s (%s)", path, account_name); + + key = g_strdup_printf ("%s/profile", path); + profile = gconf_client_get_string (client, key, NULL); + g_free (key); + + if (profile == NULL) + { + DEBUG ("Account is missing a profile entry\n"); + goto failed; + } + + protocol = _get_protocol_from_profile (profile); + manager = _get_manager_for_protocol (managers, protocol); + if (manager == NULL) + { + DEBUG ("No manager available for this protocol %s", protocol); + goto failed; + } + + key = g_strdup_printf ("%s/display_name", path); + display_name = gconf_client_get_string (client, key, NULL); + g_free (key); + + if (display_name == NULL) + display_name = _create_default_display_name (protocol); + + settings = empathy_account_settings_new (manager, protocol, display_name); + g_free (display_name); + + /* Bit of a hack, as we know EmpathyConnectionManagers is ready the + * EmpathyAccountSettings should be ready right away as well */ + g_assert (empathy_account_settings_is_ready (settings)); + + entries = gconf_client_all_entries (client, path, &error); + + if (entries == NULL) + { + DEBUG ("Failed to get all entries: %s\n", error->message); + g_error_free (error); + goto failed; + } + + _recurse_account (entries, settings, account_name); + + key = g_strdup_printf ("%s/enabled", path); + enabled = gconf_client_get_bool (client, key, NULL); + g_free (key); + + misc = g_slice_new (Misc); + misc->account_name = account_name; + misc->enable = enabled; + + empathy_account_settings_apply_async (settings, + _create_account_cb, misc); + ret = TRUE; + +out: + g_free (protocol); + g_free (profile); + g_slist_free (entries); + + return ret; + +failed: + DEBUG ("Failed to import %s", path); + g_free (account_name); + if (settings != NULL) + g_object_unref (settings); + goto out; +} + +gboolean +empathy_import_mc4_has_imported (void) +{ + GConfClient *client; + gboolean ret; + + client = gconf_client_get_default (); + + ret = gconf_client_get_bool (client, IMPORTED_MC4_ACCOUNTS, NULL); + g_object_unref (client); + + return ret; +} + +gboolean +empathy_import_mc4_accounts (EmpathyConnectionManagers *managers) +{ + GConfClient *client; + GError *error = NULL; + GSList *dir, *dirs = NULL; + gboolean imported_mc4_accounts; + gboolean imported = FALSE; + + g_return_val_if_fail (empathy_connection_managers_is_ready (managers), + FALSE); + + client = gconf_client_get_default (); + + imported_mc4_accounts = gconf_client_get_bool (client, + IMPORTED_MC4_ACCOUNTS, &error); + + if (error != NULL) + { + DEBUG ("Failed to get import_mc4_accounts key: %s\n", error->message); + g_error_free (error); + goto out; + } + + if (imported_mc4_accounts) + { + DEBUG ("Mc4 accounts previously imported"); + goto out; + } + + DEBUG ("MC 4 accounts are going to be imported\n"); + + dirs = gconf_client_all_dirs (client, MC_ACCOUNTS_GCONF_BASE, &error); + + if (error != NULL) + { + DEBUG ("Failed to get MC4 account dirs: %s\n", + error->message); + g_clear_error (&error); + g_object_unref (client); + goto out; + } + + for (dir = dirs; NULL != dir; dir = dir->next) + { + if (import_one_account ((gchar *) dir->data, managers, client)) + imported = TRUE; + g_free (dir->data); + } + +out: + gconf_client_set_bool (client, IMPORTED_MC4_ACCOUNTS, TRUE, NULL); + + g_slist_free (dirs); + g_object_unref (client); + return imported; +} diff --git a/src/empathy-import-mc4-accounts.h b/src/empathy-import-mc4-accounts.h new file mode 100644 index 000000000..0a30fdff7 --- /dev/null +++ b/src/empathy-import-mc4-accounts.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2009 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: Arnaud Maillet <arnaud.maillet@collabora.co.uk> + */ + +#ifndef __EMPATHY_IMPORT_MC4_ACCOUNTS_H__ +#define __EMPATHY_IMPORT_MC4_ACCOUNTS_H__ + +G_BEGIN_DECLS + +#include <libempathy/empathy-connection-managers.h> + +gboolean empathy_import_mc4_accounts (EmpathyConnectionManagers *managers); +gboolean empathy_import_mc4_has_imported (void); + +G_END_DECLS + +#endif /* __EMPATHY_IMPORT_MC4_ACCOUNTS_H__ */ diff --git a/src/empathy-import-pidgin.c b/src/empathy-import-pidgin.c index 935c022ea..23b1d84f5 100644 --- a/src/empathy-import-pidgin.c +++ b/src/empathy-import-pidgin.c @@ -22,6 +22,7 @@ #include <config.h> #include <string.h> +#include <unistd.h> #include <glib.h> #include <glib/gstdio.h> @@ -31,7 +32,7 @@ #include <telepathy-glib/util.h> #include <telepathy-glib/dbus.h> -#include "empathy-import-dialog.h" +#include "empathy-import-utils.h" #include "empathy-import-pidgin.h" #define DEBUG_FLAG EMPATHY_DEBUG_OTHER @@ -114,8 +115,7 @@ import_dialog_pidgin_parse_setting (EmpathyImportAccountData *data, /* Search for the map corresponding to setting we are parsing */ for (i = 0; i < G_N_ELEMENTS (pidgin_cm_map); i++) { - if (!tp_strdiff (mc_profile_get_protocol_name (data->profile), - pidgin_cm_map[i].protocol) && + if (!tp_strdiff (data->protocol, pidgin_cm_map[i].protocol) && !tp_strdiff (tag_name, pidgin_cm_map[i].pidgin_name)) { item = pidgin_cm_map + i; @@ -199,23 +199,26 @@ empathy_import_pidgin_load (void) if (!tp_strdiff ((gchar *) child->name, PIDGIN_ACCOUNT_TAG_PROTOCOL)) { - gchar *content; + xmlChar *content; const gchar *protocol; - protocol = content = (gchar *) xmlNodeGetContent (child); + content = xmlNodeGetContent (child); + + protocol = (const gchar *) content; if (g_str_has_prefix (protocol, "prpl-")) protocol += 5; if (!tp_strdiff (protocol, PIDGIN_PROTOCOL_BONJOUR)) - protocol = "salut"; + data->protocol = g_strdup ("salut"); else if (!tp_strdiff (protocol, PIDGIN_PROTOCOL_NOVELL)) - protocol = "groupwise"; + data->protocol = g_strdup ("groupwise"); + else + data->protocol = g_strdup (protocol); - data->profile = mc_profile_lookup (protocol); - g_free (content); + xmlFree (content); - if (data->profile == NULL) + if (data->protocol == NULL) break; } @@ -240,8 +243,7 @@ empathy_import_pidgin_load (void) username = name; /* Split "username@server" if it is an IRC account */ - if (strstr (name, "@") && !tp_strdiff ( - mc_profile_get_protocol_name (data->profile), "irc")) + if (strstr (name, "@") && !tp_strdiff (data->protocol, "irc")) { nick_server = g_strsplit (name, "@", 2); username = nick_server[0]; @@ -287,12 +289,11 @@ empathy_import_pidgin_load (void) /* If we have the needed settings, add the account data to the list, * otherwise free the data */ - if (data->profile != NULL && g_hash_table_size (data->settings) > 0) + if (data->protocol != NULL && g_hash_table_size (data->settings) > 0) { /* Special-case XMPP: * http://bugzilla.gnome.org/show_bug.cgi?id=579992 */ - if (!tp_strdiff ( - mc_profile_get_protocol_name (data->profile), "jabber")) + if (!tp_strdiff (data->protocol, "jabber")) { if (EMP_STR_EMPTY (tp_asv_get_string (data->settings, "server"))) { diff --git a/src/empathy-import-utils.c b/src/empathy-import-utils.c new file mode 100644 index 000000000..f84b20609 --- /dev/null +++ b/src/empathy-import-utils.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2009 Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: Jonny Lamb <jonny.lamb@collabora.co.uk> + * Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> + */ + +#include <telepathy-glib/util.h> + +#include <libempathy/empathy-utils.h> + +#include "empathy-import-utils.h" +#include "empathy-import-pidgin.h" + +EmpathyImportAccountData * +empathy_import_account_data_new (const gchar *source) +{ + EmpathyImportAccountData *data; + + g_return_val_if_fail (!EMP_STR_EMPTY (source), NULL); + + data = g_slice_new0 (EmpathyImportAccountData); + data->settings = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, + (GDestroyNotify) tp_g_value_slice_free); + data->source = g_strdup (source); + data->protocol = NULL; + data->connection_manager = NULL; + + return data; +} + +void +empathy_import_account_data_free (EmpathyImportAccountData *data) +{ + if (data == NULL) + return; + if (data->protocol != NULL) + g_free (data->protocol); + if (data->connection_manager != NULL) + g_free (data->connection_manager); + if (data->settings != NULL) + g_hash_table_destroy (data->settings); + if (data->source != NULL) + g_free (data->source); + + g_slice_free (EmpathyImportAccountData, data); +} + +gboolean +empathy_import_accounts_to_import (void) +{ + return empathy_import_pidgin_accounts_to_import (); +} + +GList * +empathy_import_accounts_load (EmpathyImportApplication id) +{ + if (id == EMPATHY_IMPORT_APPLICATION_PIDGIN) + return empathy_import_pidgin_load (); + + return empathy_import_pidgin_load (); +} diff --git a/src/empathy-import-utils.h b/src/empathy-import-utils.h new file mode 100644 index 000000000..8c971a04d --- /dev/null +++ b/src/empathy-import-utils.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2009 Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: Jonny Lamb <jonny.lamb@collabora.co.uk> + * Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> + */ + +#ifndef __EMPATHY_IMPORT_UTILS_H__ +#define __EMPATHY_IMPORT_UTILS_H__ + +#include <glib.h> + +G_BEGIN_DECLS + +typedef struct +{ + /* Table mapping CM param string to a GValue */ + GHashTable *settings; + /* Protocol name */ + gchar *protocol; + /* Connection manager name */ + gchar *connection_manager; + /* The name of the account import source */ + gchar *source; +} EmpathyImportAccountData; + +typedef enum { + EMPATHY_IMPORT_APPLICATION_ALL = 0, + EMPATHY_IMPORT_APPLICATION_PIDGIN, + EMPATHY_IMPORT_APPLICATION_INVALID +} EmpathyImportApplication; + +EmpathyImportAccountData *empathy_import_account_data_new ( + const gchar *source); +void empathy_import_account_data_free (EmpathyImportAccountData *data); + +gboolean empathy_import_accounts_to_import (void); +GList *empathy_import_accounts_load (EmpathyImportApplication id); + +G_END_DECLS + +#endif /* __EMPATHY_IMPORT_UTILS_H__ */ diff --git a/src/empathy-import-widget.c b/src/empathy-import-widget.c new file mode 100644 index 000000000..17f196229 --- /dev/null +++ b/src/empathy-import-widget.c @@ -0,0 +1,516 @@ +/* + * Copyright (C) 2008-2009 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: Jonny Lamb <jonny.lamb@collabora.co.uk> + * Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> + */ + +/* empathy-import-widget.c */ + +#include "empathy-import-dialog.h" +#include "empathy-import-widget.h" +#include "empathy-import-pidgin.h" + +#define DEBUG_FLAG EMPATHY_DEBUG_OTHER +#include <libempathy/empathy-debug.h> +#include <libempathy/empathy-account.h> +#include <libempathy/empathy-account-manager.h> +#include <libempathy/empathy-connection-managers.h> +#include <libempathy/empathy-utils.h> + +#include <libempathy-gtk/empathy-ui-utils.h> + +#include <telepathy-glib/util.h> + +#include <glib/gi18n.h> + +G_DEFINE_TYPE (EmpathyImportWidget, empathy_import_widget, G_TYPE_OBJECT) + +#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyImportWidget) + +enum +{ + COL_IMPORT = 0, + COL_PROTOCOL, + COL_NAME, + COL_SOURCE, + COL_ACCOUNT_DATA, + COL_COUNT +}; + +enum { + PROP_APPLICATION_ID = 1 +}; + +typedef struct { + GtkWidget *vbox; + GtkWidget *treeview; + + GList *accounts; + EmpathyImportApplication app_id; + + EmpathyConnectionManagers *cms; + + gboolean dispose_run; +} EmpathyImportWidgetPriv; + +static gboolean +import_widget_account_id_in_list (GList *accounts, + const gchar *account_id) +{ + GList *l; + + for (l = accounts; l; l = l->next) + { + EmpathyAccount *account = l->data; + const gchar *account_string; + GValue *value; + gboolean result; + const GHashTable *parameters; + + parameters = empathy_account_get_parameters (account); + + value = g_hash_table_lookup ((GHashTable *) parameters, "account"); + + if (value == NULL) + continue; + + account_string = g_value_get_string (value); + + result = tp_strdiff (account_string, account_id); + + if (!result) + return TRUE; + } + + return FALSE; +} + +static gboolean +protocol_is_supported (EmpathyImportWidget *self, + EmpathyImportAccountData *data) +{ + EmpathyImportWidgetPriv *priv = GET_PRIV (self); + GList *cms = empathy_connection_managers_get_cms (priv->cms); + GList *l; + gboolean proto_is_supported = FALSE; + + for (l = cms; l; l = l->next) + { + TpConnectionManager *tp_cm = l->data; + const gchar *cm_name = tp_connection_manager_get_name (tp_cm); + if (tp_connection_manager_has_protocol (tp_cm, + (const gchar*) data->protocol)) + { + data->connection_manager = g_strdup (cm_name); + proto_is_supported = TRUE; + break; + } + } + + return proto_is_supported; +} + +static void +import_widget_add_accounts_to_model (EmpathyImportWidget *self) +{ + GtkTreeModel *model; + GtkTreeIter iter; + GList *l; + EmpathyImportWidgetPriv *priv = GET_PRIV (self); + EmpathyAccountManager *manager = empathy_account_manager_dup_singleton (); + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview)); + + for (l = priv->accounts; l; l = l->next) + { + GValue *value; + EmpathyImportAccountData *data = l->data; + gboolean import; + GList *accounts; + + if (!protocol_is_supported (self, data)) + continue; + + value = g_hash_table_lookup (data->settings, "account"); + + accounts = empathy_account_manager_dup_accounts (manager); + + /* Only set the "Import" cell to be active if there isn't already an + * account set up with the same account id. */ + import = !import_widget_account_id_in_list (accounts, + g_value_get_string (value)); + + g_list_foreach (accounts, (GFunc) g_object_unref, NULL); + g_list_free (accounts); + + gtk_list_store_append (GTK_LIST_STORE (model), &iter); + + gtk_list_store_set (GTK_LIST_STORE (model), &iter, + COL_IMPORT, import, + COL_PROTOCOL, data->protocol, + COL_NAME, g_value_get_string (value), + COL_SOURCE, data->source, + COL_ACCOUNT_DATA, data, + -1); + } + + g_object_unref (manager); +} + +static void +import_widget_create_account_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + EmpathyAccount *account; + GError *error = NULL; + EmpathyImportWidget *self = user_data; + + account = empathy_account_manager_create_account_finish ( + EMPATHY_ACCOUNT_MANAGER (source), result, &error); + + if (account == NULL) + { + DEBUG ("Failed to create account: %s", + error ? error->message : "No error given"); + g_clear_error (&error); + return; + } + + DEBUG ("account created\n"); + + g_object_unref (self); +} + +static void +import_widget_add_account (EmpathyImportWidget *self, + EmpathyImportAccountData *data) +{ + EmpathyAccountManager *account_manager; + gchar *display_name; + GHashTable *properties; + GValue *username; + + account_manager = empathy_account_manager_dup_singleton (); + + DEBUG ("connection_manager: %s\n", data->connection_manager); + + /* Set the display name of the account */ + username = g_hash_table_lookup (data->settings, "account"); + display_name = g_strdup_printf ("%s (%s)", + data->protocol, + g_value_get_string (username)); + + DEBUG ("display name: %s\n", display_name); + + properties = g_hash_table_new (NULL, NULL); + + empathy_account_manager_create_account_async (account_manager, + (const gchar*) data->connection_manager, data->protocol, display_name, + data->settings, properties, import_widget_create_account_cb, + g_object_ref (self)); + + g_hash_table_unref (properties); + g_free (display_name); + g_object_unref (account_manager); +} + +static gboolean +import_widget_tree_model_foreach (GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + gpointer user_data) +{ + gboolean to_import; + EmpathyImportAccountData *data; + EmpathyImportWidget *self = user_data; + + gtk_tree_model_get (model, iter, + COL_IMPORT, &to_import, + COL_ACCOUNT_DATA, &data, + -1); + + if (to_import) + import_widget_add_account (self, data); + + return FALSE; +} + +static void +import_widget_cell_toggled_cb (GtkCellRendererToggle *cell_renderer, + const gchar *path_str, + EmpathyImportWidget *self) +{ + GtkTreeModel *model; + GtkTreeIter iter; + GtkTreePath *path; + EmpathyImportWidgetPriv *priv = GET_PRIV (self); + + path = gtk_tree_path_new_from_string (path_str); + model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview)); + + gtk_tree_model_get_iter (model, &iter, path); + + gtk_list_store_set (GTK_LIST_STORE (model), &iter, + COL_IMPORT, !gtk_cell_renderer_toggle_get_active (cell_renderer), + -1); + + gtk_tree_path_free (path); +} + +static void +import_widget_set_up_account_list (EmpathyImportWidget *self) +{ + EmpathyImportWidgetPriv *priv = GET_PRIV (self); + GtkListStore *store; + GtkTreeView *view; + GtkTreeViewColumn *column; + GtkCellRenderer *cell; + + store = gtk_list_store_new (COL_COUNT, G_TYPE_BOOLEAN, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER); + + gtk_tree_view_set_model (GTK_TREE_VIEW (priv->treeview), + GTK_TREE_MODEL (store)); + + g_object_unref (store); + + view = GTK_TREE_VIEW (priv->treeview); + gtk_tree_view_set_headers_visible (view, TRUE); + + /* Import column */ + cell = gtk_cell_renderer_toggle_new (); + gtk_tree_view_insert_column_with_attributes (view, -1, + /* Translators: this is the header of a treeview column */ + _("Import"), cell, + "active", COL_IMPORT, + NULL); + + g_signal_connect (cell, "toggled", + G_CALLBACK (import_widget_cell_toggled_cb), self); + + /* Protocol column */ + column = gtk_tree_view_column_new (); + gtk_tree_view_column_set_title (column, _("Protocol")); + gtk_tree_view_column_set_expand (column, TRUE); + gtk_tree_view_append_column (view, column); + + cell = gtk_cell_renderer_text_new (); + g_object_set (cell, "editable", FALSE, NULL); + gtk_tree_view_column_pack_start (column, cell, TRUE); + gtk_tree_view_column_add_attribute (column, cell, "text", COL_PROTOCOL); + + /* Account column */ + column = gtk_tree_view_column_new (); + gtk_tree_view_column_set_title (column, _("Account")); + gtk_tree_view_column_set_expand (column, TRUE); + gtk_tree_view_append_column (view, column); + + cell = gtk_cell_renderer_text_new (); + g_object_set (cell, "editable", FALSE, NULL); + gtk_tree_view_column_pack_start (column, cell, TRUE); + gtk_tree_view_column_add_attribute (column, cell, "text", COL_NAME); + + if (priv->app_id == EMPATHY_IMPORT_APPLICATION_ALL) + { + /* Source column */ + column = gtk_tree_view_column_new (); + gtk_tree_view_column_set_title (column, _("Source")); + gtk_tree_view_column_set_expand (column, TRUE); + gtk_tree_view_append_column (view, column); + + cell = gtk_cell_renderer_text_new (); + g_object_set (cell, "editable", FALSE, NULL); + gtk_tree_view_column_pack_start (column, cell, TRUE); + gtk_tree_view_column_add_attribute (column, cell, "text", COL_SOURCE); + } + + import_widget_add_accounts_to_model (self); +} + +static void +import_widget_cms_ready_cb (EmpathyConnectionManagers *cms, + GParamSpec *pspec, + EmpathyImportWidget *self) +{ + if (empathy_connection_managers_is_ready (cms)) + import_widget_set_up_account_list (self); +} + +static void +import_widget_destroy_cb (GtkWidget *w, + EmpathyImportWidget *self) +{ + g_object_unref (self); +} + +static void +do_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + EmpathyImportWidgetPriv *priv = GET_PRIV (object); + + switch (property_id) + { + case PROP_APPLICATION_ID: + g_value_set_int (value, priv->app_id); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +do_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + EmpathyImportWidgetPriv *priv = GET_PRIV (object); + + switch (property_id) + { + case PROP_APPLICATION_ID: + priv->app_id = g_value_get_int (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +do_finalize (GObject *obj) +{ + EmpathyImportWidgetPriv *priv = GET_PRIV (obj); + + g_list_foreach (priv->accounts, (GFunc) empathy_import_account_data_free, + NULL); + g_list_free (priv->accounts); + + if (G_OBJECT_CLASS (empathy_import_widget_parent_class)->finalize != NULL) + G_OBJECT_CLASS (empathy_import_widget_parent_class)->finalize (obj); +} + +static void +do_dispose (GObject *obj) +{ + EmpathyImportWidgetPriv *priv = GET_PRIV (obj); + + if (priv->dispose_run) + return; + + priv->dispose_run = TRUE; + + if (priv->cms != NULL) + { + g_object_unref (priv->cms); + priv->cms = NULL; + } + + if (G_OBJECT_CLASS (empathy_import_widget_parent_class)->dispose != NULL) + G_OBJECT_CLASS (empathy_import_widget_parent_class)->dispose (obj); +} + +static void +do_constructed (GObject *obj) +{ + EmpathyImportWidget *self = EMPATHY_IMPORT_WIDGET (obj); + EmpathyImportWidgetPriv *priv = GET_PRIV (self); + GtkBuilder *gui; + gchar *filename; + + priv->accounts = empathy_import_accounts_load (priv->app_id); + + filename = empathy_file_lookup ("empathy-import-dialog.ui", "src"); + gui = empathy_builder_get_file (filename, + "widget_vbox", &priv->vbox, + "treeview", &priv->treeview, + NULL); + + g_free (filename); + empathy_builder_unref_and_keep_widget (gui, priv->vbox); + + g_signal_connect (priv->vbox, "destroy", + G_CALLBACK (import_widget_destroy_cb), self); + + if (empathy_connection_managers_is_ready (priv->cms)) + import_widget_set_up_account_list (self); + else + g_signal_connect (priv->cms, "notify::ready", + G_CALLBACK (import_widget_cms_ready_cb), self); +} + +static void +empathy_import_widget_class_init (EmpathyImportWidgetClass *klass) +{ + GObjectClass *oclass = G_OBJECT_CLASS (klass); + GParamSpec *param_spec; + + oclass->constructed = do_constructed; + oclass->finalize = do_finalize; + oclass->dispose = do_dispose; + oclass->set_property = do_set_property; + oclass->get_property = do_get_property; + + param_spec = g_param_spec_int ("application-id", + "application-id", "The application id to import from", + 0, EMPATHY_IMPORT_APPLICATION_INVALID, EMPATHY_IMPORT_APPLICATION_ALL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (oclass, PROP_APPLICATION_ID, param_spec); + + g_type_class_add_private (klass, sizeof (EmpathyImportWidgetPriv)); +} + +static void +empathy_import_widget_init (EmpathyImportWidget *self) +{ + EmpathyImportWidgetPriv *priv = + G_TYPE_INSTANCE_GET_PRIVATE (self, EMPATHY_TYPE_IMPORT_WIDGET, + EmpathyImportWidgetPriv); + + self->priv = priv; + + priv->cms = empathy_connection_managers_dup_singleton (); +} + +EmpathyImportWidget * +empathy_import_widget_new (EmpathyImportApplication id) +{ + return g_object_new (EMPATHY_TYPE_IMPORT_WIDGET, "application-id", id, NULL); +} + +GtkWidget * +empathy_import_widget_get_widget (EmpathyImportWidget *self) +{ + EmpathyImportWidgetPriv *priv = GET_PRIV (self); + + return priv->vbox; +} + +void +empathy_import_widget_add_selected_accounts (EmpathyImportWidget *self) +{ + GtkTreeModel *model; + EmpathyImportWidgetPriv *priv = GET_PRIV (self); + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview)); + gtk_tree_model_foreach (model, import_widget_tree_model_foreach, self); +} diff --git a/src/empathy-import-widget.h b/src/empathy-import-widget.h new file mode 100644 index 000000000..48f2e1d48 --- /dev/null +++ b/src/empathy-import-widget.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2008-2009 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: Jonny Lamb <jonny.lamb@collabora.co.uk> + * Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> + */ + +/* empathy-import-widget.h */ + +#ifndef __EMPATHY_IMPORT_WIDGET_H__ +#define __EMPATHY_IMPORT_WIDGET_H__ + +#include <glib-object.h> + +#include "empathy-import-utils.h" + +G_BEGIN_DECLS + +#define EMPATHY_TYPE_IMPORT_WIDGET empathy_import_widget_get_type() +#define EMPATHY_IMPORT_WIDGET(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), EMPATHY_TYPE_IMPORT_WIDGET,\ + EmpathyImportWidget)) +#define EMPATHY_IMPORT_WIDGET_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), EMPATHY_TYPE_IMPORT_WIDGET,\ + EmpathyImportWidgetClass)) +#define EMPATHY_IS_IMPORT_WIDGET(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EMPATHY_TYPE_IMPORT_WIDGET)) +#define EMPATHY_IS_IMPORT_WIDGET_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), EMPATHY_TYPE_IMPORT_WIDGET)) +#define EMPATHY_IMPORT_WIDGET_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_IMPORT_WIDGET,\ + EmpathyImportWidgetClass)) + +typedef struct { + GObject parent; + + /* private */ + gpointer priv; +} EmpathyImportWidget; + +typedef struct { + GObjectClass parent_class; +} EmpathyImportWidgetClass; + +GType empathy_import_widget_get_type (void); + +EmpathyImportWidget* empathy_import_widget_new (EmpathyImportApplication id); + +GtkWidget * empathy_import_widget_get_widget (EmpathyImportWidget *self); + +void empathy_import_widget_add_selected_accounts (EmpathyImportWidget *self); + +G_END_DECLS + +#endif /* __EMPATHY_IMPORT_WIDGET_H__ */ diff --git a/src/empathy-main-window.c b/src/empathy-main-window.c index a600fd429..d61a05c27 100644 --- a/src/empathy-main-window.c +++ b/src/empathy-main-window.c @@ -49,8 +49,6 @@ #include <libempathy-gtk/empathy-sound.h> #include <libempathy-gtk/empathy-ui-utils.h> -#include <libmissioncontrol/mission-control.h> - #include "empathy-accounts-dialog.h" #include "empathy-main-window.h" #include "ephy-spinner.h" @@ -81,7 +79,6 @@ typedef struct { EmpathyContactListView *list_view; EmpathyContactListStore *list_store; - MissionControl *mc; EmpathyAccountManager *account_manager; EmpathyChatroomManager *chatroom_manager; EmpathyEventManager *event_manager; @@ -654,7 +651,6 @@ main_window_destroy_cb (GtkWidget *widget, g_list_free (window->actions_connected); - g_object_unref (window->mc); g_object_unref (window->account_manager); g_object_unref (window->list_store); g_hash_table_destroy (window->errors); @@ -1252,15 +1248,14 @@ empathy_main_window_show (void) gtk_action_set_visible (show_map_widget, FALSE); #endif - window->mc = empathy_mission_control_dup_singleton (); window->account_manager = empathy_account_manager_dup_singleton (); g_signal_connect (window->account_manager, "account-connection-changed", G_CALLBACK (main_window_connection_changed_cb), window); - window->errors = g_hash_table_new_full (empathy_account_hash, - empathy_account_equal, + window->errors = g_hash_table_new_full (g_direct_hash, + g_direct_equal, g_object_unref, NULL); @@ -1409,6 +1404,8 @@ empathy_main_window_show (void) main_window_update_status (window, window->account_manager); + gtk_widget_show (window->window); + return window->window; } diff --git a/src/empathy-new-chatroom-dialog.c b/src/empathy-new-chatroom-dialog.c index e16da91a7..219be371d 100644 --- a/src/empathy-new-chatroom-dialog.c +++ b/src/empathy-new-chatroom-dialog.c @@ -32,9 +32,6 @@ #include <glib/gi18n.h> #include <glib/gprintf.h> -#include <libmissioncontrol/mission-control.h> -#include <libmissioncontrol/mc-profile.h> - #include <libempathy/empathy-tp-roomlist.h> #include <libempathy/empathy-chatroom.h> #include <libempathy/empathy-utils.h> @@ -358,14 +355,16 @@ new_chatroom_dialog_update_widgets (EmpathyNewChatroomDialog *dialog) { EmpathyAccountChooser *account_chooser; EmpathyAccount *account; - McProfile *profile; const gchar *protocol; const gchar *room; account_chooser = EMPATHY_ACCOUNT_CHOOSER (dialog->account_chooser); account = empathy_account_chooser_dup_account (account_chooser); - profile = empathy_account_get_profile (account); - protocol = mc_profile_get_protocol_name (profile); + + if (account == NULL) + return; + + protocol = empathy_account_get_protocol (account); gtk_entry_set_text (GTK_ENTRY (dialog->entry_server), ""); @@ -390,7 +389,6 @@ new_chatroom_dialog_update_widgets (EmpathyNewChatroomDialog *dialog) gtk_widget_grab_focus (dialog->entry_room); g_object_unref (account); - g_object_unref (profile); } static void diff --git a/src/empathy-status-icon.c b/src/empathy-status-icon.c index bbb97f410..430c93343 100644 --- a/src/empathy-status-icon.c +++ b/src/empathy-status-icon.c @@ -314,24 +314,7 @@ status_icon_set_visibility (EmpathyStatusIcon *icon, if (!visible) { empathy_window_iconify (priv->window, priv->icon); } else { - GList *accounts; - GList *l; - gboolean one_enabled = FALSE; - empathy_window_present (GTK_WINDOW (priv->window), TRUE); - - /* Show the accounts dialog if there is no enabled accounts */ - accounts = empathy_account_manager_dup_accounts (priv->account_manager); - for (l = accounts ; l != NULL ; l = g_list_next (l)) { - one_enabled = empathy_account_is_enabled (EMPATHY_ACCOUNT (l->data)) - || one_enabled; - g_object_unref (l->data); - } - g_list_free (accounts); - if (!one_enabled) { - DEBUG ("No enabled account, Showing account dialog"); - empathy_accounts_dialog_show (GTK_WINDOW (priv->window), NULL); - } } } diff --git a/src/empathy-tube-dispatch.c b/src/empathy-tube-dispatch.c index 67db5a3a3..66efa217d 100644 --- a/src/empathy-tube-dispatch.c +++ b/src/empathy-tube-dispatch.c @@ -25,6 +25,7 @@ #include <telepathy-glib/dbus.h> #include <telepathy-glib/util.h> #include <telepathy-glib/proxy-subclass.h> +#include <telepathy-glib/interfaces.h> #include <gtk/gtk.h> #include <glib/gi18n.h> diff --git a/src/empathy.c b/src/empathy.c index 660e47cea..38fd56c54 100644 --- a/src/empathy.c +++ b/src/empathy.c @@ -1,6 +1,5 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* - * Copyright (C) 2007-2008 Collabora Ltd. + * Copyright (C) 2007-2009 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 @@ -30,6 +29,7 @@ #include <glib/gi18n.h> #include <gtk/gtk.h> #include <gdk/gdkx.h> +#include <unique/unique.h> #if HAVE_LIBCHAMPLAIN #include <clutter-gtk/clutter-gtk.h> @@ -40,14 +40,17 @@ #include <telepathy-glib/dbus.h> #include <telepathy-glib/util.h> -#include <libmissioncontrol/mission-control.h> +#include <telepathy-glib/connection-manager.h> +#include <telepathy-glib/interfaces.h> #include <libempathy/empathy-idle.h> #include <libempathy/empathy-utils.h> #include <libempathy/empathy-call-factory.h> #include <libempathy/empathy-chatroom-manager.h> +#include <libempathy/empathy-account-settings.h> #include <libempathy/empathy-connectivity.h> #include <libempathy/empathy-account-manager.h> +#include <libempathy/empathy-connection-managers.h> #include <libempathy/empathy-debugger.h> #include <libempathy/empathy-dispatcher.h> #include <libempathy/empathy-dispatch-operation.h> @@ -60,13 +63,14 @@ #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-status-icon.h" #include "empathy-call-window.h" #include "empathy-chat-window.h" #include "empathy-ft-manager.h" -#include "bacon-message-connection.h" +#include "empathy-import-mc4-accounts.h" #include "extensions/extensions.h" @@ -75,444 +79,432 @@ #include <gst/gst.h> -static BaconMessageConnection *connection = NULL; +#define COMMAND_ACCOUNTS_DIALOG 1 static void dispatch_cb (EmpathyDispatcher *dispatcher, - EmpathyDispatchOperation *operation, - gpointer user_data) + EmpathyDispatchOperation *operation, + gpointer user_data) { - GQuark channel_type; - - channel_type = empathy_dispatch_operation_get_channel_type_id (operation); - - if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_TEXT) { - EmpathyTpChat *tp_chat; - EmpathyChat *chat = NULL; - const gchar *id; - - tp_chat = EMPATHY_TP_CHAT ( - empathy_dispatch_operation_get_channel_wrapper (operation)); - - id = empathy_tp_chat_get_id (tp_chat); - if (!id) { - EmpathyContact *contact; - - contact = empathy_tp_chat_get_remote_contact (tp_chat); - if (contact) { - id = empathy_contact_get_id (contact); - } - } - - if (id) { - EmpathyAccountManager *manager; - TpConnection *connection; - EmpathyAccount *account; - - manager = empathy_account_manager_dup_singleton (); - connection = empathy_tp_chat_get_connection (tp_chat); - account = empathy_account_manager_get_account (manager, - connection); - chat = empathy_chat_window_find_chat (account, id); - g_object_unref (manager); - } - - if (chat) { - empathy_chat_set_tp_chat (chat, tp_chat); - } else { - chat = empathy_chat_new (tp_chat); - } - - empathy_chat_window_present_chat (chat); - - empathy_dispatch_operation_claim (operation); - } else if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_STREAMED_MEDIA) { - EmpathyCallFactory *factory; - - factory = empathy_call_factory_get (); - empathy_call_factory_claim_channel (factory, operation); - } else if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_FILE_TRANSFER) { - EmpathyFTFactory *factory; - - factory = empathy_ft_factory_dup_singleton (); - - /* if the operation is not incoming, don't claim it, - * as it might have been triggered by another client, and - * we are observing it. - */ - if (empathy_dispatch_operation_is_incoming (operation)) { - empathy_ft_factory_claim_channel (factory, operation); - } - } + GQuark channel_type; + + channel_type = empathy_dispatch_operation_get_channel_type_id (operation); + + if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_TEXT) + { + EmpathyTpChat *tp_chat; + EmpathyChat *chat = NULL; + const gchar *id; + + tp_chat = EMPATHY_TP_CHAT + (empathy_dispatch_operation_get_channel_wrapper (operation)); + + id = empathy_tp_chat_get_id (tp_chat); + if (!id) + { + EmpathyContact *contact; + + contact = empathy_tp_chat_get_remote_contact (tp_chat); + if (contact) + id = empathy_contact_get_id (contact); + } + + if (id) + { + EmpathyAccountManager *manager; + TpConnection *connection; + EmpathyAccount *account; + + manager = empathy_account_manager_dup_singleton (); + connection = empathy_tp_chat_get_connection (tp_chat); + account = empathy_account_manager_get_account_for_connection ( + manager, connection); + chat = empathy_chat_window_find_chat (account, id); + g_object_unref (manager); + } + + if (chat) + empathy_chat_set_tp_chat (chat, tp_chat); + else + chat = empathy_chat_new (tp_chat); + + empathy_chat_window_present_chat (chat); + + empathy_dispatch_operation_claim (operation); + } + else if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_STREAMED_MEDIA) + { + EmpathyCallFactory *factory; + + factory = empathy_call_factory_get (); + empathy_call_factory_claim_channel (factory, operation); + } + else if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_FILE_TRANSFER) + { + EmpathyFTFactory *factory; + + factory = empathy_ft_factory_dup_singleton (); + + /* if the operation is not incoming, don't claim it, + * as it might have been triggered by another client, and + * we are observing it. + */ + if (empathy_dispatch_operation_is_incoming (operation)) + empathy_ft_factory_claim_channel (factory, operation); + } } -static void -service_ended_cb (MissionControl *mc, - gpointer user_data) +/* Salut account creation */ +static gboolean +should_create_salut_account (void) { - DEBUG ("Mission Control stopped"); + EmpathyAccountManager *manager; + gboolean salut_created = FALSE; + GList *accounts, *l; + + /* Check if we already created a salut account */ + empathy_conf_get_bool (empathy_conf_get (), + EMPATHY_PREFS_SALUT_ACCOUNT_CREATED, + &salut_created); + + if (salut_created) + { + DEBUG ("Gconf says we already created a salut account once"); + return FALSE; + } + + manager = empathy_account_manager_dup_singleton (); + accounts = empathy_account_manager_dup_accounts (manager); + + for (l = accounts; l != NULL; l = g_list_next (l)) + { + EmpathyAccount *account = EMPATHY_ACCOUNT (l->data); + + if (!tp_strdiff (empathy_account_get_protocol (account), "local-xmpp")) + salut_created = TRUE; + + g_object_unref (account); + } + + g_object_unref (manager); + + if (salut_created) + { + DEBUG ("Existing salut account already exists, flagging so in gconf"); + empathy_conf_set_bool (empathy_conf_get (), + EMPATHY_PREFS_SALUT_ACCOUNT_CREATED, + TRUE); + } + + return !salut_created; } static void -operation_error_cb (MissionControl *mc, - guint operation_id, - guint error_code, - gpointer user_data) +salut_account_created (GObject *source, + GAsyncResult *result, + gpointer user_data) { - const gchar *message; - - switch (error_code) { - case MC_DISCONNECTED_ERROR: - message = "Disconnected"; - break; - case MC_INVALID_HANDLE_ERROR: - message = "Invalid handle"; - break; - case MC_NO_MATCHING_CONNECTION_ERROR: - message = "No matching connection"; - break; - case MC_INVALID_ACCOUNT_ERROR: - message = "Invalid account"; - break; - case MC_PRESENCE_FAILURE_ERROR: - message = "Presence failure"; - break; - case MC_NO_ACCOUNTS_ERROR: - message = "No accounts"; - break; - case MC_NETWORK_ERROR: - message = "Network error"; - break; - case MC_CONTACT_DOES_NOT_SUPPORT_VOICE_ERROR: - message = "Contact does not support voice"; - break; - case MC_LOWMEM_ERROR: - message = "Lowmem"; - break; - case MC_CHANNEL_REQUEST_GENERIC_ERROR: - message = "Channel request generic error"; - break; - case MC_CHANNEL_BANNED_ERROR: - message = "Channel banned"; - break; - case MC_CHANNEL_FULL_ERROR: - message = "Channel full"; - break; - case MC_CHANNEL_INVITE_ONLY_ERROR: - message = "Channel invite only"; - break; - default: - message = "Unknown error code"; - } - - DEBUG ("Error during operation %d: %s", operation_id, message); + EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (source); + EmpathyAccount *account; + GError *error = NULL; + + if (!empathy_account_settings_apply_finish (settings, result, &error)) + { + DEBUG ("Failed to create salut account: %s", error->message); + g_error_free (error); + return; + } + + account = empathy_account_settings_get_account (settings); + + empathy_account_set_enabled_async (account, TRUE, NULL, NULL); + empathy_conf_set_bool (empathy_conf_get (), + EMPATHY_PREFS_SALUT_ACCOUNT_CREATED, + TRUE); } static void use_conn_notify_cb (EmpathyConf *conf, - const gchar *key, - gpointer user_data) + const gchar *key, + gpointer user_data) { - EmpathyConnectivity *connectivity = user_data; - gboolean use_conn; + EmpathyConnectivity *connectivity = user_data; + gboolean use_conn; - if (empathy_conf_get_bool (conf, key, &use_conn)) { - empathy_connectivity_set_use_conn (connectivity, use_conn); - } + if (empathy_conf_get_bool (conf, key, &use_conn)) + { + empathy_connectivity_set_use_conn (connectivity, use_conn); + } } static void -create_salut_account (void) +create_salut_account_if_needed (EmpathyConnectionManagers *managers) { - McProfile *profile; - McProtocol *protocol; - gboolean salut_created = FALSE; - EmpathyAccount *account; - EmpathyAccountManager *account_manager; - GList *accounts; - EBook *book; - EContact *contact; - gchar *nickname = NULL; - gchar *first_name = NULL; - gchar *last_name = NULL; - gchar *email = NULL; - gchar *jid = NULL; - GError *error = NULL; - - /* Check if we already created a salut account */ - empathy_conf_get_bool (empathy_conf_get (), - EMPATHY_PREFS_SALUT_ACCOUNT_CREATED, - &salut_created); - if (salut_created) { - return; - } - - DEBUG ("Try to add a salut account..."); - - /* Check if the salut CM is installed */ - profile = mc_profile_lookup ("salut"); - if (!profile) { - DEBUG ("No salut profile"); - return; - } - protocol = mc_profile_get_protocol (profile); - if (!protocol) { - DEBUG ("Salut not installed"); - g_object_unref (profile); - return; - } - g_object_unref (protocol); - - /* Get self EContact from EDS */ - if (!e_book_get_self (&contact, &book, &error)) { - DEBUG ("Failed to get self econtact: %s", - error ? error->message : "No error given"); - g_clear_error (&error); - g_object_unref (profile); - return; - } - - empathy_conf_set_bool (empathy_conf_get (), - EMPATHY_PREFS_SALUT_ACCOUNT_CREATED, - TRUE); - - /* Check if there is already a salut account */ - accounts = mc_accounts_list_by_profile (profile); - if (accounts) { - DEBUG ("There is already a salut account"); - mc_accounts_list_free (accounts); - g_object_unref (profile); - return; - } - - account_manager = empathy_account_manager_dup_singleton (); - account = empathy_account_manager_create (account_manager, profile); - empathy_account_set_display_name (account, _("People nearby")); - g_object_unref (account_manager); - - nickname = e_contact_get (contact, E_CONTACT_NICKNAME); - first_name = e_contact_get (contact, E_CONTACT_GIVEN_NAME); - last_name = e_contact_get (contact, E_CONTACT_FAMILY_NAME); - email = e_contact_get (contact, E_CONTACT_EMAIL_1); - jid = e_contact_get (contact, E_CONTACT_IM_JABBER_HOME_1); - - if (!tp_strdiff (nickname, "nickname")) { - g_free (nickname); - nickname = NULL; - } - - DEBUG ("Salut account created:\nnickname=%s\nfirst-name=%s\n" - "last-name=%s\nemail=%s\njid=%s\n", - nickname, first_name, last_name, email, jid); - - empathy_account_set_param_string (account, "nickname", nickname ? nickname : ""); - empathy_account_set_param_string (account, "first-name", first_name ? first_name : ""); - empathy_account_set_param_string (account, "last-name", last_name ? last_name : ""); - empathy_account_set_param_string (account, "email", email ? email : ""); - empathy_account_set_param_string (account, "jid", jid ? jid : ""); - - g_free (nickname); - g_free (first_name); - g_free (last_name); - g_free (email); - g_free (jid); - g_object_unref (account); - g_object_unref (profile); - g_object_unref (contact); - g_object_unref (book); + EmpathyAccountSettings *settings; + TpConnectionManager *manager; + const TpConnectionManagerProtocol *protocol; + EBook *book; + EContact *contact; + gchar *nickname = NULL; + gchar *first_name = NULL; + gchar *last_name = NULL; + gchar *email = NULL; + gchar *jid = NULL; + GError *error = NULL; + + + if (!should_create_salut_account ()) + return; + + manager = empathy_connection_managers_get_cm (managers, "salut"); + if (manager == NULL) + { + DEBUG ("Salut not installed, not making a salut account"); + return; + } + + protocol = tp_connection_manager_get_protocol (manager, "local-xmpp"); + if (protocol == NULL) + { + DEBUG ("Salut doesn't support local-xmpp!!"); + return; + } + + DEBUG ("Trying to add a salut account..."); + + /* Get self EContact from EDS */ + if (!e_book_get_self (&contact, &book, &error)) + { + DEBUG ("Failed to get self econtact: %s", + error ? error->message : "No error given"); + g_clear_error (&error); + return; + } + + settings = empathy_account_settings_new ("salut", "local-xmpp", + _("People nearby")); + + nickname = e_contact_get (contact, E_CONTACT_NICKNAME); + first_name = e_contact_get (contact, E_CONTACT_GIVEN_NAME); + last_name = e_contact_get (contact, E_CONTACT_FAMILY_NAME); + email = e_contact_get (contact, E_CONTACT_EMAIL_1); + jid = e_contact_get (contact, E_CONTACT_IM_JABBER_HOME_1); + + if (!tp_strdiff (nickname, "nickname")) + { + g_free (nickname); + nickname = NULL; + } + + DEBUG ("Salut account created:\nnickname=%s\nfirst-name=%s\n" + "last-name=%s\nemail=%s\njid=%s\n", + nickname, first_name, last_name, email, jid); + + empathy_account_settings_set_string (settings, + "nickname", nickname ? nickname : ""); + empathy_account_settings_set_string (settings, + "first-name", first_name ? first_name : ""); + empathy_account_settings_set_string (settings, + "last-name", last_name ? last_name : ""); + empathy_account_settings_set_string (settings, "email", email ? email : ""); + empathy_account_settings_set_string (settings, "jid", jid ? jid : ""); + + empathy_account_settings_apply_async (settings, + salut_account_created, NULL); + + g_free (nickname); + g_free (first_name); + g_free (last_name); + g_free (email); + g_free (jid); + g_object_unref (settings); + g_object_unref (contact); + g_object_unref (book); } static void -migrate_config_to_xdg_dir (void) +maybe_show_account_assistant (void) { - gchar *xdg_dir, *old_dir, *xdg_filename, *old_filename; - int i; - GFile *xdg_file, *old_file; - static const gchar* filenames[] = { - "geometry.ini", - "irc-networks.xml", - "chatrooms.xml", - "contact-groups.xml", - "status-presets.xml", - "accels.txt", - NULL - }; - - xdg_dir = g_build_filename (g_get_user_config_dir (), PACKAGE_NAME, NULL); - if (g_file_test (xdg_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) { - /* xdg config dir already exists */ - g_free (xdg_dir); - return; - } - - old_dir = g_build_filename (g_get_home_dir (), ".gnome2", PACKAGE_NAME, NULL); - if (!g_file_test (old_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) { - /* old config dir didn't exist */ - g_free (xdg_dir); - g_free (old_dir); - return; - } - - if (g_mkdir_with_parents (xdg_dir, (S_IRUSR | S_IWUSR | S_IXUSR)) == -1) { - DEBUG ("Failed to create configuration directory; aborting migration"); - g_free (xdg_dir); - g_free (old_dir); - return; - } - - for (i = 0; filenames[i]; i++) { - old_filename = g_build_filename (old_dir, filenames[i], NULL); - if (!g_file_test (old_filename, G_FILE_TEST_EXISTS)) { - g_free (old_filename); - continue; - } - xdg_filename = g_build_filename (xdg_dir, filenames[i], NULL); - old_file = g_file_new_for_path (old_filename); - xdg_file = g_file_new_for_path (xdg_filename); - if (!g_file_move (old_file, xdg_file, G_FILE_COPY_NONE, - NULL, NULL, NULL, NULL)) { - DEBUG ("Failed to migrate %s", filenames[i]); - } - g_free (old_filename); - g_free (xdg_filename); - g_object_unref (old_file); - g_object_unref (xdg_file); - } - - g_free (xdg_dir); - g_free (old_dir); + EmpathyAccountManager *manager; + manager = empathy_account_manager_dup_singleton (); + + if (empathy_account_manager_get_count (manager) == 0) + { + GtkWidget * assistant = empathy_account_assistant_new ( + GTK_WINDOW (empathy_main_window_get ())); + gtk_window_present (GTK_WINDOW (assistant)); + } } -/* The code that handles single-instance and startup notification is - * copied from gedit. - * - * Copyright (C) 2005 - Paolo Maggi - */ -static void -on_bacon_message_received (const char *message, - gpointer data) +static gboolean +check_connection_managers_ready (EmpathyConnectionManagers *managers) { - GtkWidget *window = data; - guint32 startup_timestamp; - - g_return_if_fail (message != NULL); - - DEBUG ("Other instance launched, presenting the main window. message='%s'", - message); - - if (strcmp (message, "accounts") == 0) { - /* accounts dialog requested */ - empathy_accounts_dialog_show (GTK_WINDOW (window), NULL); - } else { - startup_timestamp = atoi (message); - - /* Set the proper interaction time on the window. - * Fall back to roundtripping to the X server when we - * don't have the timestamp, e.g. when launched from - * terminal. We also need to make sure that the window - * has been realized otherwise it will not work. lame. */ - if (startup_timestamp == 0) { - /* Work if launched from the terminal */ - DEBUG ("Using X server timestamp as a fallback"); - - if (!GTK_WIDGET_REALIZED (window)) { - gtk_widget_realize (GTK_WIDGET (window)); - } - - startup_timestamp = gdk_x11_get_server_time (gtk_widget_get_window (window)); - } - - gtk_window_present_with_time (GTK_WINDOW (window), startup_timestamp); - } + if (empathy_connection_managers_is_ready (managers)) + { + if (!empathy_import_mc4_accounts (managers)) + maybe_show_account_assistant (); + + create_salut_account_if_needed (managers); + g_object_unref (managers); + managers = NULL; + return TRUE; + } + return FALSE; } -static guint32 -get_startup_timestamp () +static void +connection_managers_ready_cb (EmpathyConnectionManagers *managers, + GParamSpec *spec, + gpointer user_data) { - const gchar *startup_id_env; - gchar *startup_id = NULL; - gchar *time_str; - gchar *end; - gulong retval = 0; - - /* we don't unset the env, since startup-notification - * may still need it */ - startup_id_env = g_getenv ("DESKTOP_STARTUP_ID"); - if (startup_id_env == NULL) { - goto out; - } - - startup_id = g_strdup (startup_id_env); - - time_str = g_strrstr (startup_id, "_TIME"); - if (time_str == NULL) { - goto out; - } - - errno = 0; - - /* Skip past the "_TIME" part */ - time_str += 5; - - retval = strtoul (time_str, &end, 0); - if (end == time_str || errno != 0) - retval = 0; + check_connection_managers_ready (managers); +} - out: - g_free (startup_id); +static void +migrate_config_to_xdg_dir (void) +{ + gchar *xdg_dir, *old_dir, *xdg_filename, *old_filename; + int i; + GFile *xdg_file, *old_file; + static const gchar* filenames[] = { + "geometry.ini", + "irc-networks.xml", + "chatrooms.xml", + "contact-groups.xml", + "status-presets.xml", + "accels.txt", + NULL + }; + + xdg_dir = g_build_filename (g_get_user_config_dir (), PACKAGE_NAME, NULL); + if (g_file_test (xdg_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) + { + /* xdg config dir already exists */ + g_free (xdg_dir); + return; + } + + old_dir = g_build_filename (g_get_home_dir (), ".gnome2", + PACKAGE_NAME, NULL); + if (!g_file_test (old_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) + { + /* old config dir didn't exist */ + g_free (xdg_dir); + g_free (old_dir); + return; + } + + if (g_mkdir_with_parents (xdg_dir, (S_IRUSR | S_IWUSR | S_IXUSR)) == -1) + { + DEBUG ("Failed to create configuration directory; aborting migration"); + g_free (xdg_dir); + g_free (old_dir); + return; + } + + for (i = 0; filenames[i]; i++) + { + old_filename = g_build_filename (old_dir, filenames[i], NULL); + if (!g_file_test (old_filename, G_FILE_TEST_EXISTS)) + { + g_free (old_filename); + continue; + } + xdg_filename = g_build_filename (xdg_dir, filenames[i], NULL); + old_file = g_file_new_for_path (old_filename); + xdg_file = g_file_new_for_path (xdg_filename); + + if (!g_file_move (old_file, xdg_file, G_FILE_COPY_NONE, + NULL, NULL, NULL, NULL)) + DEBUG ("Failed to migrate %s", filenames[i]); + + g_free (old_filename); + g_free (xdg_filename); + g_object_unref (old_file); + g_object_unref (xdg_file); + } + + g_free (xdg_dir); + g_free (old_dir); +} - return (retval > 0) ? retval : 0; +static UniqueResponse +unique_app_message_cb (UniqueApp *unique_app, + gint command, + UniqueMessageData *data, + guint timestamp, + gpointer user_data) +{ + GtkWidget *window = user_data; + + DEBUG ("Other instance launched, presenting the main window. " + "Command=%d, timestamp %u", command, timestamp); + + if (command == COMMAND_ACCOUNTS_DIALOG) + { + empathy_accounts_dialog_show (GTK_WINDOW (window), NULL); + } + else + { + gtk_window_set_screen (GTK_WINDOW (window), + unique_message_data_get_screen (data)); + gtk_window_set_startup_id (GTK_WINDOW (window), + unique_message_data_get_startup_id (data)); + gtk_window_present_with_time (GTK_WINDOW (window), timestamp); + } + + return UNIQUE_RESPONSE_OK; } static gboolean show_version_cb (const char *option_name, - const char *value, - gpointer data, - GError **error) + const char *value, + gpointer data, + GError **error) { - g_print ("%s\n", PACKAGE_STRING); + g_print ("%s\n", PACKAGE_STRING); - exit (EXIT_SUCCESS); + exit (EXIT_SUCCESS); - return FALSE; + return FALSE; } static void new_incoming_transfer_cb (EmpathyFTFactory *factory, - EmpathyFTHandler *handler, - GError *error, - gpointer user_data) + EmpathyFTHandler *handler, + GError *error, + gpointer user_data) { - if (error) { - empathy_ft_manager_display_error (handler, error); - } else { - empathy_receive_file_with_file_chooser (handler); - } + if (error) + empathy_ft_manager_display_error (handler, error); + else + empathy_receive_file_with_file_chooser (handler); } static void new_ft_handler_cb (EmpathyFTFactory *factory, - EmpathyFTHandler *handler, - GError *error, - gpointer user_data) + EmpathyFTHandler *handler, + GError *error, + gpointer user_data) { - if (error) { - empathy_ft_manager_display_error (handler, error); - } else { - empathy_ft_manager_add_handler (handler); - } + if (error) + empathy_ft_manager_display_error (handler, error); + else + empathy_ft_manager_add_handler (handler); - g_object_unref (handler); + g_object_unref (handler); } static void -new_call_handler_cb (EmpathyCallFactory *factory, EmpathyCallHandler *handler, - gboolean outgoing, gpointer user_data) +new_call_handler_cb (EmpathyCallFactory *factory, + EmpathyCallHandler *handler, + gboolean outgoing, + gpointer user_data) { - EmpathyCallWindow *window; + EmpathyCallWindow *window; - window = empathy_call_window_new (handler); - gtk_widget_show (GTK_WIDGET (window)); + window = empathy_call_window_new (handler); + gtk_widget_show (GTK_WIDGET (window)); } #ifdef ENABLE_DEBUG @@ -522,249 +514,246 @@ default_log_handler (const gchar *log_domain, const gchar *message, gpointer user_data) { - g_log_default_handler (log_domain, log_level, message, NULL); - - /* G_LOG_DOMAIN = "empathy". No need to send empathy messages to the - * debugger as they already have in empathy_debug. */ - if (log_level != G_LOG_LEVEL_DEBUG - || tp_strdiff (log_domain, G_LOG_DOMAIN)) { - EmpathyDebugger *dbg; - GTimeVal now; - - dbg = empathy_debugger_get_singleton (); - g_get_current_time (&now); - - empathy_debugger_add_message (dbg, &now, log_domain, - log_level, message); - } + g_log_default_handler (log_domain, log_level, message, NULL); + + /* G_LOG_DOMAIN = "empathy". No need to send empathy messages to the + * debugger as they already have in empathy_debug. */ + if (log_level != G_LOG_LEVEL_DEBUG + || tp_strdiff (log_domain, G_LOG_DOMAIN)) + { + EmpathyDebugger *dbg; + GTimeVal now; + + dbg = empathy_debugger_get_singleton (); + g_get_current_time (&now); + + empathy_debugger_add_message (dbg, &now, log_domain, + log_level, message); + } } #endif /* ENABLE_DEBUG */ +static void +account_manager_ready_cb (EmpathyAccountManager *manager, + GParamSpec *spec, + gpointer user_data) +{ + if (!empathy_account_manager_is_ready (manager)) + return; + + if (should_create_salut_account () || !empathy_import_mc4_has_imported ()) + { + EmpathyConnectionManagers *managers; + managers = empathy_connection_managers_dup_singleton (); + + if (!check_connection_managers_ready (managers)) + { + g_signal_connect (managers, "notify::ready", + G_CALLBACK (connection_managers_ready_cb), NULL); + } + } + else + { + maybe_show_account_assistant (); + } +} + int main (int argc, char *argv[]) { - guint32 startup_timestamp; #if HAVE_GEOCLUE - EmpathyLocationManager *location_manager = NULL; + EmpathyLocationManager *location_manager = NULL; #endif - EmpathyStatusIcon *icon; - EmpathyDispatcher *dispatcher; - EmpathyLogManager *log_manager; - EmpathyChatroomManager *chatroom_manager; - EmpathyCallFactory *call_factory; - EmpathyFTFactory *ft_factory; - GtkWidget *window; - MissionControl *mc; - EmpathyIdle *idle; - EmpathyConnectivity *connectivity; - gboolean autoconnect = TRUE; - gboolean no_connect = FALSE; - gboolean hide_contact_list = FALSE; - gboolean accounts_dialog = FALSE; - GError *error = NULL; - TpDBusDaemon *dbus_daemon; - GOptionEntry options[] = { - { "no-connect", 'n', - 0, G_OPTION_ARG_NONE, &no_connect, - N_("Don't connect on startup"), - NULL }, - { "hide-contact-list", 'h', - 0, G_OPTION_ARG_NONE, &hide_contact_list, - N_("Don't show the contact list on startup"), - NULL }, - { "accounts", 'a', - 0, G_OPTION_ARG_NONE, &accounts_dialog, - N_("Show the accounts dialog"), - NULL }, - { "version", 'v', - G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, show_version_cb, NULL, NULL }, - { NULL } - }; - - /* Init */ - g_thread_init (NULL); - empathy_init (); - - if (!gtk_init_with_args (&argc, &argv, - N_("- Empathy IM Client"), - options, GETTEXT_PACKAGE, &error)) { - g_warning ("Error in empathy init: %s", error->message); - return EXIT_FAILURE; - } - - empathy_gtk_init (); - g_set_application_name (_(PACKAGE_NAME)); - g_setenv ("PULSE_PROP_media.role", "phone", TRUE); - - gst_init (&argc, &argv); + EmpathyStatusIcon *icon; + EmpathyDispatcher *dispatcher; + EmpathyAccountManager *account_manager; + EmpathyLogManager *log_manager; + EmpathyChatroomManager *chatroom_manager; + EmpathyCallFactory *call_factory; + EmpathyFTFactory *ft_factory; + GtkWidget *window; + EmpathyIdle *idle; + EmpathyConnectivity *connectivity; + gboolean autoconnect = TRUE; + gboolean no_connect = FALSE; + gboolean hide_contact_list = FALSE; + gboolean accounts_dialog = FALSE; + GError *error = NULL; + TpDBusDaemon *dbus_daemon; + UniqueApp *unique_app; + + GOptionEntry options[] = { + { "no-connect", 'n', + 0, G_OPTION_ARG_NONE, &no_connect, + N_("Don't connect on startup"), + NULL }, + { "hide-contact-list", 'h', + 0, G_OPTION_ARG_NONE, &hide_contact_list, + N_("Don't show the contact list on startup"), + NULL }, + { "accounts", 'a', + 0, G_OPTION_ARG_NONE, &accounts_dialog, + N_("Show the accounts dialog"), + NULL }, + { "version", 'v', + G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, show_version_cb, + NULL, NULL }, + { NULL } + }; + + /* Init */ + g_thread_init (NULL); + empathy_init (); + + if (!gtk_init_with_args (&argc, &argv, N_("- Empathy IM Client"), + options, GETTEXT_PACKAGE, &error)) + { + g_warning ("Error in empathy init: %s", error->message); + return EXIT_FAILURE; + } + + empathy_gtk_init (); + g_set_application_name (_(PACKAGE_NAME)); + g_setenv ("PULSE_PROP_media.role", "phone", TRUE); + + gst_init (&argc, &argv); #if HAVE_LIBCHAMPLAIN - gtk_clutter_init (&argc, &argv); + gtk_clutter_init (&argc, &argv); #endif - gtk_window_set_default_icon_name ("empathy"); - textdomain (GETTEXT_PACKAGE); + gtk_window_set_default_icon_name ("empathy"); + textdomain (GETTEXT_PACKAGE); #ifdef ENABLE_DEBUG - /* Set up debugger */ - g_log_set_default_handler (default_log_handler, NULL); + /* Set up debugger */ + g_log_set_default_handler (default_log_handler, NULL); #endif - /* Setting up the bacon connection */ - startup_timestamp = get_startup_timestamp (); - connection = bacon_message_connection_new ("empathy"); - if (connection != NULL) { - if (!bacon_message_connection_get_is_server (connection)) { - gchar *message; - - if (accounts_dialog) { - DEBUG ("Showing accounts dialog from existing Empathy instance"); - - message = g_strdup ("accounts"); - - } else { - - DEBUG ("Activating existing instance"); - - message = g_strdup_printf ("%" G_GUINT32_FORMAT, - startup_timestamp); - } - - bacon_message_connection_send (connection, message); - - /* We never popup a window, so tell startup-notification - * that we are done. */ - gdk_notify_startup_complete (); - - g_free (message); - bacon_message_connection_free (connection); - - return EXIT_SUCCESS; - } - } else { - g_warning ("Cannot create the 'empathy' bacon connection."); - } - - /* Take well-known name */ - dbus_daemon = tp_dbus_daemon_dup (&error); - if (error == NULL) { - if (!tp_dbus_daemon_request_name (dbus_daemon, - "org.gnome.Empathy", - 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); - } - - /* Setting up MC */ - mc = empathy_mission_control_dup_singleton (); - g_signal_connect (mc, "ServiceEnded", - G_CALLBACK (service_ended_cb), - NULL); - g_signal_connect (mc, "Error", - G_CALLBACK (operation_error_cb), - NULL); - - if (accounts_dialog) { - GtkWidget *dialog; - - dialog = empathy_accounts_dialog_show (NULL, NULL); - g_signal_connect (dialog, "destroy", - G_CALLBACK (gtk_main_quit), - NULL); - - gtk_main (); - return 0; - } - - /* Setting up Idle */ - idle = empathy_idle_dup_singleton (); - empathy_idle_set_auto_away (idle, TRUE); - - /* Setting up Connectivity */ - connectivity = empathy_connectivity_dup_singleton (); - use_conn_notify_cb (empathy_conf_get (), EMPATHY_PREFS_USE_CONN, - connectivity); - empathy_conf_notify_add (empathy_conf_get (), EMPATHY_PREFS_USE_CONN, - use_conn_notify_cb, connectivity); - - /* Autoconnect */ - empathy_conf_get_bool (empathy_conf_get (), - EMPATHY_PREFS_AUTOCONNECT, - &autoconnect); - if (autoconnect && ! no_connect && - tp_connection_presence_type_cmp_availability (empathy_idle_get_state - (idle), TP_CONNECTION_PRESENCE_TYPE_OFFLINE) <= 0) { - empathy_idle_set_state (idle, MC_PRESENCE_AVAILABLE); - } - - - migrate_config_to_xdg_dir (); - create_salut_account (); - - /* Setting up UI */ - window = empathy_main_window_show (); - icon = empathy_status_icon_new (GTK_WINDOW (window), hide_contact_list); - - if (connection) { - /* We se the callback here because we need window */ - bacon_message_connection_set_callback (connection, - on_bacon_message_received, - window); - } - - /* Handle channels */ - dispatcher = empathy_dispatcher_dup_singleton (); - g_signal_connect (dispatcher, "dispatch", G_CALLBACK (dispatch_cb), NULL); - - /* Logging */ - log_manager = empathy_log_manager_dup_singleton (); - empathy_log_manager_observe (log_manager, dispatcher); - - chatroom_manager = empathy_chatroom_manager_dup_singleton (NULL); - empathy_chatroom_manager_observe (chatroom_manager, dispatcher); - - notify_init (_(PACKAGE_NAME)); - /* Create the call factory */ - call_factory = empathy_call_factory_initialise (); - g_signal_connect (G_OBJECT (call_factory), "new-call-handler", - G_CALLBACK (new_call_handler_cb), NULL); - /* Create the FT factory */ - ft_factory = empathy_ft_factory_dup_singleton (); - g_signal_connect (ft_factory, "new-ft-handler", - G_CALLBACK (new_ft_handler_cb), NULL); - g_signal_connect (ft_factory, "new-incoming-transfer", - G_CALLBACK (new_incoming_transfer_cb), NULL); - - /* Location mananger */ + unique_app = unique_app_new_with_commands ("org.gnome.Empathy", + NULL, "accounts_dialog", COMMAND_ACCOUNTS_DIALOG, NULL); + + if (unique_app_is_running (unique_app)) + { + unique_app_send_message (unique_app, accounts_dialog ? + COMMAND_ACCOUNTS_DIALOG : 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, + "org.gnome.Empathy", 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); + } + + if (accounts_dialog) + { + GtkWidget *dialog; + + dialog = empathy_accounts_dialog_show (NULL, NULL); + g_signal_connect (dialog, "destroy", + G_CALLBACK (gtk_main_quit), NULL); + + gtk_main (); + return 0; + } + + /* Setting up Idle */ + idle = empathy_idle_dup_singleton (); + empathy_idle_set_auto_away (idle, TRUE); + + /* Setting up Connectivity */ + connectivity = empathy_connectivity_dup_singleton (); + use_conn_notify_cb (empathy_conf_get (), EMPATHY_PREFS_USE_CONN, + connectivity); + empathy_conf_notify_add (empathy_conf_get (), EMPATHY_PREFS_USE_CONN, + use_conn_notify_cb, connectivity); + + /* Autoconnect */ + empathy_conf_get_bool (empathy_conf_get (), + EMPATHY_PREFS_AUTOCONNECT, &autoconnect); + if (autoconnect && !no_connect && + tp_connection_presence_type_cmp_availability + (empathy_idle_get_state (idle), TP_CONNECTION_PRESENCE_TYPE_OFFLINE) + <= 0) + empathy_idle_set_state (idle, TP_CONNECTION_PRESENCE_TYPE_AVAILABLE); + + /* account management */ + account_manager = empathy_account_manager_dup_singleton (); + g_signal_connect (account_manager, "notify::ready", + G_CALLBACK (account_manager_ready_cb), NULL); + + migrate_config_to_xdg_dir (); + + /* Setting up UI */ + window = empathy_main_window_show (); + icon = empathy_status_icon_new (GTK_WINDOW (window), hide_contact_list); + + g_signal_connect (unique_app, "message-received", + G_CALLBACK (unique_app_message_cb), window); + + /* Handle channels */ + dispatcher = empathy_dispatcher_dup_singleton (); + g_signal_connect (dispatcher, "dispatch", G_CALLBACK (dispatch_cb), NULL); + + /* Logging */ + log_manager = empathy_log_manager_dup_singleton (); + empathy_log_manager_observe (log_manager, dispatcher); + + chatroom_manager = empathy_chatroom_manager_dup_singleton (NULL); + empathy_chatroom_manager_observe (chatroom_manager, dispatcher); + + notify_init (_(PACKAGE_NAME)); + /* Create the call factory */ + call_factory = empathy_call_factory_initialise (); + g_signal_connect (G_OBJECT (call_factory), "new-call-handler", + G_CALLBACK (new_call_handler_cb), NULL); + /* Create the FT factory */ + ft_factory = empathy_ft_factory_dup_singleton (); + g_signal_connect (ft_factory, "new-ft-handler", + G_CALLBACK (new_ft_handler_cb), NULL); + g_signal_connect (ft_factory, "new-incoming-transfer", + G_CALLBACK (new_incoming_transfer_cb), NULL); + + /* Location mananger */ #if HAVE_GEOCLUE - location_manager = empathy_location_manager_dup_singleton (); + location_manager = empathy_location_manager_dup_singleton (); #endif - gtk_main (); + gtk_main (); - empathy_idle_set_state (idle, TP_CONNECTION_PRESENCE_TYPE_OFFLINE); + empathy_idle_set_state (idle, TP_CONNECTION_PRESENCE_TYPE_OFFLINE); - g_object_unref (mc); - g_object_unref (idle); - g_object_unref (connectivity); - g_object_unref (icon); - g_object_unref (log_manager); - g_object_unref (dispatcher); - g_object_unref (chatroom_manager); + g_object_unref (idle); + g_object_unref (connectivity); + g_object_unref (icon); + g_object_unref (account_manager); + g_object_unref (log_manager); + g_object_unref (dispatcher); + g_object_unref (chatroom_manager); #if HAVE_GEOCLUE - g_object_unref (location_manager); + g_object_unref (location_manager); #endif - g_object_unref (ft_factory); + g_object_unref (ft_factory); + g_object_unref (unique_app); - notify_uninit (); + notify_uninit (); - return EXIT_SUCCESS; + return EXIT_SUCCESS; } - |