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