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