]> git.0d.be Git - empathy.git/blob - src/empathy-accounts-dialog.c
Use the new function in the accounts dialog
[empathy.git] / src / empathy-accounts-dialog.c
1 /*
2  * Copyright (C) 2005-2007 Imendio AB
3  * Copyright (C) 2007-2009 Collabora Ltd.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public
16  * License along with this program; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA  02110-1301  USA
19  *
20  * Authors: Martyn Russell <martyn@imendio.com>
21  *          Xavier Claessens <xclaesse@gmail.com>
22  *          Cosimo Cecchi <cosimo.cecchi@collabora.co.uk>
23  *          Jonathan Tellier <jonathan.tellier@gmail.com>
24  */
25
26 #include <config.h>
27
28 #include <string.h>
29 #include <stdlib.h>
30
31 #include <gtk/gtk.h>
32 #include <glib/gi18n.h>
33 #include <dbus/dbus-glib.h>
34
35 #include <telepathy-glib/util.h>
36
37 #include <libempathy/empathy-utils.h>
38 #include <libempathy/empathy-account-manager.h>
39 #include <libempathy/empathy-connection-managers.h>
40 #include <libempathy-gtk/empathy-ui-utils.h>
41
42 #include <libempathy-gtk/empathy-protocol-chooser.h>
43 #include <libempathy-gtk/empathy-account-widget.h>
44 #include <libempathy-gtk/empathy-account-widget-irc.h>
45 #include <libempathy-gtk/empathy-account-widget-sip.h>
46 #include <libempathy-gtk/empathy-cell-renderer-activatable.h>
47 #include <libempathy-gtk/empathy-conf.h>
48 #include <libempathy-gtk/empathy-images.h>
49
50 #include "empathy-accounts-dialog.h"
51 #include "empathy-import-dialog.h"
52 #include "empathy-import-utils.h"
53
54 #define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT
55 #include <libempathy/empathy-debug.h>
56
57 /* Flashing delay for icons (milliseconds). */
58 #define FLASH_TIMEOUT 500
59
60 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyAccountsDialog)
61 G_DEFINE_TYPE (EmpathyAccountsDialog, empathy_accounts_dialog, G_TYPE_OBJECT);
62
63 static EmpathyAccountsDialog *dialog_singleton = NULL;
64
65 typedef struct {
66   GtkWidget *window;
67
68   GtkWidget *alignment_settings;
69
70   GtkWidget *vbox_details;
71   GtkWidget *frame_no_protocol;
72
73   GtkWidget *treeview;
74
75   GtkWidget *button_add;
76
77   GtkWidget *frame_new_account;
78   GtkWidget *combobox_protocol;
79   GtkWidget *hbox_type;
80   GtkWidget *button_create;
81   GtkWidget *button_back;
82   GtkWidget *radiobutton_reuse;
83   GtkWidget *radiobutton_register;
84
85   GtkWidget *image_type;
86   GtkWidget *label_name;
87   GtkWidget *label_type;
88   GtkWidget *settings_widget;
89
90   gboolean  connecting_show;
91   guint connecting_id;
92
93   gulong  settings_ready_id;
94   EmpathyAccountSettings *settings_ready;
95
96   EmpathyAccountManager *account_manager;
97   EmpathyConnectionManagers *cms;
98
99   GtkWindow *parent_window;
100   EmpathyAccount *initial_selection;
101 } EmpathyAccountsDialogPriv;
102
103 enum {
104   COL_NAME,
105   COL_STATUS,
106   COL_ACCOUNT_POINTER,
107   COL_ACCOUNT_SETTINGS_POINTER,
108   COL_COUNT
109 };
110
111 enum {
112   PROP_PARENT = 1
113 };
114
115 static EmpathyAccountSettings * accounts_dialog_model_get_selected_settings (
116     EmpathyAccountsDialog *dialog);
117
118 static void accounts_dialog_model_select_first (EmpathyAccountsDialog *dialog);
119
120 static void accounts_dialog_update (EmpathyAccountsDialog *dialog,
121     EmpathyAccountSettings *settings);
122
123 static void accounts_dialog_update_settings (EmpathyAccountsDialog *dialog,
124     EmpathyAccountSettings *settings);
125
126 static void
127 accounts_dialog_update_name_label (EmpathyAccountsDialog *dialog,
128     const gchar *display_name)
129 {
130   gchar *text;
131   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
132
133   text = g_markup_printf_escaped ("<big><b>%s</b></big>", display_name);
134   gtk_label_set_markup (GTK_LABEL (priv->label_name), text);
135
136   g_free (text);
137 }
138
139 static void
140 empathy_account_dialog_widget_cancelled_cb (EmpathyAccountWidget *widget_object,
141     EmpathyAccountsDialog *dialog)
142 {
143   GtkTreeView *view;
144   GtkTreeModel *model;
145   GtkTreeSelection *selection;
146   GtkTreeIter iter;
147   EmpathyAccountSettings *settings;
148   EmpathyAccount *account;
149   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
150
151   view = GTK_TREE_VIEW (priv->treeview);
152   selection = gtk_tree_view_get_selection (view);
153
154   if (!gtk_tree_selection_get_selected (selection, &model, &iter))
155     return;
156
157   gtk_tree_model_get (model, &iter,
158       COL_ACCOUNT_SETTINGS_POINTER, &settings,
159       COL_ACCOUNT_POINTER, &account, -1);
160
161   empathy_account_settings_discard_changes (settings);
162
163   if (account == NULL)
164     {
165       /* We were creating an account. We remove the selected row */
166       gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
167     }
168   else
169     {
170       /* We were modifying an account. We discard the changes by reloading the
171        * settings and the UI. */
172       accounts_dialog_update_settings (dialog, settings);
173       g_object_unref (account);
174     }
175
176   if (settings != NULL)
177     g_object_unref (settings);
178 }
179
180 static void
181 empathy_account_dialog_account_created_cb (EmpathyAccountWidget *widget_object,
182     EmpathyAccountsDialog *dialog)
183 {
184   EmpathyAccountSettings *settings =
185       accounts_dialog_model_get_selected_settings (dialog);
186   accounts_dialog_update_settings (dialog, settings);
187
188   if (settings)
189     g_object_unref (settings);
190 }
191
192 static GtkWidget *
193 get_account_setup_widget (EmpathyAccountSettings *settings,
194     EmpathyAccountWidget **widget_object)
195 {
196   const gchar *proto = empathy_account_settings_get_protocol (settings);
197   EmpathyConnectionManagers *cm =
198       empathy_connection_managers_dup_singleton ();
199   GList *cms = empathy_connection_managers_get_cms (cm);
200   GList *l;
201
202   for (l = cms; l; l = l->next)
203     {
204       TpConnectionManager *tp_cm = l->data;
205       if (tp_connection_manager_has_protocol (tp_cm, proto))
206         {
207           g_object_unref (cm);
208           *widget_object = empathy_account_widget_new_for_protocol (proto,
209               settings, FALSE);
210           return empathy_account_widget_get_widget (*widget_object);
211         }
212     }
213
214   g_object_unref (cm);
215   *widget_object = empathy_account_widget_new_for_protocol ("generic", settings,
216       FALSE);
217   return empathy_account_widget_get_widget (*widget_object);
218 }
219
220 static void
221 account_dialog_create_settings_widget (EmpathyAccountsDialog *dialog,
222     EmpathyAccountSettings *settings)
223 {
224   EmpathyAccountWidget *widget_object = NULL;
225   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
226   gchar *icon_name;
227
228   priv->settings_widget = get_account_setup_widget (settings, &widget_object);
229   g_signal_connect (widget_object, "account-created",
230         G_CALLBACK (empathy_account_dialog_account_created_cb), dialog);
231   g_signal_connect (widget_object, "cancelled",
232           G_CALLBACK (empathy_account_dialog_widget_cancelled_cb), dialog);
233
234   gtk_container_add (GTK_CONTAINER (priv->alignment_settings),
235       priv->settings_widget);
236   gtk_widget_show (priv->settings_widget);
237
238   icon_name = empathy_account_settings_get_icon_name (settings);
239
240   gtk_image_set_from_icon_name (GTK_IMAGE (priv->image_type),
241       icon_name, GTK_ICON_SIZE_DIALOG);
242   gtk_widget_set_tooltip_text (priv->image_type,
243       empathy_protocol_name_to_display_name
244       (empathy_account_settings_get_protocol (settings)));
245
246   accounts_dialog_update_name_label (dialog,
247       empathy_account_settings_get_display_name (settings));
248 }
249
250 static void
251 account_dialog_settings_ready_cb (EmpathyAccountSettings *settings,
252     GParamSpec *spec,
253     EmpathyAccountsDialog *dialog)
254 {
255   if (empathy_account_settings_is_ready (settings))
256     account_dialog_create_settings_widget (dialog, settings);
257 }
258
259 static void
260 accounts_dialog_model_select_first (EmpathyAccountsDialog *dialog)
261 {
262   GtkTreeView      *view;
263   GtkTreeModel     *model;
264   GtkTreeSelection *selection;
265   GtkTreeIter       iter;
266   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
267
268   /* select first */
269   view = GTK_TREE_VIEW (priv->treeview);
270   model = gtk_tree_view_get_model (view);
271
272   if (gtk_tree_model_get_iter_first (model, &iter))
273     {
274       selection = gtk_tree_view_get_selection (view);
275       gtk_tree_selection_select_iter (selection, &iter);
276     }
277   else
278     {
279       accounts_dialog_update_settings (dialog, NULL);
280     }
281 }
282
283 static void
284 accounts_dialog_protocol_changed_cb (GtkWidget *widget,
285     EmpathyAccountsDialog *dialog)
286 {
287   TpConnectionManager *cm;
288   TpConnectionManagerProtocol *proto;
289   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
290
291   cm = empathy_protocol_chooser_dup_selected (
292       EMPATHY_PROTOCOL_CHOOSER (priv->combobox_protocol), &proto);
293
294   if (cm == NULL)
295     return;
296
297   if (proto == NULL)
298     {
299       g_object_unref (cm);
300       return;
301     }
302
303   if (tp_connection_manager_protocol_can_register (proto))
304     {
305       gtk_widget_show (priv->radiobutton_register);
306       gtk_widget_show (priv->radiobutton_reuse);
307     }
308   else
309     {
310       gtk_widget_hide (priv->radiobutton_register);
311       gtk_widget_hide (priv->radiobutton_reuse);
312     }
313   g_object_unref (cm);
314 }
315
316 static void
317 accounts_dialog_button_add_clicked_cb (GtkWidget *button,
318     EmpathyAccountsDialog *dialog)
319 {
320   GtkTreeView      *view;
321   GtkTreeModel     *model;
322   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
323
324   view = GTK_TREE_VIEW (priv->treeview);
325   model = gtk_tree_view_get_model (view);
326
327   gtk_widget_set_sensitive (priv->button_add, FALSE);
328   gtk_widget_hide (priv->vbox_details);
329   gtk_widget_hide (priv->frame_no_protocol);
330   gtk_widget_show (priv->frame_new_account);
331
332   /* If we have no account, no need of a back button */
333   if (gtk_tree_model_iter_n_children (model, NULL) > 0)
334     gtk_widget_show (priv->button_back);
335   else
336     gtk_widget_hide (priv->button_back);
337
338   accounts_dialog_protocol_changed_cb (priv->radiobutton_register, dialog);
339   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->radiobutton_reuse),
340       TRUE);
341   gtk_combo_box_set_active (GTK_COMBO_BOX (priv->combobox_protocol), 0);
342   gtk_widget_grab_focus (priv->combobox_protocol);
343 }
344
345 static void
346 accounts_dialog_update_settings (EmpathyAccountsDialog *dialog,
347     EmpathyAccountSettings *settings)
348 {
349   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
350
351   if (priv->settings_ready != NULL)
352     {
353       g_signal_handler_disconnect (priv->settings_ready,
354           priv->settings_ready_id);
355       priv->settings_ready = NULL;
356       priv->settings_ready_id = 0;
357     }
358
359   if (!settings)
360     {
361       GtkTreeView  *view;
362       GtkTreeModel *model;
363
364       view = GTK_TREE_VIEW (priv->treeview);
365       model = gtk_tree_view_get_model (view);
366
367       if (gtk_tree_model_iter_n_children (model, NULL) > 0)
368         {
369           /* We have configured accounts, select the first one */
370           accounts_dialog_model_select_first (dialog);
371           return;
372         }
373       if (empathy_connection_managers_get_cms_num (priv->cms) > 0)
374         {
375           /* We have no account configured but we have some
376            * profiles installed. The user obviously wants to add
377            * an account. Click on the Add button for him. */
378           accounts_dialog_button_add_clicked_cb (priv->button_add,
379               dialog);
380           return;
381         }
382
383       /* No account and no profile, warn the user */
384       gtk_widget_hide (priv->vbox_details);
385       gtk_widget_hide (priv->frame_new_account);
386       gtk_widget_show (priv->frame_no_protocol);
387       gtk_widget_set_sensitive (priv->button_add, FALSE);
388       return;
389     }
390
391   /* We have an account selected, destroy old settings and create a new
392    * one for the account selected */
393   gtk_widget_hide (priv->frame_new_account);
394   gtk_widget_hide (priv->frame_no_protocol);
395   gtk_widget_show (priv->vbox_details);
396   gtk_widget_set_sensitive (priv->button_add, TRUE);
397
398   if (priv->settings_widget)
399     {
400       gtk_widget_destroy (priv->settings_widget);
401       priv->settings_widget = NULL;
402     }
403
404   if (empathy_account_settings_is_ready (settings))
405     {
406       account_dialog_create_settings_widget (dialog, settings);
407     }
408   else
409     {
410       priv->settings_ready = settings;
411       priv->settings_ready_id =
412         g_signal_connect (settings, "notify::ready",
413             G_CALLBACK (account_dialog_settings_ready_cb), dialog);
414     }
415
416 }
417
418 static void
419 accounts_dialog_name_editing_started_cb (GtkCellRenderer *renderer,
420     GtkCellEditable *editable,
421     gchar *path,
422     EmpathyAccountsDialog *dialog)
423 {
424   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
425
426   if (priv->connecting_id)
427     g_source_remove (priv->connecting_id);
428
429   DEBUG ("Editing account name started; stopping flashing");
430 }
431
432 static void
433 accounts_dialog_model_pixbuf_data_func (GtkTreeViewColumn *tree_column,
434     GtkCellRenderer *cell,
435     GtkTreeModel *model,
436     GtkTreeIter *iter,
437     EmpathyAccountsDialog *dialog)
438 {
439   EmpathyAccountSettings  *settings;
440   gchar              *icon_name;
441   GdkPixbuf          *pixbuf;
442   TpConnectionStatus  status;
443   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
444
445   gtk_tree_model_get (model, iter,
446       COL_STATUS, &status,
447       COL_ACCOUNT_SETTINGS_POINTER, &settings,
448       -1);
449
450   icon_name = empathy_account_settings_get_icon_name (settings);
451   pixbuf = empathy_pixbuf_from_icon_name (icon_name, GTK_ICON_SIZE_BUTTON);
452
453   if (pixbuf)
454     {
455       if (status == TP_CONNECTION_STATUS_DISCONNECTED ||
456           (status == TP_CONNECTION_STATUS_CONNECTING &&
457               !priv->connecting_show))
458         {
459           GdkPixbuf *modded_pixbuf;
460
461           modded_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
462               TRUE,
463               8,
464               gdk_pixbuf_get_width (pixbuf),
465               gdk_pixbuf_get_height (pixbuf));
466
467           gdk_pixbuf_saturate_and_pixelate (pixbuf,
468               modded_pixbuf,
469               1.0,
470               TRUE);
471           g_object_unref (pixbuf);
472           pixbuf = modded_pixbuf;
473         }
474     }
475
476   g_object_set (cell,
477       "visible", TRUE,
478       "pixbuf", pixbuf,
479       NULL);
480
481   g_object_unref (settings);
482
483   if (pixbuf)
484     g_object_unref (pixbuf);
485 }
486
487 static gboolean
488 accounts_dialog_row_changed_foreach (GtkTreeModel *model,
489     GtkTreePath *path,
490     GtkTreeIter *iter,
491     gpointer user_data)
492 {
493   gtk_tree_model_row_changed (model, path, iter);
494
495   return FALSE;
496 }
497
498 static gboolean
499 accounts_dialog_flash_connecting_cb (EmpathyAccountsDialog *dialog)
500 {
501   GtkTreeView  *view;
502   GtkTreeModel *model;
503   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
504
505   priv->connecting_show = !priv->connecting_show;
506
507   view = GTK_TREE_VIEW (priv->treeview);
508   model = gtk_tree_view_get_model (view);
509
510   gtk_tree_model_foreach (model, accounts_dialog_row_changed_foreach, NULL);
511
512   return TRUE;
513 }
514
515 static void
516 accounts_dialog_name_edited_cb (GtkCellRendererText *renderer,
517     gchar *path,
518     gchar *new_text,
519     EmpathyAccountsDialog *dialog)
520 {
521   EmpathyAccountSettings    *settings;
522   GtkTreeModel *model;
523   GtkTreePath  *treepath;
524   GtkTreeIter   iter;
525   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
526
527   if (empathy_account_manager_get_connecting_accounts
528       (priv->account_manager) > 0)
529     {
530       priv->connecting_id = g_timeout_add (FLASH_TIMEOUT,
531           (GSourceFunc) accounts_dialog_flash_connecting_cb,
532           dialog);
533     }
534
535   model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
536   treepath = gtk_tree_path_new_from_string (path);
537   gtk_tree_model_get_iter (model, &iter, treepath);
538   gtk_tree_model_get (model, &iter,
539       COL_ACCOUNT_SETTINGS_POINTER, &settings,
540       -1);
541   gtk_list_store_set (GTK_LIST_STORE (model), &iter,
542       COL_NAME, new_text,
543       -1);
544   gtk_tree_path_free (treepath);
545
546   empathy_account_settings_set_display_name_async (settings, new_text,
547       NULL, NULL);
548   g_object_set (settings, "display-name-overridden", TRUE, NULL);
549   g_object_unref (settings);
550 }
551
552 static void
553 accounts_dialog_delete_account_response_cb (GtkDialog *message_dialog,
554   gint response_id,
555   gpointer user_data)
556 {
557   EmpathyAccount *account;
558   GtkTreeModel *model;
559   GtkTreeIter iter;
560   GtkTreeSelection *selection;
561   EmpathyAccountsDialog *account_dialog = EMPATHY_ACCOUNTS_DIALOG (user_data);
562   EmpathyAccountsDialogPriv *priv = GET_PRIV (account_dialog);
563
564   if (response_id == GTK_RESPONSE_YES)
565     {
566       selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview));
567
568       if (!gtk_tree_selection_get_selected (selection, &model, &iter))
569         return;
570
571       gtk_tree_model_get (model, &iter, COL_ACCOUNT_POINTER, &account, -1);
572
573       if (account != NULL)
574         {
575           empathy_account_remove_async (account, NULL, NULL);
576           g_object_unref (account);
577         }
578
579       gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
580       accounts_dialog_model_select_first (account_dialog);
581     }
582
583   gtk_widget_destroy (GTK_WIDGET (message_dialog));
584 }
585
586 static void
587 accounts_dialog_view_delete_activated_cb (EmpathyCellRendererActivatable *cell,
588     const gchar *path_string,
589     EmpathyAccountsDialog *dialog)
590 {
591   EmpathyAccount *account;
592   GtkTreeModel *model;
593   GtkTreeIter iter;
594   GtkWidget *message_dialog;
595   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
596
597   model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
598
599   if (!gtk_tree_model_get_iter_from_string (model, &iter, path_string))
600     return;
601
602   gtk_tree_model_get (model, &iter, COL_ACCOUNT_POINTER, &account, -1);
603
604   if (account == NULL || !empathy_account_is_valid (account))
605     {
606       gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
607       accounts_dialog_model_select_first (dialog);
608       return;
609     }
610
611   message_dialog = gtk_message_dialog_new
612       (GTK_WINDOW (priv->window),
613           GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
614           GTK_MESSAGE_QUESTION,
615           GTK_BUTTONS_NONE,
616           _("You are about to remove your %s account!\n"
617               "Are you sure you want to proceed?"),
618               empathy_account_get_display_name (account));
619
620   gtk_message_dialog_format_secondary_text
621   (GTK_MESSAGE_DIALOG (message_dialog),
622       _("Any associated conversations and chat rooms will NOT be "
623           "removed if you decide to proceed.\n"
624           "\n"
625           "Should you decide to add the account back at a later time, "
626           "they will still be available."));
627
628   gtk_dialog_add_button (GTK_DIALOG (message_dialog),
629       GTK_STOCK_CANCEL,
630       GTK_RESPONSE_NO);
631   gtk_dialog_add_button (GTK_DIALOG (message_dialog),
632       GTK_STOCK_REMOVE,
633       GTK_RESPONSE_YES);
634
635   g_signal_connect (message_dialog, "response",
636       G_CALLBACK (accounts_dialog_delete_account_response_cb), dialog);
637
638   gtk_widget_show (message_dialog);
639
640   if (account != NULL)
641     g_object_unref (account);
642 }
643
644 static void
645 accounts_dialog_model_add_columns (EmpathyAccountsDialog *dialog)
646 {
647   GtkTreeView       *view;
648   GtkTreeViewColumn *column;
649   GtkCellRenderer   *cell;
650   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
651
652   view = GTK_TREE_VIEW (priv->treeview);
653   gtk_tree_view_set_headers_visible (view, FALSE);
654
655   /* Account column */
656   column = gtk_tree_view_column_new ();
657   gtk_tree_view_column_set_expand (column, TRUE);
658   gtk_tree_view_append_column (view, column);
659
660   /* Icon renderer */
661   cell = gtk_cell_renderer_pixbuf_new ();
662   gtk_tree_view_column_pack_start (column, cell, FALSE);
663   gtk_tree_view_column_set_cell_data_func (column, cell,
664       (GtkTreeCellDataFunc)
665       accounts_dialog_model_pixbuf_data_func,
666       dialog,
667       NULL);
668
669   /* Name renderer */
670   cell = gtk_cell_renderer_text_new ();
671   g_object_set (cell,
672       "ellipsize", PANGO_ELLIPSIZE_END,
673       "width-chars", 25,
674       "editable", TRUE,
675       NULL);
676   gtk_tree_view_column_pack_start (column, cell, TRUE);
677   gtk_tree_view_column_add_attribute (column, cell, "text", COL_NAME);
678   g_signal_connect (cell, "edited",
679       G_CALLBACK (accounts_dialog_name_edited_cb),
680       dialog);
681   g_signal_connect (cell, "editing-started",
682       G_CALLBACK (accounts_dialog_name_editing_started_cb),
683       dialog);
684
685   /* Delete column */
686   cell = empathy_cell_renderer_activatable_new ();
687   gtk_tree_view_column_pack_start (column, cell, FALSE);
688   g_object_set (cell,
689         "icon-name", GTK_STOCK_DELETE,
690         NULL);
691
692   g_signal_connect (cell, "path-activated",
693       G_CALLBACK (accounts_dialog_view_delete_activated_cb),
694       dialog);
695 }
696
697 static EmpathyAccountSettings *
698 accounts_dialog_model_get_selected_settings (EmpathyAccountsDialog *dialog)
699 {
700   GtkTreeView      *view;
701   GtkTreeModel     *model;
702   GtkTreeSelection *selection;
703   GtkTreeIter       iter;
704   EmpathyAccountSettings   *settings;
705   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
706
707   view = GTK_TREE_VIEW (priv->treeview);
708   selection = gtk_tree_view_get_selection (view);
709
710   if (!gtk_tree_selection_get_selected (selection, &model, &iter))
711     return NULL;
712
713   gtk_tree_model_get (model, &iter,
714       COL_ACCOUNT_SETTINGS_POINTER, &settings, -1);
715
716   return settings;
717 }
718
719 static void
720 accounts_dialog_model_selection_changed (GtkTreeSelection *selection,
721     EmpathyAccountsDialog *dialog)
722 {
723   EmpathyAccountSettings *settings;
724   GtkTreeModel *model;
725   GtkTreeIter   iter;
726   gboolean      is_selection;
727
728   is_selection = gtk_tree_selection_get_selected (selection, &model, &iter);
729
730   settings = accounts_dialog_model_get_selected_settings (dialog);
731
732   if (settings != NULL)
733     empathy_account_settings_discard_changes (settings);
734
735   accounts_dialog_update_settings (dialog, settings);
736
737   if (settings != NULL)
738     g_object_unref (settings);
739 }
740
741 static void
742 accounts_dialog_model_setup (EmpathyAccountsDialog *dialog)
743 {
744   GtkListStore     *store;
745   GtkTreeSelection *selection;
746   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
747
748   store = gtk_list_store_new (COL_COUNT,
749       G_TYPE_STRING,         /* name */
750       G_TYPE_UINT,           /* status */
751       EMPATHY_TYPE_ACCOUNT,   /* account */
752       EMPATHY_TYPE_ACCOUNT_SETTINGS); /* settings */
753
754   gtk_tree_view_set_model (GTK_TREE_VIEW (priv->treeview),
755       GTK_TREE_MODEL (store));
756
757   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview));
758   gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
759
760   g_signal_connect (selection, "changed",
761       G_CALLBACK (accounts_dialog_model_selection_changed),
762       dialog);
763
764   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
765       COL_NAME, GTK_SORT_ASCENDING);
766
767   accounts_dialog_model_add_columns (dialog);
768
769   g_object_unref (store);
770 }
771
772 static gboolean
773 accounts_dialog_get_settings_iter (EmpathyAccountsDialog *dialog,
774     EmpathyAccountSettings *settings,
775     GtkTreeIter *iter)
776 {
777   GtkTreeView      *view;
778   GtkTreeSelection *selection;
779   GtkTreeModel     *model;
780   gboolean          ok;
781   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
782
783   /* Update the status in the model */
784   view = GTK_TREE_VIEW (priv->treeview);
785   selection = gtk_tree_view_get_selection (view);
786   model = gtk_tree_view_get_model (view);
787
788   for (ok = gtk_tree_model_get_iter_first (model, iter);
789        ok;
790        ok = gtk_tree_model_iter_next (model, iter))
791     {
792       EmpathyAccountSettings *this_settings;
793       gboolean   equal;
794
795       gtk_tree_model_get (model, iter,
796           COL_ACCOUNT_SETTINGS_POINTER, &this_settings,
797           -1);
798
799       equal = (this_settings == settings);
800       g_object_unref (this_settings);
801
802       if (equal)
803         return TRUE;
804     }
805
806   return FALSE;
807 }
808
809 static gboolean
810 accounts_dialog_get_account_iter (EmpathyAccountsDialog *dialog,
811     EmpathyAccount *account,
812     GtkTreeIter *iter)
813 {
814   GtkTreeView      *view;
815   GtkTreeSelection *selection;
816   GtkTreeModel     *model;
817   gboolean          ok;
818   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
819
820   /* Update the status in the model */
821   view = GTK_TREE_VIEW (priv->treeview);
822   selection = gtk_tree_view_get_selection (view);
823   model = gtk_tree_view_get_model (view);
824
825   for (ok = gtk_tree_model_get_iter_first (model, iter);
826        ok;
827        ok = gtk_tree_model_iter_next (model, iter))
828     {
829       EmpathyAccountSettings *settings;
830       gboolean   equal;
831
832       gtk_tree_model_get (model, iter,
833           COL_ACCOUNT_SETTINGS_POINTER, &settings,
834           -1);
835
836       equal = empathy_account_settings_has_account (settings, account);
837       g_object_unref (settings);
838
839       if (equal)
840         return TRUE;
841     }
842
843   return FALSE;
844 }
845
846 static void
847 accounts_dialog_model_set_selected (EmpathyAccountsDialog *dialog,
848     EmpathyAccountSettings *settings)
849 {
850   GtkTreeSelection *selection;
851   GtkTreeIter       iter;
852   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
853
854   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview));
855   if (accounts_dialog_get_settings_iter (dialog, settings, &iter))
856     gtk_tree_selection_select_iter (selection, &iter);
857 }
858 static void
859 accounts_dialog_add (EmpathyAccountsDialog *dialog,
860     EmpathyAccountSettings *settings)
861 {
862   GtkTreeModel       *model;
863   GtkTreeIter         iter;
864   const gchar        *name;
865   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
866
867   model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
868   name = empathy_account_settings_get_display_name (settings);
869
870   gtk_list_store_append (GTK_LIST_STORE (model), &iter);
871
872   gtk_list_store_set (GTK_LIST_STORE (model), &iter,
873       COL_NAME, name,
874       COL_STATUS, TP_CONNECTION_STATUS_DISCONNECTED,
875       COL_ACCOUNT_SETTINGS_POINTER, settings,
876       -1);
877 }
878
879 static void
880 accounts_dialog_connection_changed_cb     (EmpathyAccountManager *manager,
881     EmpathyAccount *account,
882     TpConnectionStatusReason reason,
883     TpConnectionStatus current,
884     TpConnectionStatus previous,
885     EmpathyAccountsDialog *dialog)
886 {
887   GtkTreeModel *model;
888   GtkTreeIter   iter;
889   gboolean      found;
890   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
891
892   /* Update the status in the model */
893   model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
894
895   if (accounts_dialog_get_account_iter (dialog, account, &iter))
896     {
897       GtkTreePath *path;
898
899       gtk_list_store_set (GTK_LIST_STORE (model), &iter,
900           COL_STATUS, current,
901           -1);
902
903       path = gtk_tree_model_get_path (model, &iter);
904       gtk_tree_model_row_changed (model, path, &iter);
905       gtk_tree_path_free (path);
906     }
907
908   found = (empathy_account_manager_get_connecting_accounts (manager) > 0);
909
910   if (!found && priv->connecting_id)
911     {
912       g_source_remove (priv->connecting_id);
913       priv->connecting_id = 0;
914     }
915
916   if (found && !priv->connecting_id)
917     priv->connecting_id = g_timeout_add (FLASH_TIMEOUT,
918         (GSourceFunc) accounts_dialog_flash_connecting_cb,
919         dialog);
920 }
921
922 static void
923 accounts_dialog_add_account (EmpathyAccountsDialog *dialog,
924     EmpathyAccount *account)
925 {
926   EmpathyAccountSettings *settings;
927   GtkTreeModel       *model;
928   GtkTreeIter         iter;
929   TpConnectionStatus  status;
930   const gchar        *name;
931   gboolean            enabled;
932   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
933
934   model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
935   g_object_get (account, "connection-status", &status, NULL);
936   name = empathy_account_get_display_name (account);
937   enabled = empathy_account_is_enabled (account);
938
939   if (!accounts_dialog_get_account_iter (dialog, account, &iter))
940     gtk_list_store_append (GTK_LIST_STORE (model), &iter);
941
942   settings = empathy_account_settings_new_for_account (account);
943
944   gtk_list_store_set (GTK_LIST_STORE (model), &iter,
945       COL_NAME, name,
946       COL_STATUS, status,
947       COL_ACCOUNT_POINTER, account,
948       COL_ACCOUNT_SETTINGS_POINTER, settings,
949       -1);
950
951   accounts_dialog_connection_changed_cb (priv->account_manager,
952       account,
953       TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED,
954       status,
955       TP_CONNECTION_STATUS_DISCONNECTED,
956       dialog);
957
958   g_object_unref (settings);
959 }
960
961 static void
962 accounts_dialog_update (EmpathyAccountsDialog *dialog,
963     EmpathyAccountSettings *settings)
964 {
965   GtkTreeModel       *model;
966   GtkTreeIter         iter;
967   TpConnectionStatus  status = TP_CONNECTION_STATUS_DISCONNECTED;
968   const gchar        *name;
969   gboolean            enabled = FALSE;
970   EmpathyAccount     *account;
971   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
972
973   model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
974   name = empathy_account_settings_get_display_name (settings);
975
976   account = empathy_account_settings_get_account (settings);
977   if (account != NULL)
978     {
979       enabled = empathy_account_is_enabled (account);
980       g_object_get (account, "connection-status", &status, NULL);
981     }
982
983   accounts_dialog_get_settings_iter (dialog, settings, &iter);
984   gtk_list_store_set (GTK_LIST_STORE (model), &iter,
985       COL_NAME, name,
986       COL_STATUS, status,
987       COL_ACCOUNT_POINTER, account,
988       COL_ACCOUNT_SETTINGS_POINTER, settings,
989       -1);
990 }
991
992 static void
993 accounts_dialog_account_added_cb (EmpathyAccountManager *manager,
994     EmpathyAccount *account,
995     EmpathyAccountsDialog *dialog)
996 {
997   accounts_dialog_add_account (dialog, account);
998 }
999
1000
1001 static void
1002 accounts_dialog_account_removed_cb (EmpathyAccountManager *manager,
1003     EmpathyAccount *account,
1004     EmpathyAccountsDialog *dialog)
1005 {
1006   GtkTreeIter iter;
1007   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
1008
1009   if (accounts_dialog_get_account_iter (dialog, account, &iter))
1010     gtk_list_store_remove (GTK_LIST_STORE (
1011             gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview))), &iter);
1012 }
1013
1014 static void
1015 enable_or_disable_account (EmpathyAccountsDialog *dialog,
1016     EmpathyAccount *account,
1017     gboolean enabled)
1018 {
1019   GtkTreeModel *model;
1020   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
1021
1022   /* Update the status in the model */
1023   model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
1024
1025   DEBUG ("Account %s is now %s",
1026       empathy_account_get_display_name (account),
1027       enabled ? "enabled" : "disabled");
1028 }
1029
1030 static void
1031 accounts_dialog_account_disabled_cb (EmpathyAccountManager *manager,
1032     EmpathyAccount *account,
1033     EmpathyAccountsDialog *dialog)
1034 {
1035   enable_or_disable_account (dialog, account, FALSE);
1036 }
1037
1038 static void
1039 accounts_dialog_account_enabled_cb (EmpathyAccountManager *manager,
1040     EmpathyAccount *account,
1041     EmpathyAccountsDialog *dialog)
1042 {
1043   enable_or_disable_account (dialog, account, TRUE);
1044 }
1045
1046 static void
1047 accounts_dialog_account_changed_cb (EmpathyAccountManager *manager,
1048     EmpathyAccount *account,
1049     EmpathyAccountsDialog  *dialog)
1050 {
1051   EmpathyAccountSettings *settings, *selected_settings;
1052   GtkTreeModel *model;
1053   GtkTreeIter iter;
1054   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
1055
1056   model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
1057
1058   if (!accounts_dialog_get_account_iter (dialog, account, &iter))
1059     return;
1060
1061   gtk_tree_model_get (model, &iter,
1062       COL_ACCOUNT_SETTINGS_POINTER, &settings,
1063       -1);
1064
1065   accounts_dialog_update (dialog, settings);
1066   selected_settings = accounts_dialog_model_get_selected_settings (dialog);
1067
1068   if (settings == selected_settings)
1069     accounts_dialog_update_name_label (dialog,
1070         empathy_account_settings_get_display_name (settings));
1071
1072   if (settings)
1073     g_object_unref (settings);
1074
1075   if (selected_settings)
1076     g_object_unref (selected_settings);
1077 }
1078
1079 static void
1080 accounts_dialog_button_create_clicked_cb (GtkWidget *button,
1081     EmpathyAccountsDialog *dialog)
1082 {
1083   EmpathyAccountSettings *settings;
1084   gchar     *str;
1085   TpConnectionManager *cm;
1086   TpConnectionManagerProtocol *proto;
1087   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
1088
1089   cm = empathy_protocol_chooser_dup_selected (
1090       EMPATHY_PROTOCOL_CHOOSER (priv->combobox_protocol), &proto);
1091
1092   /* Create account */
1093   /* To translator: %s is the protocol name */
1094   str = g_strdup_printf (_("New %s account"),
1095       empathy_protocol_name_to_display_name (proto->name));
1096
1097   settings = empathy_account_settings_new (cm->name, proto->name, str);
1098
1099   g_free (str);
1100
1101   if (tp_connection_manager_protocol_can_register (proto))
1102     {
1103       gboolean active;
1104
1105       active = gtk_toggle_button_get_active
1106           (GTK_TOGGLE_BUTTON (priv->radiobutton_register));
1107       if (active)
1108         empathy_account_settings_set_boolean (settings, "register", TRUE);
1109     }
1110
1111   accounts_dialog_add (dialog, settings);
1112   accounts_dialog_model_set_selected (dialog, settings);
1113
1114   g_object_unref (settings);
1115   g_object_unref (cm);
1116 }
1117
1118 static void
1119 accounts_dialog_button_back_clicked_cb (GtkWidget *button,
1120     EmpathyAccountsDialog *dialog)
1121 {
1122   EmpathyAccountSettings *settings;
1123
1124   settings = accounts_dialog_model_get_selected_settings (dialog);
1125   accounts_dialog_update_settings (dialog, settings);
1126
1127   if (settings)
1128     g_object_unref (settings);
1129 }
1130
1131 static void
1132 accounts_dialog_button_help_clicked_cb (GtkWidget *button,
1133     EmpathyAccountsDialog *dialog)
1134 {
1135   empathy_url_show (button, "ghelp:empathy?empathy-create-account");
1136 }
1137
1138 static void
1139 accounts_dialog_response_cb (GtkWidget *widget,
1140     gint response,
1141     EmpathyAccountsDialog *dialog)
1142 {
1143   if (response == GTK_RESPONSE_CLOSE)
1144     gtk_widget_destroy (widget);
1145 }
1146
1147 static void
1148 accounts_dialog_destroy_cb (GtkObject *obj,
1149     EmpathyAccountsDialog *dialog)
1150 {
1151   DEBUG ("%p", obj);
1152
1153   g_object_unref (dialog);
1154 }
1155
1156 static void
1157 accounts_dialog_set_selected_account (EmpathyAccountsDialog *dialog,
1158     EmpathyAccount *account)
1159 {
1160   GtkTreeSelection *selection;
1161   GtkTreeIter       iter;
1162   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
1163
1164   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview));
1165   if (accounts_dialog_get_account_iter (dialog, account, &iter))
1166     gtk_tree_selection_select_iter (selection, &iter);
1167 }
1168
1169 static void
1170 accounts_dialog_cms_ready_cb (EmpathyConnectionManagers *cms,
1171     GParamSpec *pspec,
1172     EmpathyAccountsDialog *dialog)
1173 {
1174   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
1175
1176   if (empathy_connection_managers_is_ready (cms))
1177     {
1178       accounts_dialog_update_settings (dialog, NULL);
1179
1180       if (priv->initial_selection != NULL)
1181         {
1182           accounts_dialog_set_selected_account
1183               (dialog, priv->initial_selection);
1184           g_object_unref (priv->initial_selection);
1185           priv->initial_selection = NULL;
1186         }
1187     }
1188 }
1189
1190 static void
1191 accounts_dialog_build_ui (EmpathyAccountsDialog *dialog)
1192 {
1193   GtkBuilder                   *gui;
1194   gchar                        *filename;
1195   EmpathyAccountsDialogPriv    *priv = GET_PRIV (dialog);
1196
1197   filename = empathy_file_lookup ("empathy-accounts-dialog.ui", "src");
1198
1199   gui = empathy_builder_get_file (filename,
1200       "accounts_dialog", &priv->window,
1201       "vbox_details", &priv->vbox_details,
1202       "frame_no_protocol", &priv->frame_no_protocol,
1203       "alignment_settings", &priv->alignment_settings,
1204       "treeview", &priv->treeview,
1205       "frame_new_account", &priv->frame_new_account,
1206       "hbox_type", &priv->hbox_type,
1207       "button_create", &priv->button_create,
1208       "button_back", &priv->button_back,
1209       "radiobutton_reuse", &priv->radiobutton_reuse,
1210       "radiobutton_register", &priv->radiobutton_register,
1211       "image_type", &priv->image_type,
1212       "label_name", &priv->label_name,
1213       "button_add", &priv->button_add,
1214       NULL);
1215   g_free (filename);
1216
1217   empathy_builder_connect (gui, dialog,
1218       "accounts_dialog", "response", accounts_dialog_response_cb,
1219       "accounts_dialog", "destroy", accounts_dialog_destroy_cb,
1220       "button_create", "clicked", accounts_dialog_button_create_clicked_cb,
1221       "button_back", "clicked", accounts_dialog_button_back_clicked_cb,
1222       "button_add", "clicked", accounts_dialog_button_add_clicked_cb,
1223       "button_help", "clicked", accounts_dialog_button_help_clicked_cb,
1224       NULL);
1225
1226   g_object_unref (gui);
1227
1228   priv->combobox_protocol = empathy_protocol_chooser_new ();
1229   gtk_box_pack_start (GTK_BOX (priv->hbox_type),
1230       priv->combobox_protocol,
1231       TRUE, TRUE, 0);
1232   gtk_widget_show (priv->combobox_protocol);
1233   g_signal_connect (priv->combobox_protocol, "changed",
1234       G_CALLBACK (accounts_dialog_protocol_changed_cb),
1235       dialog);
1236
1237   if (priv->parent_window)
1238     gtk_window_set_transient_for (GTK_WINDOW (priv->window),
1239         priv->parent_window);
1240 }
1241
1242 static void
1243 do_dispose (GObject *obj)
1244 {
1245   EmpathyAccountsDialog *dialog = EMPATHY_ACCOUNTS_DIALOG (obj);
1246   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
1247
1248   /* Disconnect signals */
1249   g_signal_handlers_disconnect_by_func (priv->account_manager,
1250       accounts_dialog_account_added_cb,
1251       dialog);
1252   g_signal_handlers_disconnect_by_func (priv->account_manager,
1253       accounts_dialog_account_removed_cb,
1254       dialog);
1255   g_signal_handlers_disconnect_by_func (priv->account_manager,
1256       accounts_dialog_account_enabled_cb,
1257       dialog);
1258   g_signal_handlers_disconnect_by_func (priv->account_manager,
1259       accounts_dialog_account_disabled_cb,
1260       dialog);
1261   g_signal_handlers_disconnect_by_func (priv->account_manager,
1262       accounts_dialog_account_changed_cb,
1263       dialog);
1264   g_signal_handlers_disconnect_by_func (priv->account_manager,
1265       accounts_dialog_connection_changed_cb,
1266       dialog);
1267
1268   if (priv->connecting_id)
1269     g_source_remove (priv->connecting_id);
1270
1271   if (priv->account_manager != NULL)
1272     {
1273       g_object_unref (priv->account_manager);
1274       priv->account_manager = NULL;
1275     }
1276
1277   if (priv->cms != NULL)
1278     {
1279       g_object_unref (priv->cms);
1280       priv->cms = NULL;
1281     }
1282
1283   if (priv->initial_selection != NULL)
1284     g_object_unref (priv->initial_selection);
1285   priv->initial_selection = NULL;
1286
1287   G_OBJECT_CLASS (empathy_accounts_dialog_parent_class)->dispose (obj);
1288 }
1289
1290 static GObject *
1291 do_constructor (GType type,
1292     guint n_props,
1293     GObjectConstructParam *props)
1294 {
1295   GObject *retval;
1296
1297   if (dialog_singleton)
1298     {
1299       retval = G_OBJECT (dialog_singleton);
1300       g_object_ref (retval);
1301     }
1302   else
1303     {
1304       retval =
1305         G_OBJECT_CLASS (empathy_accounts_dialog_parent_class)->constructor
1306             (type, n_props, props);
1307
1308       dialog_singleton = EMPATHY_ACCOUNTS_DIALOG (retval);
1309       g_object_add_weak_pointer (retval, (gpointer) &dialog_singleton);
1310     }
1311
1312   return retval;
1313 }
1314
1315 static void
1316 do_get_property (GObject *object,
1317     guint property_id,
1318     GValue *value,
1319     GParamSpec *pspec)
1320 {
1321   EmpathyAccountsDialogPriv *priv = GET_PRIV (object);
1322
1323   switch (property_id)
1324     {
1325     case PROP_PARENT:
1326       g_value_set_object (value, priv->parent_window);
1327       break;
1328     default:
1329       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1330     }
1331 }
1332
1333 static void
1334 do_set_property (GObject *object,
1335     guint property_id,
1336     const GValue *value,
1337     GParamSpec *pspec)
1338 {
1339   EmpathyAccountsDialogPriv *priv = GET_PRIV (object);
1340
1341   switch (property_id)
1342     {
1343     case PROP_PARENT:
1344       priv->parent_window = g_value_get_object (value);
1345       break;
1346     default:
1347       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1348     }
1349 }
1350
1351 static void
1352 do_constructed (GObject *object)
1353 {
1354   EmpathyAccountsDialog *dialog = EMPATHY_ACCOUNTS_DIALOG (object);
1355   EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog);
1356   GList *accounts, *l;
1357   gboolean import_asked;
1358
1359   accounts_dialog_build_ui (dialog);
1360
1361   /* Set up signalling */
1362   priv->account_manager = empathy_account_manager_dup_singleton ();
1363
1364   g_signal_connect (priv->account_manager, "account-created",
1365       G_CALLBACK (accounts_dialog_account_added_cb),
1366       dialog);
1367   g_signal_connect (priv->account_manager, "account-deleted",
1368       G_CALLBACK (accounts_dialog_account_removed_cb),
1369       dialog);
1370   g_signal_connect (priv->account_manager, "account-enabled",
1371       G_CALLBACK (accounts_dialog_account_enabled_cb),
1372       dialog);
1373   g_signal_connect (priv->account_manager, "account-disabled",
1374       G_CALLBACK (accounts_dialog_account_disabled_cb),
1375       dialog);
1376   g_signal_connect (priv->account_manager, "account-changed",
1377       G_CALLBACK (accounts_dialog_account_changed_cb),
1378       dialog);
1379   g_signal_connect (priv->account_manager, "account-connection-changed",
1380       G_CALLBACK (accounts_dialog_connection_changed_cb),
1381       dialog);
1382
1383   accounts_dialog_model_setup (dialog);
1384
1385   /* Add existing accounts */
1386   accounts = empathy_account_manager_dup_accounts (priv->account_manager);
1387   for (l = accounts; l; l = l->next)
1388     {
1389       accounts_dialog_add_account (dialog, l->data);
1390       g_object_unref (l->data);
1391     }
1392   g_list_free (accounts);
1393
1394   priv->cms = empathy_connection_managers_dup_singleton ();
1395   if (!empathy_connection_managers_is_ready (priv->cms))
1396     g_signal_connect (priv->cms, "notify::ready",
1397         G_CALLBACK (accounts_dialog_cms_ready_cb), dialog);
1398
1399   accounts_dialog_model_select_first (dialog);
1400
1401   empathy_conf_get_bool (empathy_conf_get (),
1402       EMPATHY_PREFS_IMPORT_ASKED, &import_asked);
1403
1404
1405   if (empathy_import_accounts_to_import ())
1406     {
1407
1408       if (!import_asked)
1409         {
1410           GtkWidget *import_dialog;
1411
1412           empathy_conf_set_bool (empathy_conf_get (),
1413               EMPATHY_PREFS_IMPORT_ASKED, TRUE);
1414           import_dialog = empathy_import_dialog_new (GTK_WINDOW (priv->window),
1415               FALSE);
1416           gtk_widget_show (import_dialog);
1417         }
1418     }
1419 }
1420
1421 static void
1422 empathy_accounts_dialog_class_init (EmpathyAccountsDialogClass *klass)
1423 {
1424   GObjectClass *oclass = G_OBJECT_CLASS (klass);
1425   GParamSpec *param_spec;
1426
1427   oclass->constructor = do_constructor;
1428   oclass->dispose = do_dispose;
1429   oclass->constructed = do_constructed;
1430   oclass->set_property = do_set_property;
1431   oclass->get_property = do_get_property;
1432
1433   param_spec = g_param_spec_object ("parent",
1434       "parent", "The parent window",
1435       GTK_TYPE_WINDOW,
1436       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
1437   g_object_class_install_property (oclass, PROP_PARENT, param_spec);
1438
1439   g_type_class_add_private (klass, sizeof (EmpathyAccountsDialogPriv));
1440 }
1441
1442 static void
1443 empathy_accounts_dialog_init (EmpathyAccountsDialog *dialog)
1444 {
1445   EmpathyAccountsDialogPriv *priv;
1446
1447   priv = G_TYPE_INSTANCE_GET_PRIVATE ((dialog),
1448       EMPATHY_TYPE_ACCOUNTS_DIALOG,
1449       EmpathyAccountsDialogPriv);
1450   dialog->priv = priv;
1451 }
1452
1453 /* public methods */
1454
1455 GtkWidget *
1456 empathy_accounts_dialog_show (GtkWindow *parent,
1457     EmpathyAccount *selected_account)
1458 {
1459   EmpathyAccountsDialog *dialog;
1460   EmpathyAccountsDialogPriv *priv;
1461
1462   dialog = g_object_new (EMPATHY_TYPE_ACCOUNTS_DIALOG,
1463       "parent", parent, NULL);
1464
1465   priv = GET_PRIV (dialog);
1466
1467   if (selected_account)
1468     {
1469       if (empathy_connection_managers_is_ready (priv->cms))
1470         accounts_dialog_set_selected_account (dialog, selected_account);
1471       else
1472         /* save the selection to set it later when the cms
1473          * becomes ready.
1474          */
1475         priv->initial_selection = g_object_ref (selected_account);
1476     }
1477
1478   gtk_window_present (GTK_WINDOW (priv->window));
1479
1480   return priv->window;
1481 }