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