]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-password-dialog.c
2b1048c1c41b25f51a70edf88518fe4b7202a1af
[empathy.git] / libempathy-gtk / empathy-password-dialog.c
1 /*
2  * empathy-password-dialog.c - Source for EmpathyPasswordDialog
3  * Copyright (C) 2010 Collabora Ltd.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library 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  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19
20 #include <config.h>
21
22 #include "empathy-password-dialog.h"
23
24 #include <glib/gi18n-lib.h>
25
26 #define DEBUG_FLAG EMPATHY_DEBUG_SASL
27 #include <libempathy/empathy-debug.h>
28 #include <libempathy/empathy-utils.h>
29
30 G_DEFINE_TYPE (EmpathyPasswordDialog, empathy_password_dialog,
31     GTK_TYPE_MESSAGE_DIALOG)
32
33 enum {
34   PROP_HANDLER = 1,
35
36   LAST_PROPERTY,
37 };
38
39 typedef struct {
40   EmpathyServerSASLHandler *handler;
41
42   GtkWidget *entry;
43   GtkWidget *ticky;
44   GtkWidget *ok_button;
45
46   gboolean grabbing;
47
48   gboolean dispose_run;
49 } EmpathyPasswordDialogPriv;
50
51 static void
52 empathy_password_dialog_get_property (GObject *object,
53     guint property_id,
54     GValue *value,
55     GParamSpec *pspec)
56 {
57   EmpathyPasswordDialogPriv *priv = EMPATHY_PASSWORD_DIALOG (object)->priv;
58
59   switch (property_id)
60     {
61     case PROP_HANDLER:
62       g_value_set_object (value, priv->handler);
63       break;
64     default:
65       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
66       break;
67     }
68 }
69
70 static void
71 empathy_password_dialog_set_property (GObject *object,
72     guint property_id,
73     const GValue *value,
74     GParamSpec *pspec)
75 {
76   EmpathyPasswordDialogPriv *priv = EMPATHY_PASSWORD_DIALOG (object)->priv;
77
78   switch (property_id)
79     {
80     case PROP_HANDLER:
81       g_assert (priv->handler == NULL); /* construct only */
82       priv->handler = g_value_dup_object (value);
83       break;
84     default:
85       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
86       break;
87     }
88 }
89
90 static void
91 empathy_password_dialog_dispose (GObject *object)
92 {
93   EmpathyPasswordDialogPriv *priv = EMPATHY_PASSWORD_DIALOG (object)->priv;
94
95   if (priv->dispose_run)
96     return;
97
98   priv->dispose_run = TRUE;
99
100   tp_clear_object (&priv->handler);
101
102   G_OBJECT_CLASS (empathy_password_dialog_parent_class)->dispose (object);
103 }
104
105 static void
106 password_dialog_response_cb (GtkDialog *dialog,
107     gint response,
108     gpointer user_data)
109 {
110   EmpathyPasswordDialogPriv *priv = EMPATHY_PASSWORD_DIALOG (user_data)->priv;
111
112   if (response == GTK_RESPONSE_OK)
113     {
114       empathy_server_sasl_handler_provide_password (priv->handler,
115           gtk_entry_get_text (GTK_ENTRY (priv->entry)),
116           gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->ticky)));
117     }
118   else
119     {
120       empathy_server_sasl_handler_cancel (priv->handler);
121     }
122
123   gtk_widget_destroy (GTK_WIDGET (dialog));
124 }
125
126 static void
127 clear_icon_released_cb (GtkEntry *entry,
128     GtkEntryIconPosition icon_pos,
129     GdkEvent *event,
130     gpointer user_data)
131 {
132   gtk_entry_set_text (entry, "");
133 }
134
135 static void
136 password_entry_changed_cb (GtkEditable *entry,
137     gpointer user_data)
138 {
139   EmpathyPasswordDialogPriv *priv = EMPATHY_PASSWORD_DIALOG (user_data)->priv;
140   const gchar *str;
141
142   str = gtk_entry_get_text (GTK_ENTRY (entry));
143
144   gtk_entry_set_icon_sensitive (GTK_ENTRY (entry),
145       GTK_ENTRY_ICON_SECONDARY, !EMP_STR_EMPTY (str));
146
147   gtk_widget_set_sensitive (priv->ok_button,
148       !EMP_STR_EMPTY (str));
149 }
150
151 static gboolean
152 password_dialog_grab_keyboard (GtkWidget *widget,
153     GdkEvent *event,
154     gpointer user_data)
155 {
156   EmpathyPasswordDialogPriv *priv = EMPATHY_PASSWORD_DIALOG (user_data)->priv;
157
158   if (!priv->grabbing)
159     {
160       GdkGrabStatus status = gdk_keyboard_grab (gtk_widget_get_window (widget),
161           FALSE, gdk_event_get_time (event));
162
163       if (status != GDK_GRAB_SUCCESS)
164         DEBUG ("Could not grab keyboard; grab status was %u", status);
165       else
166         priv->grabbing = TRUE;
167     }
168
169   return FALSE;
170 }
171
172 static gboolean
173 password_dialog_ungrab_keyboard (GtkWidget *widget,
174     GdkEvent *event,
175     gpointer user_data)
176 {
177   EmpathyPasswordDialogPriv *priv = EMPATHY_PASSWORD_DIALOG (user_data)->priv;
178
179   if (priv->grabbing)
180     {
181       gdk_keyboard_ungrab (gdk_event_get_time (event));
182       priv->grabbing = FALSE;
183     }
184
185   return FALSE;
186 }
187
188 static gboolean
189 password_dialog_window_state_changed (GtkWidget *widget,
190     GdkEventWindowState *event,
191     gpointer data)
192 {
193   GdkWindowState state = gdk_window_get_state (gtk_widget_get_window (widget));
194
195   if (state & GDK_WINDOW_STATE_WITHDRAWN
196       || state & GDK_WINDOW_STATE_ICONIFIED
197       || state & GDK_WINDOW_STATE_FULLSCREEN
198       || state & GDK_WINDOW_STATE_MAXIMIZED)
199     {
200       password_dialog_ungrab_keyboard (widget, (GdkEvent *) event, data);
201     }
202   else
203     {
204       password_dialog_grab_keyboard (widget, (GdkEvent *) event, data);
205     }
206
207   return FALSE;
208 }
209
210 static void
211 password_dialog_handler_invalidated_cb (EmpathyServerSASLHandler *handler,
212     EmpathyPasswordDialog *dialog)
213 {
214   gtk_widget_destroy (GTK_WIDGET (dialog));
215 }
216
217 static void
218 empathy_password_dialog_constructed (GObject *object)
219 {
220   EmpathyPasswordDialog *dialog;
221   EmpathyPasswordDialogPriv *priv;
222   TpAccount *account;
223   GtkWidget *icon;
224   GtkBox *box;
225   gchar *text;
226
227   dialog = EMPATHY_PASSWORD_DIALOG (object);
228   priv = dialog->priv;
229
230   g_assert (priv->handler != NULL);
231
232   priv->grabbing = FALSE;
233
234   account = empathy_server_sasl_handler_get_account (priv->handler);
235
236   tp_g_signal_connect_object (priv->handler, "invalidated",
237       G_CALLBACK (password_dialog_handler_invalidated_cb),
238       object, 0);
239
240   /* dialog */
241   gtk_dialog_add_button (GTK_DIALOG (dialog),
242       GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
243
244   priv->ok_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
245       GTK_STOCK_OK, GTK_RESPONSE_OK);
246   gtk_widget_set_sensitive (priv->ok_button, FALSE);
247
248   text = g_strdup_printf (_("Enter your password for account\n<b>%s</b>"),
249       tp_account_get_display_name (account));
250   gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), text);
251   g_free (text);
252
253   gtk_window_set_icon_name (GTK_WINDOW (dialog),
254       GTK_STOCK_DIALOG_AUTHENTICATION);
255
256   box = GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog)));
257
258   /* dialog icon */
259   icon = gtk_image_new_from_icon_name (tp_account_get_icon_name (account),
260       GTK_ICON_SIZE_DIALOG);
261   gtk_message_dialog_set_image (GTK_MESSAGE_DIALOG (dialog), icon);
262   gtk_widget_show (icon);
263
264   /* entry */
265   priv->entry = gtk_entry_new ();
266   gtk_entry_set_visibility (GTK_ENTRY (priv->entry), FALSE);
267
268   /* entry clear icon */
269   gtk_entry_set_icon_from_stock (GTK_ENTRY (priv->entry),
270       GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
271   gtk_entry_set_icon_sensitive (GTK_ENTRY (priv->entry),
272       GTK_ENTRY_ICON_SECONDARY, FALSE);
273
274   g_signal_connect (priv->entry, "icon-release",
275       G_CALLBACK (clear_icon_released_cb), NULL);
276   g_signal_connect (priv->entry, "changed",
277       G_CALLBACK (password_entry_changed_cb), dialog);
278
279   gtk_box_pack_start (box, priv->entry, FALSE, FALSE, 0);
280   gtk_widget_show (priv->entry);
281
282   /* remember password ticky box */
283   priv->ticky = gtk_check_button_new_with_label (_("Remember password"));
284
285   gtk_box_pack_start (box, priv->ticky, FALSE, FALSE, 0);
286   gtk_widget_show (priv->ticky);
287
288   g_signal_connect (dialog, "response",
289       G_CALLBACK (password_dialog_response_cb), dialog);
290   g_signal_connect (dialog, "window-state-event",
291       G_CALLBACK (password_dialog_window_state_changed), dialog);
292   g_signal_connect (dialog, "map-event",
293       G_CALLBACK (password_dialog_grab_keyboard), dialog);
294   g_signal_connect (dialog, "unmap-event",
295       G_CALLBACK (password_dialog_ungrab_keyboard), dialog);
296
297   gtk_widget_grab_focus (priv->entry);
298
299   gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER_ALWAYS);
300 }
301
302 static void
303 empathy_password_dialog_init (EmpathyPasswordDialog *self)
304 {
305   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
306       EMPATHY_TYPE_PASSWORD_DIALOG, EmpathyPasswordDialogPriv);
307 }
308
309 static void
310 empathy_password_dialog_class_init (EmpathyPasswordDialogClass *klass)
311 {
312   GParamSpec *pspec;
313   GObjectClass *oclass = G_OBJECT_CLASS (klass);
314
315   g_type_class_add_private (klass, sizeof (EmpathyPasswordDialogPriv));
316
317   oclass->set_property = empathy_password_dialog_set_property;
318   oclass->get_property = empathy_password_dialog_get_property;
319   oclass->dispose = empathy_password_dialog_dispose;
320   oclass->constructed = empathy_password_dialog_constructed;
321
322   pspec = g_param_spec_object ("handler", "The EmpathyServerSASLHandler",
323       "The EmpathyServerSASLHandler to be used.",
324       EMPATHY_TYPE_SERVER_SASL_HANDLER,
325       G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
326   g_object_class_install_property (oclass, PROP_HANDLER, pspec);
327 }
328
329 GtkWidget *
330 empathy_password_dialog_new (EmpathyServerSASLHandler *handler)
331 {
332   g_assert (EMPATHY_IS_SERVER_SASL_HANDLER (handler));
333
334   return g_object_new (EMPATHY_TYPE_PASSWORD_DIALOG,
335       "handler", handler, NULL);
336 }