]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-password-dialog.c
password-dialog: destroy the dialog if the handler is invalidated
[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
45   gboolean grabbing;
46
47   gboolean dispose_run;
48 } EmpathyPasswordDialogPriv;
49
50 static void
51 empathy_password_dialog_get_property (GObject *object,
52     guint property_id,
53     GValue *value,
54     GParamSpec *pspec)
55 {
56   EmpathyPasswordDialogPriv *priv = EMPATHY_PASSWORD_DIALOG (object)->priv;
57
58   switch (property_id)
59     {
60     case PROP_HANDLER:
61       g_value_set_object (value, priv->handler);
62       break;
63     default:
64       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
65       break;
66     }
67 }
68
69 static void
70 empathy_password_dialog_set_property (GObject *object,
71     guint property_id,
72     const GValue *value,
73     GParamSpec *pspec)
74 {
75   EmpathyPasswordDialogPriv *priv = EMPATHY_PASSWORD_DIALOG (object)->priv;
76
77   switch (property_id)
78     {
79     case PROP_HANDLER:
80       g_assert (priv->handler == NULL); /* construct only */
81       priv->handler = g_value_dup_object (value);
82       break;
83     default:
84       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
85       break;
86     }
87 }
88
89 static void
90 empathy_password_dialog_dispose (GObject *object)
91 {
92   EmpathyPasswordDialogPriv *priv = EMPATHY_PASSWORD_DIALOG (object)->priv;
93
94   if (priv->dispose_run)
95     return;
96
97   priv->dispose_run = TRUE;
98
99   tp_clear_object (&priv->handler);
100
101   G_OBJECT_CLASS (empathy_password_dialog_parent_class)->dispose (object);
102 }
103
104 static void
105 password_dialog_response_cb (GtkDialog *dialog,
106     gint response,
107     gpointer user_data)
108 {
109   EmpathyPasswordDialogPriv *priv = EMPATHY_PASSWORD_DIALOG (user_data)->priv;
110
111   if (response == GTK_RESPONSE_OK)
112     {
113       empathy_server_sasl_handler_provide_password (priv->handler,
114           gtk_entry_get_text (GTK_ENTRY (priv->entry)),
115           gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->ticky)));
116     }
117   else
118     {
119       empathy_server_sasl_handler_cancel (priv->handler);
120     }
121
122   gtk_widget_destroy (GTK_WIDGET (dialog));
123 }
124
125 static void
126 clear_icon_released_cb (GtkEntry *entry,
127     GtkEntryIconPosition icon_pos,
128     GdkEvent *event,
129     gpointer user_data)
130 {
131   gtk_entry_set_text (entry, "");
132 }
133
134 static void
135 password_entry_changed_cb (GtkEditable *entry,
136     gpointer user_data)
137 {
138   const gchar *str;
139
140   str = gtk_entry_get_text (GTK_ENTRY (entry));
141
142   gtk_entry_set_icon_sensitive (GTK_ENTRY (entry),
143       GTK_ENTRY_ICON_SECONDARY, !EMP_STR_EMPTY (str));
144 }
145
146 static gboolean
147 password_dialog_grab_keyboard (GtkWidget *widget,
148     GdkEvent *event,
149     gpointer user_data)
150 {
151   EmpathyPasswordDialogPriv *priv = EMPATHY_PASSWORD_DIALOG (user_data)->priv;
152
153   if (!priv->grabbing)
154     {
155       GdkGrabStatus status = gdk_keyboard_grab (gtk_widget_get_window (widget),
156           FALSE, gdk_event_get_time (event));
157
158       if (status != GDK_GRAB_SUCCESS)
159         DEBUG ("Could not grab keyboard; grab status was %u", status);
160       else
161         priv->grabbing = TRUE;
162     }
163
164   return FALSE;
165 }
166
167 static gboolean
168 password_dialog_ungrab_keyboard (GtkWidget *widget,
169     GdkEvent *event,
170     gpointer user_data)
171 {
172   EmpathyPasswordDialogPriv *priv = EMPATHY_PASSWORD_DIALOG (user_data)->priv;
173
174   if (priv->grabbing)
175     {
176       gdk_keyboard_ungrab (gdk_event_get_time (event));
177       priv->grabbing = FALSE;
178     }
179
180   return FALSE;
181 }
182
183 static gboolean
184 password_dialog_window_state_changed (GtkWidget *widget,
185     GdkEventWindowState *event,
186     gpointer data)
187 {
188   GdkWindowState state = gdk_window_get_state (gtk_widget_get_window (widget));
189
190   if (state & GDK_WINDOW_STATE_WITHDRAWN
191       || state & GDK_WINDOW_STATE_ICONIFIED
192       || state & GDK_WINDOW_STATE_FULLSCREEN
193       || state & GDK_WINDOW_STATE_MAXIMIZED)
194     {
195       password_dialog_ungrab_keyboard (widget, (GdkEvent *) event, data);
196     }
197   else
198     {
199       password_dialog_grab_keyboard (widget, (GdkEvent *) event, data);
200     }
201
202   return FALSE;
203 }
204
205 static void
206 password_dialog_handler_invalidated_cb (EmpathyServerSASLHandler *handler,
207     EmpathyPasswordDialog *dialog)
208 {
209   gtk_widget_destroy (GTK_WIDGET (dialog));
210 }
211
212 static void
213 empathy_password_dialog_constructed (GObject *object)
214 {
215   EmpathyPasswordDialog *dialog;
216   EmpathyPasswordDialogPriv *priv;
217   TpAccount *account;
218   GtkWidget *icon;
219   GtkBox *box;
220   gchar *text;
221
222   dialog = EMPATHY_PASSWORD_DIALOG (object);
223   priv = dialog->priv;
224
225   g_assert (priv->handler != NULL);
226
227   priv->grabbing = FALSE;
228
229   account = empathy_server_sasl_handler_get_account (priv->handler);
230
231   tp_g_signal_connect_object (priv->handler, "invalidated",
232       G_CALLBACK (password_dialog_handler_invalidated_cb),
233       object, 0);
234
235   /* dialog */
236   gtk_dialog_add_buttons (GTK_DIALOG (dialog),
237       GTK_STOCK_OK, GTK_RESPONSE_OK,
238       GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
239       NULL);
240
241   text = g_strdup_printf (_("Enter your password for account\n<b>%s</b>"),
242       tp_account_get_display_name (account));
243   gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), text);
244   g_free (text);
245
246   gtk_window_set_icon_name (GTK_WINDOW (dialog),
247       GTK_STOCK_DIALOG_AUTHENTICATION);
248
249   box = GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog)));
250
251   /* dialog icon */
252   icon = gtk_image_new_from_icon_name (tp_account_get_icon_name (account),
253       GTK_ICON_SIZE_DIALOG);
254   gtk_message_dialog_set_image (GTK_MESSAGE_DIALOG (dialog), icon);
255   gtk_widget_show (icon);
256
257   /* entry */
258   priv->entry = gtk_entry_new ();
259   gtk_entry_set_visibility (GTK_ENTRY (priv->entry), FALSE);
260
261   /* entry clear icon */
262   gtk_entry_set_icon_from_stock (GTK_ENTRY (priv->entry),
263       GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
264   gtk_entry_set_icon_sensitive (GTK_ENTRY (priv->entry),
265       GTK_ENTRY_ICON_SECONDARY, FALSE);
266
267   g_signal_connect (priv->entry, "icon-release",
268       G_CALLBACK (clear_icon_released_cb), NULL);
269   g_signal_connect (priv->entry, "changed",
270       G_CALLBACK (password_entry_changed_cb), NULL);
271
272   gtk_box_pack_start (box, priv->entry, FALSE, FALSE, 0);
273   gtk_widget_show (priv->entry);
274
275   /* remember password ticky box */
276   priv->ticky = gtk_check_button_new_with_label (_("Remember password"));
277
278   gtk_box_pack_start (box, priv->ticky, FALSE, FALSE, 0);
279   gtk_widget_show (priv->ticky);
280
281   g_signal_connect (dialog, "response",
282       G_CALLBACK (password_dialog_response_cb), dialog);
283   g_signal_connect (dialog, "window-state-event",
284       G_CALLBACK (password_dialog_window_state_changed), dialog);
285   g_signal_connect (dialog, "map-event",
286       G_CALLBACK (password_dialog_grab_keyboard), dialog);
287   g_signal_connect (dialog, "unmap-event",
288       G_CALLBACK (password_dialog_ungrab_keyboard), dialog);
289
290   gtk_widget_grab_focus (priv->entry);
291
292   gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER_ALWAYS);
293 }
294
295 static void
296 empathy_password_dialog_init (EmpathyPasswordDialog *self)
297 {
298   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
299       EMPATHY_TYPE_PASSWORD_DIALOG, EmpathyPasswordDialogPriv);
300 }
301
302 static void
303 empathy_password_dialog_class_init (EmpathyPasswordDialogClass *klass)
304 {
305   GParamSpec *pspec;
306   GObjectClass *oclass = G_OBJECT_CLASS (klass);
307
308   g_type_class_add_private (klass, sizeof (EmpathyPasswordDialogPriv));
309
310   oclass->set_property = empathy_password_dialog_set_property;
311   oclass->get_property = empathy_password_dialog_get_property;
312   oclass->dispose = empathy_password_dialog_dispose;
313   oclass->constructed = empathy_password_dialog_constructed;
314
315   pspec = g_param_spec_object ("handler", "The EmpathyServerSASLHandler",
316       "The EmpathyServerSASLHandler to be used.",
317       EMPATHY_TYPE_SERVER_SASL_HANDLER,
318       G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
319   g_object_class_install_property (oclass, PROP_HANDLER, pspec);
320 }
321
322 GtkWidget *
323 empathy_password_dialog_new (EmpathyServerSASLHandler *handler)
324 {
325   g_assert (EMPATHY_IS_SERVER_SASL_HANDLER (handler));
326
327   return g_object_new (EMPATHY_TYPE_PASSWORD_DIALOG,
328       "handler", handler, NULL);
329 }