]> git.0d.be Git - empathy.git/blob - ubuntu-online-accounts/cc-plugins/account-plugins/empathy-accounts-plugin-widget.c
use tp_account_manager_dup_valid_accounts()
[empathy.git] / ubuntu-online-accounts / cc-plugins / account-plugins / empathy-accounts-plugin-widget.c
1 /*
2  * empathy-accounts-plugin-widget.c
3  *
4  * Copyright (C) 2012 Collabora Ltd. <http://www.collabora.co.uk/>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20
21
22 #include "config.h"
23
24 #include "empathy-accounts-plugin-widget.h"
25
26 #include <glib/gi18n-lib.h>
27
28 #include <telepathy-glib/telepathy-glib.h>
29
30 #include <libaccounts-glib/ag-service.h>
31 #include <libaccounts-glib/ag-account-service.h>
32
33 #include <libempathy-gtk/empathy-account-widget.h>
34
35 G_DEFINE_TYPE (EmpathyAccountsPluginWidget, empathy_accounts_plugin_widget, GTK_TYPE_BOX)
36
37 enum
38 {
39   PROP_ACCOUNT = 1,
40   N_PROPS
41 };
42
43 enum
44 {
45   SIG_DONE,
46   LAST_SIGNAL
47 };
48
49 static guint signals[LAST_SIGNAL];
50
51 struct _EmpathyAccountsPluginWidgetPriv
52 {
53   AgAccount *account;
54
55   EmpathyAccountSettings *settings;
56
57   EmpathyAccountWidget *account_widget;
58   GtkWidget *done_button;
59 };
60
61 static void
62 empathy_accounts_plugin_widget_get_property (GObject *object,
63     guint property_id,
64     GValue *value,
65     GParamSpec *pspec)
66 {
67   EmpathyAccountsPluginWidget *self = EMPATHY_ACCOUNTS_PLUGIN_WIDGET (object);
68
69   switch (property_id)
70     {
71       case PROP_ACCOUNT:
72         g_value_set_object (value, self->priv->account);
73         break;
74       default:
75         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
76         break;
77     }
78 }
79
80 static void
81 empathy_accounts_plugin_widget_set_property (GObject *object,
82     guint property_id,
83     const GValue *value,
84     GParamSpec *pspec)
85 {
86   EmpathyAccountsPluginWidget *self = EMPATHY_ACCOUNTS_PLUGIN_WIDGET (object);
87
88   switch (property_id)
89     {
90       case PROP_ACCOUNT:
91         self->priv->account = g_value_dup_object (value);
92         break;
93       default:
94         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
95         break;
96     }
97 }
98
99 static EmpathyAccountSettings *
100 create_account_settings (AgAccount *account)
101 {
102   AgService *service;
103   GList *services;
104   AgAccountService *account_service;
105   GValue v = G_VALUE_INIT;
106   gchar *manager = NULL, *protocol = NULL;
107   EmpathyAccountSettings *settings;
108
109   g_assert (account->id == 0);
110
111   services = ag_account_list_services_by_type (account, "IM");
112   g_return_val_if_fail (services != NULL, NULL);
113   service = (AgService *) services->data;
114
115   account_service = ag_account_service_new (account, service);
116
117   g_value_init (&v, G_TYPE_STRING);
118   if (ag_account_service_get_value (account_service,
119         "telepathy/manager", &v) != AG_SETTING_SOURCE_NONE)
120     manager = g_value_dup_string (&v);
121   g_value_unset (&v);
122
123   g_value_init (&v, G_TYPE_STRING);
124   if (ag_account_service_get_value (account_service,
125         "telepathy/protocol", &v) != AG_SETTING_SOURCE_NONE)
126     protocol = g_value_dup_string (&v);
127   g_value_unset (&v);
128
129   g_return_val_if_fail (manager != NULL, NULL);
130   g_return_val_if_fail (protocol != NULL, NULL);
131
132   settings = empathy_account_settings_new (manager, protocol, NULL,
133       ag_service_get_display_name (service));
134
135   empathy_account_settings_set_storage_provider (settings,
136       EMPATHY_UOA_PROVIDER);
137
138   empathy_account_settings_set_icon_name_async (settings,
139     ag_service_get_icon_name (service), NULL, NULL);
140
141   g_free (manager);
142   g_free (protocol);
143
144   return settings;
145 }
146
147 static void
148 response_cb (GtkWidget *widget,
149     gint response,
150     EmpathyAccountsPluginWidget *self)
151 {
152   if (response == GTK_RESPONSE_OK)
153     {
154       empathy_account_widget_apply_and_log_in (self->priv->account_widget);
155
156       /* Rely on account_widget_close_cb to fire the 'done' signal */
157     }
158   else
159     {
160       empathy_account_widget_discard_pending_changes (
161           self->priv->account_widget);
162
163       g_signal_emit (self, signals[SIG_DONE], 0);
164     }
165 }
166
167 static GtkWidget *
168 create_top_bar (EmpathyAccountsPluginWidget *self)
169 {
170   GtkWidget *bar, *content, *action, *label;
171   GtkCssProvider *css;
172   GError *error = NULL;
173
174   bar = gtk_info_bar_new_with_buttons (
175       GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
176       NULL);
177
178   self->priv->done_button = gtk_info_bar_add_button (GTK_INFO_BAR (bar),
179       _("Done"), GTK_RESPONSE_OK);
180
181   gtk_widget_set_hexpand (bar, TRUE);
182   gtk_info_bar_set_message_type (GTK_INFO_BAR (bar), GTK_MESSAGE_QUESTION);
183   action = gtk_info_bar_get_action_area (GTK_INFO_BAR (bar));
184   gtk_orientable_set_orientation (GTK_ORIENTABLE (action),
185       GTK_ORIENTATION_HORIZONTAL);
186   gtk_widget_set_name (bar, "authorization-infobar");
187   css = gtk_css_provider_new ();
188   if (gtk_css_provider_load_from_data (css,
189           "@define-color question_bg_color rgb (222, 222, 222);"
190           "GtkInfoBar#authorization-infobar"
191           "{"
192           "  color: @fg_color;"
193           "}",
194           -1, &error))
195     {
196       GtkStyleContext *context = gtk_widget_get_style_context (bar);
197
198       gtk_style_context_add_provider (context, (GtkStyleProvider *) css,
199           GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
200     }
201   else
202     {
203       g_warning ("Error processing CSS theme override: %s", error->message);
204       g_clear_error (&error);
205     }
206   g_object_unref (css);
207
208   content = gtk_info_bar_get_content_area (GTK_INFO_BAR (bar));
209
210   label = gtk_label_new (_("Please enter your account details"));
211   gtk_container_add (GTK_CONTAINER (content), label);
212   gtk_widget_show (label);
213
214   g_signal_connect (bar, "response",
215       G_CALLBACK (response_cb), self);
216
217   return bar;
218 }
219
220 static void
221 account_widget_handle_apply_cb (EmpathyAccountWidget *widget,
222     gboolean valid,
223     EmpathyAccountsPluginWidget *self)
224 {
225   gtk_widget_set_sensitive (self->priv->done_button, valid);
226 }
227
228 static void
229 account_widget_close_cb (EmpathyAccountWidget *widget,
230     GtkResponseType response,
231     EmpathyAccountsPluginWidget *self)
232 {
233   g_signal_emit (self, signals[SIG_DONE], 0);
234 }
235
236 static void
237 add_account_widget (EmpathyAccountsPluginWidget *self)
238 {
239   GtkWidget *alig;
240   gboolean simple;
241
242   alig = gtk_alignment_new (0.5, 0, 0, 0);
243
244   gtk_box_pack_start (GTK_BOX (self), alig, TRUE, TRUE, 0);
245   gtk_widget_show (GTK_WIDGET (alig));
246
247   /* Use the simple widget only when creating the account */
248   simple = (self->priv->account->id == 0);
249
250   self->priv->account_widget = empathy_account_widget_new_for_protocol (
251       self->priv->settings, simple);
252
253   empathy_account_widget_hide_buttons (self->priv->account_widget);
254
255   gtk_widget_set_valign (GTK_WIDGET (self->priv->account_widget),
256       GTK_ALIGN_CENTER);
257
258   gtk_container_add (GTK_CONTAINER (alig),
259       GTK_WIDGET (self->priv->account_widget));
260   gtk_widget_show (GTK_WIDGET (self->priv->account_widget));
261
262   if (!empathy_account_settings_is_valid (self->priv->settings))
263     {
264       gtk_widget_set_sensitive (self->priv->done_button, FALSE);
265     }
266
267   g_signal_connect (self->priv->account_widget, "handle-apply",
268       G_CALLBACK (account_widget_handle_apply_cb), self);
269   g_signal_connect (self->priv->account_widget, "close",
270       G_CALLBACK (account_widget_close_cb), self);
271 }
272
273 static void
274 maybe_add_account_widget (EmpathyAccountsPluginWidget *self)
275 {
276   g_return_if_fail (self->priv->settings != NULL);
277
278   if (empathy_account_settings_is_ready (self->priv->settings))
279     {
280       add_account_widget (self);
281     }
282   else
283     {
284       g_signal_connect_swapped (self->priv->settings, "notify::ready",
285           G_CALLBACK (add_account_widget), self);
286     }
287 }
288
289 static void
290 manager_prepared_cb (GObject *source,
291     GAsyncResult *result,
292     gpointer user_data)
293 {
294   TpWeakRef *wr = user_data;
295   EmpathyAccountsPluginWidget *self = tp_weak_ref_dup_object (wr);
296   TpAccountManager *manager = (TpAccountManager *) source;
297   GList *accounts;
298   GError *error = NULL;
299
300   if (self == NULL)
301     {
302       tp_weak_ref_destroy (wr);
303       return;
304     }
305
306   if (!tp_proxy_prepare_finish (manager, result, &error))
307     {
308       g_debug ("Error preparing Account Manager: %s", error->message);
309       g_clear_error (&error);
310       goto out;
311     }
312
313   accounts = tp_account_manager_dup_valid_accounts (manager);
314   while (accounts != NULL)
315     {
316       TpAccount *account = accounts->data;
317       const GValue *value;
318
319       value = tp_account_get_storage_identifier (account);
320       if (G_VALUE_HOLDS_UINT (value) &&
321           g_value_get_uint (value) == self->priv->account->id)
322         {
323           self->priv->settings = empathy_account_settings_new_for_account (
324               account);
325           maybe_add_account_widget (self);
326           break;
327         }
328
329       accounts = g_list_delete_link (accounts, accounts);
330     }
331   g_list_free_full (accounts, g_object_unref);
332
333 out:
334   tp_weak_ref_destroy (wr);
335   g_object_unref (self);
336 }
337
338 static void
339 empathy_accounts_plugin_widget_constructed (GObject *object)
340 {
341   EmpathyAccountsPluginWidget *self = EMPATHY_ACCOUNTS_PLUGIN_WIDGET (object);
342   void (*chain_up) (GObject *) =
343       ((GObjectClass *) empathy_accounts_plugin_widget_parent_class)->constructed;
344   GtkWidget *top;
345
346   if (chain_up != NULL)
347     chain_up (object);
348
349   g_return_if_fail (AG_IS_ACCOUNT (self->priv->account));
350
351   /* Top bar */
352   top = create_top_bar (self);
353   gtk_widget_show (top);
354   gtk_box_pack_start (GTK_BOX (self), top, FALSE, FALSE, 0);
355
356   if (self->priv->account->id != 0)
357     {
358       TpAccountManager *manager;
359
360       /* Prepare tp's account manager to find the TpAccount corresponding to our
361        * AgAccount */
362       manager = tp_account_manager_dup ();
363
364       tp_proxy_prepare_async (manager, NULL,
365           manager_prepared_cb, tp_weak_ref_new (self, NULL, NULL));
366       g_object_unref (manager);
367       return;
368     }
369
370   self->priv->settings = create_account_settings (self->priv->account);
371   maybe_add_account_widget (self);
372 }
373
374 static void
375 empathy_accounts_plugin_widget_dispose (GObject *object)
376 {
377   EmpathyAccountsPluginWidget *self = EMPATHY_ACCOUNTS_PLUGIN_WIDGET (object);
378   void (*chain_up) (GObject *) =
379       ((GObjectClass *) empathy_accounts_plugin_widget_parent_class)->dispose;
380
381   g_clear_object (&self->priv->account);
382   g_clear_object (&self->priv->settings);
383
384   if (chain_up != NULL)
385     chain_up (object);
386 }
387
388 static void
389 empathy_accounts_plugin_widget_class_init (
390     EmpathyAccountsPluginWidgetClass *klass)
391 {
392   GObjectClass *oclass = G_OBJECT_CLASS (klass);
393   GParamSpec *spec;
394
395   oclass->get_property = empathy_accounts_plugin_widget_get_property;
396   oclass->set_property = empathy_accounts_plugin_widget_set_property;
397   oclass->constructed = empathy_accounts_plugin_widget_constructed;
398   oclass->dispose = empathy_accounts_plugin_widget_dispose;
399
400   spec = g_param_spec_object ("account", "account",
401       "AgAccount",
402       AG_TYPE_ACCOUNT,
403       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
404   g_object_class_install_property (oclass, PROP_ACCOUNT, spec);
405
406   signals[SIG_DONE] = g_signal_new ("done",
407       G_OBJECT_CLASS_TYPE (klass),
408       G_SIGNAL_RUN_LAST,
409       0, NULL, NULL, NULL,
410       G_TYPE_NONE,
411       0);
412
413   g_type_class_add_private (klass, sizeof (EmpathyAccountsPluginWidgetPriv));
414 }
415
416 static void
417 empathy_accounts_plugin_widget_init (EmpathyAccountsPluginWidget *self)
418 {
419   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
420       EMPATHY_TYPE_ACCOUNTS_PLUGIN_WIDGET, EmpathyAccountsPluginWidgetPriv);
421 }
422
423 GtkWidget *
424 empathy_accounts_plugin_widget_new (AgAccount *account)
425 {
426   return g_object_new (EMPATHY_TYPE_ACCOUNTS_PLUGIN_WIDGET,
427       "account", account,
428       "orientation", GTK_ORIENTATION_VERTICAL,
429       "spacing", 10,
430       NULL);
431 }