]> git.0d.be Git - empathy.git/blob - src/empathy-import-widget.c
include telepathy-glib.h
[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 <config.h>
26
27 #include "empathy-import-dialog.h"
28 #include "empathy-import-widget.h"
29 #include "empathy-import-pidgin.h"
30
31 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER
32 #include <libempathy/empathy-debug.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/telepathy-glib.h>
39
40 #include <glib/gi18n-lib.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 enum {
57   PROP_APPLICATION_ID = 1,
58   PROP_CMS
59 };
60
61 typedef struct {
62   GtkWidget *vbox;
63   GtkWidget *treeview;
64   GtkWidget *scrolledwindow;
65
66   GList *accounts;
67   EmpathyImportApplication app_id;
68
69   EmpathyConnectionManagers *cms;
70
71   gboolean dispose_run;
72 } EmpathyImportWidgetPriv;
73
74 static gboolean
75 import_widget_account_id_in_list (GList *accounts,
76     const gchar *account_id)
77 {
78   GList *l;
79
80   for (l = accounts; l; l = l->next)
81     {
82       TpAccount *account = l->data;
83       const GHashTable *parameters;
84
85       parameters = tp_account_get_parameters (account);
86
87       if (!tp_strdiff (tp_asv_get_string (parameters, "account"), account_id))
88         return TRUE;
89     }
90
91   return FALSE;
92 }
93
94 #define MAX_TREEVIEW_HEIGHT 300
95
96 static void
97 import_widget_add_accounts_to_model (EmpathyImportWidget *self)
98 {
99   TpAccountManager *manager;
100   GtkTreeModel *model;
101   GList *l;
102   EmpathyImportWidgetPriv *priv = GET_PRIV (self);
103   gint min, natural;
104
105   manager = tp_account_manager_dup ();
106
107   model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
108
109   for (l = priv->accounts; l; l = l->next)
110     {
111       GValue *value;
112       EmpathyImportAccountData *data = l->data;
113       gboolean import;
114       GList *accounts;
115       TpConnectionManager *cm = NULL;
116
117       if (!empathy_import_protocol_is_supported (data->protocol, &cm))
118         continue;
119
120       data->connection_manager = g_strdup (
121           tp_connection_manager_get_name (cm));
122
123       value = g_hash_table_lookup (data->settings, "account");
124
125       accounts = tp_account_manager_dup_valid_accounts (manager);
126
127       /* Only set the "Import" cell to be active if there isn't already an
128        * account set up with the same account id. */
129       import = !import_widget_account_id_in_list (accounts,
130           g_value_get_string (value));
131
132       g_list_free_full (accounts, g_object_unref);
133
134       gtk_list_store_insert_with_values (GTK_LIST_STORE (model), NULL, -1,
135           COL_IMPORT, import,
136           COL_PROTOCOL, data->protocol,
137           COL_NAME, g_value_get_string (value),
138           COL_SOURCE, data->source,
139           COL_ACCOUNT_DATA, data,
140           -1);
141
142     }
143
144   /* Display as much rows as possible */
145   gtk_widget_get_preferred_height (priv->treeview, &min, &natural);
146   gtk_widget_set_size_request (priv->scrolledwindow, -1,
147       MIN (natural, MAX_TREEVIEW_HEIGHT));
148
149   g_object_unref (manager);
150 }
151
152 static void
153 import_widget_create_account_cb (GObject *source,
154   GAsyncResult *result,
155   gpointer user_data)
156 {
157   TpAccountManager *account_manager;
158   TpAccount *account;
159   GError *error = NULL;
160   EmpathyImportWidget *self = user_data;
161
162   account = tp_account_manager_create_account_finish (
163     TP_ACCOUNT_MANAGER (source), result, &error);
164
165   if (account == NULL)
166     {
167       DEBUG ("Failed to create account: %s",
168           error ? error->message : "No error given");
169       g_clear_error (&error);
170       return;
171     }
172
173   DEBUG ("account created\n");
174
175   if (tp_account_is_enabled (account))
176     {
177       account_manager = tp_account_manager_dup ();
178       empathy_connect_new_account (account, account_manager);
179       g_object_unref (account_manager);
180     }
181
182   g_object_unref (self);
183 }
184
185 static void
186 import_widget_add_account (EmpathyImportWidget *self,
187     EmpathyImportAccountData *data)
188 {
189   TpAccountManager *account_manager;
190   gchar *display_name = NULL;
191   GHashTable *properties;
192   GValue *username;
193
194   account_manager = tp_account_manager_dup ();
195
196   DEBUG ("connection_manager: %s\n", data->connection_manager);
197
198   /* Set the display name of the account */
199   username = g_hash_table_lookup (data->settings, "account");
200
201   if (!tp_strdiff (data->protocol, "irc"))
202     {
203       const gchar *server;
204
205       server = tp_asv_get_string (data->settings, "server");
206
207       if (server != NULL)
208         display_name = g_strdup_printf ("%s on %s",
209             g_value_get_string (username), server);
210     }
211
212   if (display_name == NULL)
213     {
214       display_name = g_strdup_printf ("%s (%s)",
215           data->protocol, g_value_get_string (username));
216     }
217
218   DEBUG ("display name: %s\n", display_name);
219
220   properties = tp_asv_new (NULL, NULL);
221   tp_asv_set_boolean (properties, TP_IFACE_ACCOUNT ".Enabled", data->enabled);
222
223   tp_account_manager_create_account_async (account_manager,
224       (const gchar*) data->connection_manager, data->protocol, display_name,
225       data->settings, properties, import_widget_create_account_cb,
226       g_object_ref (self));
227
228   g_hash_table_unref (properties);
229   g_free (display_name);
230   g_object_unref (account_manager);
231 }
232
233 static gboolean
234 import_widget_tree_model_foreach (GtkTreeModel *model,
235     GtkTreePath *path,
236     GtkTreeIter *iter,
237     gpointer user_data)
238 {
239   gboolean to_import;
240   EmpathyImportAccountData *data;
241   EmpathyImportWidget *self = user_data;
242
243   gtk_tree_model_get (model, iter,
244       COL_IMPORT, &to_import,
245       COL_ACCOUNT_DATA, &data,
246       -1);
247
248   if (to_import)
249     import_widget_add_account (self, data);
250
251   return FALSE;
252 }
253
254 static void
255 import_widget_cell_toggled_cb (GtkCellRendererToggle *cell_renderer,
256     const gchar *path_str,
257     EmpathyImportWidget *self)
258 {
259   GtkTreeModel *model;
260   GtkTreeIter iter;
261   GtkTreePath *path;
262   EmpathyImportWidgetPriv *priv = GET_PRIV (self);
263
264   path = gtk_tree_path_new_from_string (path_str);
265   model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
266
267   gtk_tree_model_get_iter (model, &iter, path);
268
269   gtk_list_store_set (GTK_LIST_STORE (model), &iter,
270       COL_IMPORT, !gtk_cell_renderer_toggle_get_active (cell_renderer),
271       -1);
272
273   gtk_tree_path_free (path);
274 }
275
276 static void
277 import_widget_set_up_account_list (EmpathyImportWidget *self)
278 {
279   EmpathyImportWidgetPriv *priv = GET_PRIV (self);
280   GtkListStore *store;
281   GtkTreeView *view;
282   GtkTreeViewColumn *column;
283   GtkCellRenderer *cell;
284
285   priv->accounts = empathy_import_accounts_load (priv->app_id);
286
287   store = gtk_list_store_new (COL_COUNT, G_TYPE_BOOLEAN, G_TYPE_STRING,
288       G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
289
290   gtk_tree_view_set_model (GTK_TREE_VIEW (priv->treeview),
291       GTK_TREE_MODEL (store));
292
293   g_object_unref (store);
294
295   view = GTK_TREE_VIEW (priv->treeview);
296   gtk_tree_view_set_headers_visible (view, TRUE);
297
298   /* Import column */
299   cell = gtk_cell_renderer_toggle_new ();
300   gtk_tree_view_insert_column_with_attributes (view, -1,
301       /* Translators: this is the header of a treeview column */
302       _("Import"), cell,
303       "active", COL_IMPORT,
304       NULL);
305
306   g_signal_connect (cell, "toggled",
307       G_CALLBACK (import_widget_cell_toggled_cb), self);
308
309   /* Protocol column */
310   column = gtk_tree_view_column_new ();
311   gtk_tree_view_column_set_title (column, _("Protocol"));
312   gtk_tree_view_column_set_expand (column, TRUE);
313   gtk_tree_view_append_column (view, column);
314
315   cell = gtk_cell_renderer_text_new ();
316   g_object_set (cell, "editable", FALSE, NULL);
317   gtk_tree_view_column_pack_start (column, cell, TRUE);
318   gtk_tree_view_column_add_attribute (column, cell, "text", COL_PROTOCOL);
319
320   /* Account column */
321   column = gtk_tree_view_column_new ();
322   gtk_tree_view_column_set_title (column, _("Account"));
323   gtk_tree_view_column_set_expand (column, TRUE);
324   gtk_tree_view_append_column (view, column);
325
326   cell = gtk_cell_renderer_text_new ();
327   g_object_set (cell, "editable", FALSE, NULL);
328   gtk_tree_view_column_pack_start (column, cell, TRUE);
329   gtk_tree_view_column_add_attribute (column, cell, "text", COL_NAME);
330
331   if (priv->app_id == EMPATHY_IMPORT_APPLICATION_ALL)
332     {
333       /* Source column */
334       column = gtk_tree_view_column_new ();
335       gtk_tree_view_column_set_title (column, _("Source"));
336       gtk_tree_view_column_set_expand (column, TRUE);
337       gtk_tree_view_append_column (view, column);
338
339       cell = gtk_cell_renderer_text_new ();
340       g_object_set (cell, "editable", FALSE, NULL);
341       gtk_tree_view_column_pack_start (column, cell, TRUE);
342       gtk_tree_view_column_add_attribute (column, cell, "text", COL_SOURCE);
343     }
344
345   import_widget_add_accounts_to_model (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_get_property (GObject *object,
357     guint property_id,
358     GValue *value,
359     GParamSpec *pspec)
360 {
361   EmpathyImportWidgetPriv *priv = GET_PRIV (object);
362
363   switch (property_id)
364     {
365     case PROP_APPLICATION_ID:
366       g_value_set_int (value, priv->app_id);
367       break;
368     case PROP_CMS:
369       g_value_set_object (value, priv->cms);
370       break;
371     default:
372       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
373     }
374 }
375
376 static void
377 do_set_property (GObject *object,
378     guint property_id,
379     const GValue *value,
380     GParamSpec *pspec)
381 {
382   EmpathyImportWidgetPriv *priv = GET_PRIV (object);
383
384   switch (property_id)
385     {
386     case PROP_APPLICATION_ID:
387       priv->app_id = g_value_get_int (value);
388       break;
389     case PROP_CMS:
390       priv->cms = g_value_dup_object (value);
391       break;
392     default:
393       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
394     }
395 }
396
397 static void
398 do_finalize (GObject *obj)
399 {
400   EmpathyImportWidgetPriv *priv = GET_PRIV (obj);
401
402   g_list_foreach (priv->accounts, (GFunc) empathy_import_account_data_free,
403       NULL);
404   g_list_free (priv->accounts);
405
406   if (G_OBJECT_CLASS (empathy_import_widget_parent_class)->finalize != NULL)
407     G_OBJECT_CLASS (empathy_import_widget_parent_class)->finalize (obj);
408 }
409
410 static void
411 do_dispose (GObject *obj)
412 {
413   EmpathyImportWidgetPriv *priv = GET_PRIV (obj);
414
415   if (priv->dispose_run)
416     return;
417
418   priv->dispose_run = TRUE;
419
420   if (priv->cms != NULL)
421     {
422       g_object_unref (priv->cms);
423       priv->cms = NULL;
424     }
425
426   if (G_OBJECT_CLASS (empathy_import_widget_parent_class)->dispose != NULL)
427     G_OBJECT_CLASS (empathy_import_widget_parent_class)->dispose (obj);
428 }
429
430 static void
431 do_constructed (GObject *obj)
432 {
433   EmpathyImportWidget *self = EMPATHY_IMPORT_WIDGET (obj);
434   EmpathyImportWidgetPriv *priv = GET_PRIV (self);
435   GtkBuilder *gui;
436   gchar *filename;
437
438   filename = empathy_file_lookup ("empathy-import-dialog.ui", "src");
439   gui = empathy_builder_get_file (filename,
440       "widget_vbox", &priv->vbox,
441       "treeview", &priv->treeview,
442       "scrolledwindow", &priv->scrolledwindow,
443       NULL);
444
445   g_free (filename);
446   empathy_builder_unref_and_keep_widget (gui, priv->vbox);
447
448   g_signal_connect (priv->vbox, "destroy",
449       G_CALLBACK (import_widget_destroy_cb), self);
450
451   import_widget_set_up_account_list (self);
452 }
453
454 static void
455 empathy_import_widget_class_init (EmpathyImportWidgetClass *klass)
456 {
457   GObjectClass *oclass = G_OBJECT_CLASS (klass);
458   GParamSpec *param_spec;
459
460   oclass->constructed = do_constructed;
461   oclass->finalize = do_finalize;
462   oclass->dispose = do_dispose;
463   oclass->set_property = do_set_property;
464   oclass->get_property = do_get_property;
465
466   param_spec = g_param_spec_int ("application-id",
467       "application-id", "The application id to import from",
468       0, EMPATHY_IMPORT_APPLICATION_INVALID, EMPATHY_IMPORT_APPLICATION_ALL,
469       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
470   g_object_class_install_property (oclass, PROP_APPLICATION_ID, param_spec);
471
472   param_spec = g_param_spec_object ("cms",
473       "EmpathyConnectionManagers", "EmpathyConnectionManager",
474       EMPATHY_TYPE_CONNECTION_MANAGERS,
475       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
476   g_object_class_install_property (oclass, PROP_CMS, param_spec);
477
478   g_type_class_add_private (klass, sizeof (EmpathyImportWidgetPriv));
479 }
480
481 static void
482 empathy_import_widget_init (EmpathyImportWidget *self)
483 {
484   EmpathyImportWidgetPriv *priv =
485     G_TYPE_INSTANCE_GET_PRIVATE (self, EMPATHY_TYPE_IMPORT_WIDGET,
486         EmpathyImportWidgetPriv);
487
488   self->priv = priv;
489 }
490
491 EmpathyImportWidget *
492 empathy_import_widget_new (EmpathyImportApplication id,
493     EmpathyConnectionManagers *cms)
494 {
495   g_return_val_if_fail (EMPATHY_IS_CONNECTION_MANAGERS (cms), NULL);
496
497   return g_object_new (EMPATHY_TYPE_IMPORT_WIDGET,
498       "application-id", id,
499       "cms", cms,
500       NULL);
501 }
502
503 GtkWidget *
504 empathy_import_widget_get_widget (EmpathyImportWidget *self)
505 {
506   EmpathyImportWidgetPriv *priv = GET_PRIV (self);
507
508   return priv->vbox;
509 }
510
511 void
512 empathy_import_widget_add_selected_accounts (EmpathyImportWidget *self)
513 {
514   GtkTreeModel *model;
515   EmpathyImportWidgetPriv *priv = GET_PRIV (self);
516
517   model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview));
518   gtk_tree_model_foreach (model, import_widget_tree_model_foreach, self);
519 }