]> git.0d.be Git - empathy.git/blob - src/empathy-import-widget.c
d276c03e51ff53803edc9a68605d6218eef7192a
[empathy.git] / src / empathy-import-widget.c
1 /*
2  * Copyright (C) 2008-2009 Collabora Ltd.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public
15  * License along with this program; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17  * Boston, MA  02110-1301  USA
18  *
19  * Authors: Jonny Lamb <jonny.lamb@collabora.co.uk>
20  *          Cosimo Cecchi <cosimo.cecchi@collabora.co.uk>
21  */
22
23 /* empathy-import-widget.c */
24
25 #include "empathy-import-dialog.h"
26 #include "empathy-import-widget.h"
27 #include "empathy-import-pidgin.h"
28
29 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER
30 #include <libempathy/empathy-debug.h>
31 #include <libempathy/empathy-account.h>
32 #include <libempathy/empathy-account-manager.h>
33 #include <libempathy/empathy-connection-managers.h>
34 #include <libempathy/empathy-utils.h>
35
36 #include <libempathy-gtk/empathy-ui-utils.h>
37
38 #include <telepathy-glib/util.h>
39
40 #include <glib/gi18n.h>
41
42 G_DEFINE_TYPE (EmpathyImportWidget, empathy_import_widget, G_TYPE_OBJECT)
43
44 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyImportWidget)
45
46 enum
47 {
48   COL_IMPORT = 0,
49   COL_PROTOCOL,
50   COL_NAME,
51   COL_SOURCE,
52   COL_ACCOUNT_DATA,
53   COL_COUNT
54 };
55
56 typedef struct {
57   GtkWidget *vbox;
58   GtkWidget *treeview;
59
60   GList *accounts;
61
62   EmpathyConnectionManagers *cms;
63
64   gboolean dispose_run;
65 } EmpathyImportWidgetPriv;
66
67 static gboolean
68 import_widget_account_id_in_list (GList *accounts,
69     const gchar *account_id)
70 {
71   GList *l;
72
73   for (l = accounts; l; l = l->next)
74     {
75       EmpathyAccount *account = l->data;
76       const gchar *account_string;
77       GValue *value;
78       gboolean result;
79       const GHashTable *parameters;
80
81       parameters = empathy_account_get_parameters (account);
82
83       value = g_hash_table_lookup ((GHashTable *)parameters, "account");
84
85       if (value == NULL)
86         continue;
87
88       account_string = g_value_get_string (value);
89
90       result = tp_strdiff (account_string, account_id);
91
92       if (!result)
93         return TRUE;
94     }
95
96   return FALSE;
97 }
98
99 static gboolean
100 protocol_is_supported (EmpathyImportWidget *self,
101     EmpathyImportAccountData *data)
102 {
103   EmpathyImportWidgetPriv *priv = GET_PRIV (self);
104   GList *cms = empathy_connection_managers_get_cms (priv->cms);
105   GList *l;
106   gboolean proto_is_supported = FALSE;
107
108   for (l = cms; l; l = l->next)
109     {
110       TpConnectionManager *tp_cm = l->data;
111       const gchar *cm_name = tp_connection_manager_get_name (tp_cm);
112       if (tp_connection_manager_has_protocol (tp_cm,
113           (const gchar*) data->protocol))
114         {
115           data->connection_manager = g_strdup (cm_name);
116           proto_is_supported = TRUE;
117           break;
118         }
119     }
120
121   return proto_is_supported;
122 }
123
124 static void
125 import_widget_add_accounts_to_model (EmpathyImportWidget *self)
126 {
127   GtkTreeModel *model;
128   GtkTreeIter iter;
129   GList *l;
130   EmpathyImportWidgetPriv *priv = GET_PRIV (self);
131   EmpathyAccountManager *manager = empathy_account_manager_dup_singleton ();
132
133   model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
134
135   for (l = priv->accounts; l; l = l->next)
136     {
137       GValue *value;
138       EmpathyImportAccountData *data = l->data;
139       gboolean import;
140       GList *accounts;
141
142       if (!protocol_is_supported (self, data))
143         continue;
144
145       value = g_hash_table_lookup (data->settings, "account");
146
147       accounts = empathy_account_manager_dup_accounts (manager);
148
149       /* Only set the "Import" cell to be active if there isn't already an
150        * account set up with the same account id. */
151       import = !import_widget_account_id_in_list (accounts,
152           g_value_get_string (value));
153
154       g_list_foreach (accounts, (GFunc) g_object_unref, NULL);
155       g_list_free (accounts);
156
157       gtk_list_store_append (GTK_LIST_STORE (model), &iter);
158
159       gtk_list_store_set (GTK_LIST_STORE (model), &iter,
160           COL_IMPORT, import,
161           COL_PROTOCOL, data->protocol,
162           COL_NAME, g_value_get_string (value),
163           COL_SOURCE, data->source,
164           COL_ACCOUNT_DATA, data,
165           -1);
166     }
167
168   g_object_unref (manager);
169 }
170
171 static void
172 import_widget_create_account_cb (GObject *source,
173   GAsyncResult *result,
174   gpointer user_data)
175 {
176   EmpathyAccount *account;
177   GError *error = NULL;
178   EmpathyImportWidget *self = user_data;
179
180   account = empathy_account_manager_create_account_finish (
181     EMPATHY_ACCOUNT_MANAGER (source), result, &error);
182
183   if (account == NULL)
184     {
185       DEBUG ("Failed to create account: %s",
186           error ? error->message : "No error given");
187       g_clear_error (&error);
188       return;
189     }
190
191   DEBUG ("account created\n");
192
193   g_object_unref (self);
194 }
195
196 static void
197 import_widget_add_account (EmpathyImportWidget *self,
198     EmpathyImportAccountData *data)
199 {
200   EmpathyAccountManager *account_manager;
201   gchar *display_name;
202   GHashTable *properties;
203   GValue *username;
204
205   account_manager = empathy_account_manager_dup_singleton ();
206
207   DEBUG ("connection_manager: %s\n", data->connection_manager);
208
209   /* Set the display name of the account */
210   username = g_hash_table_lookup (data->settings, "account");
211   display_name = g_strdup_printf ("%s (%s)",
212       data->protocol,
213       g_value_get_string (username));
214
215   DEBUG ("display name: %s\n", display_name);
216
217   properties = g_hash_table_new (NULL, NULL);
218
219   empathy_account_manager_create_account_async (account_manager,
220       (const gchar*) data->connection_manager, data->protocol, display_name,
221       data->settings, properties, import_widget_create_account_cb,
222       g_object_ref (self));
223
224   g_hash_table_unref (properties);
225   g_free (display_name);
226   g_object_unref (account_manager);
227 }
228
229 static gboolean
230 import_widget_tree_model_foreach (GtkTreeModel *model,
231     GtkTreePath *path,
232     GtkTreeIter *iter,
233     gpointer user_data)
234 {
235   gboolean to_import;
236   EmpathyImportAccountData *data;
237   EmpathyImportWidget *self = user_data;
238
239   gtk_tree_model_get (model, iter,
240       COL_IMPORT, &to_import,
241       COL_ACCOUNT_DATA, &data,
242       -1);
243
244   if (to_import)
245     import_widget_add_account (self, data);
246
247   return FALSE;
248 }
249
250 static void
251 import_widget_cell_toggled_cb (GtkCellRendererToggle *cell_renderer,
252     const gchar *path_str,
253     EmpathyImportWidget *self)
254 {
255   GtkTreeModel *model;
256   GtkTreeIter iter;
257   GtkTreePath *path;
258   EmpathyImportWidgetPriv *priv = GET_PRIV (self);
259
260   path = gtk_tree_path_new_from_string (path_str);
261   model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
262
263   gtk_tree_model_get_iter (model, &iter, path);
264
265   gtk_list_store_set (GTK_LIST_STORE (model), &iter,
266       COL_IMPORT, !gtk_cell_renderer_toggle_get_active (cell_renderer),
267       -1);
268
269   gtk_tree_path_free (path);
270 }
271
272 static void
273 import_widget_set_up_account_list (EmpathyImportWidget *self)
274 {
275   EmpathyImportWidgetPriv *priv = GET_PRIV (self);
276   GtkListStore *store;
277   GtkTreeView *view;
278   GtkTreeViewColumn *column;
279   GtkCellRenderer *cell;
280
281   store = gtk_list_store_new (COL_COUNT, G_TYPE_BOOLEAN, G_TYPE_STRING,
282       G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
283
284   gtk_tree_view_set_model (GTK_TREE_VIEW (priv->treeview),
285       GTK_TREE_MODEL (store));
286
287   g_object_unref (store);
288
289   view = GTK_TREE_VIEW (priv->treeview);
290   gtk_tree_view_set_headers_visible (view, TRUE);
291
292   /* Import column */
293   cell = gtk_cell_renderer_toggle_new ();
294   gtk_tree_view_insert_column_with_attributes (view, -1,
295       /* Translators: this is the header of a treeview column */
296       _("Import"), cell,
297       "active", COL_IMPORT,
298       NULL);
299
300   g_signal_connect (cell, "toggled",
301       G_CALLBACK (import_widget_cell_toggled_cb), self);
302
303   /* Protocol column */
304   column = gtk_tree_view_column_new ();
305   gtk_tree_view_column_set_title (column, _("Protocol"));
306   gtk_tree_view_column_set_expand (column, TRUE);
307   gtk_tree_view_append_column (view, column);
308
309   cell = gtk_cell_renderer_text_new ();
310   g_object_set (cell, "editable", FALSE, NULL);
311   gtk_tree_view_column_pack_start (column, cell, TRUE);
312   gtk_tree_view_column_add_attribute (column, cell, "text", COL_PROTOCOL);
313
314   /* Account column */
315   column = gtk_tree_view_column_new ();
316   gtk_tree_view_column_set_title (column, _("Account"));
317   gtk_tree_view_column_set_expand (column, TRUE);
318   gtk_tree_view_append_column (view, column);
319
320   cell = gtk_cell_renderer_text_new ();
321   g_object_set (cell, "editable", FALSE, NULL);
322   gtk_tree_view_column_pack_start (column, cell, TRUE);
323   gtk_tree_view_column_add_attribute (column, cell, "text", COL_NAME);
324
325   /* Source column */
326   column = gtk_tree_view_column_new ();
327   gtk_tree_view_column_set_title (column, _("Source"));
328   gtk_tree_view_column_set_expand (column, TRUE);
329   gtk_tree_view_append_column (view, column);
330
331   cell = gtk_cell_renderer_text_new ();
332   g_object_set (cell, "editable", FALSE, NULL);
333   gtk_tree_view_column_pack_start (column, cell, TRUE);
334   gtk_tree_view_column_add_attribute (column, cell, "text", COL_SOURCE);
335
336   import_widget_add_accounts_to_model (self);
337 }
338
339 static void
340 import_widget_cms_ready_cb (EmpathyConnectionManagers *cms,
341     GParamSpec *pspec,
342     EmpathyImportWidget *self)
343 {
344   if (empathy_connection_managers_is_ready (cms))
345     import_widget_set_up_account_list (self);
346 }
347
348 static void
349 import_widget_destroy_cb (GtkWidget *w,
350     EmpathyImportWidget *self)
351 {
352   g_object_unref (self);
353 }
354
355 static void
356 do_finalize (GObject *obj)
357 {
358   EmpathyImportWidgetPriv *priv = GET_PRIV (obj);
359
360   g_list_foreach (priv->accounts, (GFunc) empathy_import_account_data_free,
361       NULL);
362   g_list_free (priv->accounts);
363
364   if (G_OBJECT_CLASS (empathy_import_widget_parent_class)->finalize != NULL)
365     G_OBJECT_CLASS (empathy_import_widget_parent_class)->finalize (obj);
366 }
367
368 static void
369 do_dispose (GObject *obj)
370 {
371   EmpathyImportWidgetPriv *priv = GET_PRIV (obj);
372
373   if (priv->dispose_run)
374     return;
375
376   priv->dispose_run = TRUE;
377
378   if (priv->cms != NULL)
379     {
380       g_object_unref (priv->cms);
381       priv->cms = NULL;
382     }
383
384   if (G_OBJECT_CLASS (empathy_import_widget_parent_class)->dispose != NULL)
385     G_OBJECT_CLASS (empathy_import_widget_parent_class)->dispose (obj);
386 }
387
388 static void
389 do_constructed (GObject *obj)
390 {
391   EmpathyImportWidget *self = EMPATHY_IMPORT_WIDGET (obj);
392   EmpathyImportWidgetPriv *priv = GET_PRIV (self);
393   GtkBuilder *gui;
394   gchar *filename;
395
396   filename = empathy_file_lookup ("empathy-import-dialog.ui", "src");
397   gui = empathy_builder_get_file (filename,
398       "widget_vbox", &priv->vbox,
399       "treeview", &priv->treeview,
400       NULL);
401
402   g_free (filename);
403   empathy_builder_unref_and_keep_widget (gui, priv->vbox);
404
405   g_signal_connect (priv->vbox, "destroy",
406       G_CALLBACK (import_widget_destroy_cb), self);
407
408   if (empathy_connection_managers_is_ready (priv->cms))
409     import_widget_set_up_account_list (self);
410   else
411     g_signal_connect (priv->cms, "notify::ready",
412         G_CALLBACK (import_widget_cms_ready_cb), self);
413 }
414
415 static void
416 empathy_import_widget_class_init (EmpathyImportWidgetClass *klass)
417 {
418   GObjectClass *oclass = G_OBJECT_CLASS (klass);
419
420   oclass->constructed = do_constructed;
421   oclass->finalize = do_finalize;
422   oclass->dispose = do_dispose;
423
424   g_type_class_add_private (klass, sizeof (EmpathyImportWidgetPriv));
425 }
426
427 static void
428 empathy_import_widget_init (EmpathyImportWidget *self)
429 {
430   EmpathyImportWidgetPriv *priv =
431     G_TYPE_INSTANCE_GET_PRIVATE (self, EMPATHY_TYPE_IMPORT_WIDGET,
432         EmpathyImportWidgetPriv);
433
434   self->priv = priv;
435
436   /* Load all accounts from all supported applications */
437   priv->accounts = empathy_import_pidgin_load ();
438
439   priv->cms = empathy_connection_managers_dup_singleton ();
440 }
441
442 EmpathyImportWidget *
443 empathy_import_widget_new (void)
444 {
445   return g_object_new (EMPATHY_TYPE_IMPORT_WIDGET, NULL);
446 }
447
448 GtkWidget *
449 empathy_import_widget_get_widget (EmpathyImportWidget *self)
450 {
451   EmpathyImportWidgetPriv *priv = GET_PRIV (self);
452
453   return priv->vbox;
454 }
455
456 void
457 empathy_import_widget_add_selected_accounts (EmpathyImportWidget *self)
458 {
459   GtkTreeModel *model;
460   EmpathyImportWidgetPriv *priv = GET_PRIV (self);
461
462   model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
463   gtk_tree_model_foreach (model, import_widget_tree_model_foreach, self);
464 }