]> www.fi.muni.cz Git - evince.git/blob - shell/ev-password-view.c
[shell] Dialogues have no separators on gtk 3
[evince.git] / shell / ev-password-view.c
1 /* this file is part of evince, a gnome document viewer
2  *
3  *  Copyright (C) 2008 Carlos Garcia Campos <carlosgc@gnome.org>
4  *  Copyright (C) 2005 Red Hat, Inc
5  *
6  * Evince is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * Evince is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  */
20
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <glib/gi18n.h>
27 #include <gtk/gtk.h>
28 #include <gio/gio.h>
29
30 #include "ev-keyring.h"
31 #include "ev-password-view.h"
32
33 enum {
34         UNLOCK,
35         LAST_SIGNAL
36 };
37 struct _EvPasswordViewPrivate {
38         GtkWindow    *parent_window;
39         GtkWidget    *label;
40         GtkWidget    *password_entry;
41
42         gchar        *password;
43         GPasswordSave password_save;
44
45         GFile        *uri_file;
46 };
47
48 #define EV_PASSWORD_VIEW_GET_PRIVATE(object) \
49         (G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_PASSWORD_VIEW, EvPasswordViewPrivate));
50
51 static guint password_view_signals [LAST_SIGNAL] = { 0 };
52
53
54 G_DEFINE_TYPE (EvPasswordView, ev_password_view, GTK_TYPE_VIEWPORT)
55
56 static void
57 ev_password_view_finalize (GObject *object)
58 {
59         EvPasswordView *password_view = EV_PASSWORD_VIEW (object);
60
61         if (password_view->priv->password) {
62                 g_free (password_view->priv->password);
63                 password_view->priv->password = NULL;
64         }
65
66         password_view->priv->parent_window = NULL;
67
68         if (password_view->priv->uri_file) {
69                 g_object_unref (password_view->priv->uri_file);
70                 password_view->priv->uri_file = NULL;
71         }
72
73         G_OBJECT_CLASS (ev_password_view_parent_class)->finalize (object);
74 }
75
76 static void
77 ev_password_view_class_init (EvPasswordViewClass *class)
78 {
79         GObjectClass *g_object_class;
80         GtkWidgetClass *widget_class;
81
82         g_object_class = G_OBJECT_CLASS (class);
83         widget_class = GTK_WIDGET_CLASS (class);
84
85         password_view_signals[UNLOCK] =
86                 g_signal_new ("unlock",
87                               G_TYPE_FROM_CLASS (g_object_class),
88                               G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
89                               G_STRUCT_OFFSET (EvPasswordViewClass, unlock),
90                               NULL, NULL,
91                               g_cclosure_marshal_VOID__VOID,
92                               G_TYPE_NONE, 0);
93
94         g_type_class_add_private (g_object_class, sizeof (EvPasswordViewPrivate));
95
96         g_object_class->finalize = ev_password_view_finalize;
97 }
98
99 static void
100 ev_password_view_clicked_cb (GtkWidget      *button,
101                              EvPasswordView *password_view)
102 {
103         ev_password_view_ask_password (password_view);
104 }
105
106 static void
107 ev_password_view_init (EvPasswordView *password_view)
108 {
109         GtkWidget *align;
110         GtkWidget *vbox;
111         GtkWidget *hbox;
112         GtkWidget *image;
113         GtkWidget *button;
114         GtkWidget *label;
115         gchar     *markup;
116
117         password_view->priv = EV_PASSWORD_VIEW_GET_PRIVATE (password_view);
118
119         password_view->priv->password_save = G_PASSWORD_SAVE_NEVER;
120         
121         gtk_widget_push_composite_child ();
122
123         /* set ourselves up */
124         align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
125         vbox = gtk_vbox_new (FALSE, 24);
126         gtk_container_set_border_width (GTK_CONTAINER (vbox), 24);
127         gtk_container_add (GTK_CONTAINER (password_view), align);
128         gtk_container_add (GTK_CONTAINER (align), vbox);
129
130         password_view->priv->label =
131                 (GtkWidget *) g_object_new (GTK_TYPE_LABEL,
132                                             "wrap", TRUE,
133                                             "selectable", TRUE,
134                                             NULL);
135         gtk_box_pack_start (GTK_BOX (vbox), password_view->priv->label, FALSE, FALSE, 0);
136
137         image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_AUTHENTICATION,
138                                           GTK_ICON_SIZE_DIALOG);
139         gtk_box_pack_start (GTK_BOX (vbox), image, FALSE, FALSE, 0);
140
141         label = gtk_label_new (NULL);
142         gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
143         markup = g_strdup_printf ("<span size=\"x-large\">%s</span>",
144                                   _("This document is locked and can only be read by entering the correct password."));
145         gtk_label_set_markup (GTK_LABEL (label), markup);
146         g_free (markup);
147                               
148         gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
149
150         hbox = gtk_hbox_new (FALSE, 0);
151         gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
152
153         button = gtk_button_new_with_mnemonic (_("_Unlock Document"));
154         g_signal_connect (button, "clicked", G_CALLBACK (ev_password_view_clicked_cb), password_view);
155         gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
156
157         gtk_widget_show_all (align);
158         gtk_widget_pop_composite_child ();
159 }
160
161 /* Public functions */
162 void
163 ev_password_view_set_uri (EvPasswordView *password_view,
164                           const char     *uri)
165 {
166         gchar *markup, *file_name;
167         GFile *file;
168
169         g_return_if_fail (EV_IS_PASSWORD_VIEW (password_view));
170         g_return_if_fail (uri != NULL);
171
172         file = g_file_new_for_uri (uri);
173         if (password_view->priv->uri_file &&
174             g_file_equal (file, password_view->priv->uri_file)) {
175                 g_object_unref (file);
176                 return;
177         }
178         if (password_view->priv->uri_file)
179                 g_object_unref (password_view->priv->uri_file);
180         password_view->priv->uri_file = file;
181
182         file_name = g_file_get_basename (password_view->priv->uri_file);
183         markup = g_markup_printf_escaped ("<span size=\"x-large\" weight=\"bold\">%s</span>",
184                                           file_name);
185         g_free (file_name);
186
187         gtk_label_set_markup (GTK_LABEL (password_view->priv->label), markup);
188         g_free (markup);
189 }
190
191 static void
192 ev_password_dialog_got_response (GtkDialog      *dialog,
193                                  gint            response_id,
194                                  EvPasswordView *password_view)
195 {
196         gtk_widget_set_sensitive (GTK_WIDGET (password_view), TRUE);
197         
198         if (response_id == GTK_RESPONSE_OK) {
199                 g_free (password_view->priv->password);
200                 password_view->priv->password =
201                         g_strdup (gtk_entry_get_text (GTK_ENTRY (password_view->priv->password_entry)));
202                 
203                 g_signal_emit (password_view, password_view_signals[UNLOCK], 0);
204         }
205         
206         gtk_widget_destroy (GTK_WIDGET (dialog));
207 }
208
209 static void
210 ev_password_dialog_remember_button_toggled (GtkToggleButton *button,
211                                             EvPasswordView  *password_view)
212 {
213         if (gtk_toggle_button_get_active (button)) {
214                 gpointer data;
215                 
216                 data = g_object_get_data (G_OBJECT (button), "password-save");
217                 password_view->priv->password_save = GPOINTER_TO_INT (data);
218         }
219 }
220
221 static void
222 ev_password_dialog_entry_changed_cb (GtkEditable *editable,
223                                      GtkDialog   *dialog)
224 {
225         const char *text;
226
227         text = gtk_entry_get_text (GTK_ENTRY (editable));
228
229         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK,
230                                            (text != NULL && *text != '\0'));
231 }
232
233 static void
234 ev_password_dialog_entry_activated_cb (GtkEntry  *entry,
235                                        GtkDialog *dialog)
236 {
237         gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
238 }
239
240 void
241 ev_password_view_ask_password (EvPasswordView *password_view)
242 {
243         GtkDialog *dialog;
244         GtkWidget *content_area, *action_area;
245         GtkWidget *entry_container;
246         GtkWidget *hbox, *main_vbox, *vbox, *icon;
247         GtkWidget *table;
248         GtkWidget *label;
249         gchar     *format, *markup, *file_name;
250
251         gtk_widget_set_sensitive (GTK_WIDGET (password_view), FALSE);
252         
253         dialog = GTK_DIALOG (gtk_dialog_new ());
254         content_area = gtk_dialog_get_content_area (dialog);
255         action_area = gtk_dialog_get_action_area (dialog);
256
257         /* Set the dialog up with HIG properties */
258 #if !GTK_CHECK_VERSION (2, 90, 7)
259         gtk_dialog_set_has_separator (dialog, FALSE);
260 #endif
261         gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
262         gtk_box_set_spacing (GTK_BOX (content_area), 2); /* 2 * 5 + 2 = 12 */
263         gtk_container_set_border_width (GTK_CONTAINER (action_area), 5);
264         gtk_box_set_spacing (GTK_BOX (action_area), 6);
265
266         gtk_window_set_title (GTK_WINDOW (dialog), _("Enter password"));
267         gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
268         gtk_window_set_icon_name (GTK_WINDOW (dialog), GTK_STOCK_DIALOG_AUTHENTICATION);
269         gtk_window_set_transient_for (GTK_WINDOW (dialog), password_view->priv->parent_window);
270         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
271
272         gtk_dialog_add_buttons (dialog,
273                                 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
274                                 _("_Unlock Document"), GTK_RESPONSE_OK,
275                                 NULL);
276         gtk_dialog_set_default_response (dialog, GTK_RESPONSE_OK);
277         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
278                                            GTK_RESPONSE_OK, FALSE);
279         gtk_dialog_set_alternative_button_order (dialog,
280                                                  GTK_RESPONSE_OK,
281                                                  GTK_RESPONSE_CANCEL,
282                                                  -1);
283         
284         /* Build contents */
285         hbox = gtk_hbox_new (FALSE, 12);
286         gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
287         gtk_box_pack_start (GTK_BOX (content_area), hbox, TRUE, TRUE, 0);
288         gtk_widget_show (hbox);
289
290         icon = gtk_image_new_from_stock (GTK_STOCK_DIALOG_AUTHENTICATION,
291                                          GTK_ICON_SIZE_DIALOG);
292
293         gtk_misc_set_alignment (GTK_MISC (icon), 0.5, 0.0);
294         gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, FALSE, 0);
295         gtk_widget_show (icon);
296
297         main_vbox = gtk_vbox_new (FALSE, 18);
298         gtk_box_pack_start (GTK_BOX (hbox), main_vbox, TRUE, TRUE, 0);
299         gtk_widget_show (main_vbox);
300
301         label = gtk_label_new (NULL);
302         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
303         gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
304         file_name = g_file_get_basename (password_view->priv->uri_file);
305         format = g_strdup_printf ("<span size=\"larger\" weight=\"bold\">%s</span>\n\n%s",
306                                   _("Password required"),
307                                   _("The document ā€œ%sā€ is locked and requires a password before it can be opened."));
308         markup = g_markup_printf_escaped (format, file_name);
309         gtk_label_set_markup (GTK_LABEL (label), markup);
310         g_free (format);
311         g_free (markup);
312         g_free (file_name);
313         gtk_box_pack_start (GTK_BOX (main_vbox), label,
314                             FALSE, FALSE, 0);
315         gtk_widget_show (label);
316
317         vbox = gtk_vbox_new (FALSE, 6);
318         gtk_box_pack_start (GTK_BOX (main_vbox), vbox, FALSE, FALSE, 0);
319         gtk_widget_show (vbox);
320
321         /* The table that holds the entries */
322         entry_container = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
323
324         gtk_alignment_set_padding (GTK_ALIGNMENT (entry_container),
325                                    0, 0, 0, 0);
326         
327         gtk_box_pack_start (GTK_BOX (vbox), entry_container,
328                             FALSE, FALSE, 0);
329         gtk_widget_show (entry_container);
330
331         table = gtk_table_new (1, 2, FALSE);
332         gtk_table_set_col_spacings (GTK_TABLE (table), 12);
333         gtk_table_set_row_spacings (GTK_TABLE (table), 6);
334         gtk_container_add (GTK_CONTAINER (entry_container), table);
335         gtk_widget_show (table);
336
337         label = gtk_label_new_with_mnemonic (_("_Password:"));
338         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
339
340         password_view->priv->password_entry = gtk_entry_new ();
341         gtk_entry_set_visibility (GTK_ENTRY (password_view->priv->password_entry), FALSE);
342         g_signal_connect (password_view->priv->password_entry, "changed",
343                           G_CALLBACK (ev_password_dialog_entry_changed_cb),
344                           dialog);
345         g_signal_connect (password_view->priv->password_entry, "activate",
346                           G_CALLBACK (ev_password_dialog_entry_activated_cb),
347                           dialog);
348         gtk_table_attach (GTK_TABLE (table), label,
349                           0, 1, 0, 1,
350                           GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);       
351         gtk_widget_show (label);
352
353         gtk_table_attach_defaults (GTK_TABLE (table), password_view->priv->password_entry,
354                                    1, 2, 0, 1);
355         gtk_widget_show (password_view->priv->password_entry);
356         
357         gtk_label_set_mnemonic_widget (GTK_LABEL (label),
358                                        password_view->priv->password_entry);
359
360         if (ev_keyring_is_available ()) {
361                 GtkWidget  *choice;
362                 GtkWidget  *remember_box;
363                 GSList     *group;
364
365                 remember_box = gtk_vbox_new (FALSE, 6);
366                 gtk_box_pack_start (GTK_BOX (vbox), remember_box,
367                                     FALSE, FALSE, 0);
368                 gtk_widget_show (remember_box);
369
370                 choice = gtk_radio_button_new_with_mnemonic (NULL, _("Forget password _immediately"));
371                 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (choice),
372                                               password_view->priv->password_save == G_PASSWORD_SAVE_NEVER);
373                 g_object_set_data (G_OBJECT (choice), "password-save",
374                                    GINT_TO_POINTER (G_PASSWORD_SAVE_NEVER));
375                 g_signal_connect (choice, "toggled",
376                                   G_CALLBACK (ev_password_dialog_remember_button_toggled),
377                                   password_view);
378                 gtk_box_pack_start (GTK_BOX (remember_box), choice, FALSE, FALSE, 0);
379                 gtk_widget_show (choice);
380
381                 group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (choice));
382                 choice = gtk_radio_button_new_with_mnemonic (group, _("Remember password until you _log out"));
383                 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (choice),
384                                               password_view->priv->password_save == G_PASSWORD_SAVE_FOR_SESSION);
385                 g_object_set_data (G_OBJECT (choice), "password-save",
386                                    GINT_TO_POINTER (G_PASSWORD_SAVE_FOR_SESSION));
387                 g_signal_connect (choice, "toggled",
388                                   G_CALLBACK (ev_password_dialog_remember_button_toggled),
389                                   password_view);
390                 gtk_box_pack_start (GTK_BOX (remember_box), choice, FALSE, FALSE, 0);
391                 gtk_widget_show (choice);
392
393                 group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (choice));
394                 choice = gtk_radio_button_new_with_mnemonic (group, _("Remember _forever"));
395                 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (choice),
396                                               password_view->priv->password_save == G_PASSWORD_SAVE_PERMANENTLY);
397                 g_object_set_data (G_OBJECT (choice), "password-save",
398                                    GINT_TO_POINTER (G_PASSWORD_SAVE_PERMANENTLY));
399                 g_signal_connect (choice, "toggled",
400                                   G_CALLBACK (ev_password_dialog_remember_button_toggled),
401                                   password_view);
402                 gtk_box_pack_start (GTK_BOX (remember_box), choice, FALSE, FALSE, 0);
403                 gtk_widget_show (choice);
404         }
405
406         g_signal_connect (dialog, "response",
407                           G_CALLBACK (ev_password_dialog_got_response),
408                           password_view);
409         
410         gtk_widget_show (GTK_WIDGET (dialog));
411 }
412
413 const gchar *
414 ev_password_view_get_password (EvPasswordView *password_view)
415 {
416         return password_view->priv->password;
417 }
418
419 GPasswordSave
420 ev_password_view_get_password_save_flags (EvPasswordView *password_view)
421 {
422         return password_view->priv->password_save;
423 }
424
425 GtkWidget *
426 ev_password_view_new (GtkWindow *parent)
427 {
428         EvPasswordView *retval;
429
430         retval = EV_PASSWORD_VIEW (g_object_new (EV_TYPE_PASSWORD_VIEW, NULL));
431
432         retval->priv->parent_window = parent;
433
434         return GTK_WIDGET (retval);
435 }
436