Evince
Evince is a document viewer capable of displaying multiple and single page document formats like PDF and Postscript.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ev-password-view.c
Go to the documentation of this file.
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 {
36 };
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
78 {
79  GObjectClass *g_object_class;
80 
81  g_object_class = G_OBJECT_CLASS (class);
82 
84  g_signal_new ("unlock",
85  G_TYPE_FROM_CLASS (g_object_class),
86  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
87  G_STRUCT_OFFSET (EvPasswordViewClass, unlock),
88  NULL, NULL,
89  g_cclosure_marshal_VOID__VOID,
90  G_TYPE_NONE, 0);
91 
92  g_type_class_add_private (g_object_class, sizeof (EvPasswordViewPrivate));
93 
94  g_object_class->finalize = ev_password_view_finalize;
95 }
96 
97 static void
98 ev_password_view_clicked_cb (GtkWidget *button,
99  EvPasswordView *password_view)
100 {
101  ev_password_view_ask_password (password_view);
102 }
103 
104 static void
106 {
107  GtkWidget *align;
108  GtkWidget *vbox;
109  GtkWidget *hbox;
110  GtkWidget *image;
111  GtkWidget *button;
112  GtkWidget *label;
113  gchar *markup;
114 
115  password_view->priv = EV_PASSWORD_VIEW_GET_PRIVATE (password_view);
116 
117  password_view->priv->password_save = G_PASSWORD_SAVE_NEVER;
118 
119  gtk_widget_push_composite_child ();
120 
121  /* set ourselves up */
122  align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
123  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 24);
124  gtk_container_set_border_width (GTK_CONTAINER (vbox), 24);
125  gtk_container_add (GTK_CONTAINER (password_view), align);
126  gtk_container_add (GTK_CONTAINER (align), vbox);
127 
128  password_view->priv->label =
129  (GtkWidget *) g_object_new (GTK_TYPE_LABEL,
130  "wrap", TRUE,
131  "selectable", TRUE,
132  NULL);
133  gtk_box_pack_start (GTK_BOX (vbox), password_view->priv->label, FALSE, FALSE, 0);
134 
135  image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_AUTHENTICATION,
136  GTK_ICON_SIZE_DIALOG);
137  gtk_box_pack_start (GTK_BOX (vbox), image, FALSE, FALSE, 0);
138 
139  label = gtk_label_new (NULL);
140  gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
141  markup = g_strdup_printf ("<span size=\"x-large\">%s</span>",
142  _("This document is locked and can only be read by entering the correct password."));
143  gtk_label_set_markup (GTK_LABEL (label), markup);
144  g_free (markup);
145 
146  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
147 
148  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
149  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
150 
151  button = gtk_button_new_with_mnemonic (_("_Unlock Document"));
152  g_signal_connect (button, "clicked", G_CALLBACK (ev_password_view_clicked_cb), password_view);
153  gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
154 
155  gtk_widget_show_all (align);
156  gtk_widget_pop_composite_child ();
157 }
158 
159 /* Public functions */
160 void
162  const char *uri)
163 {
164  gchar *markup, *file_name;
165  GFile *file;
166 
167  g_return_if_fail (EV_IS_PASSWORD_VIEW (password_view));
168  g_return_if_fail (uri != NULL);
169 
170  file = g_file_new_for_uri (uri);
171  if (password_view->priv->uri_file &&
172  g_file_equal (file, password_view->priv->uri_file)) {
173  g_object_unref (file);
174  return;
175  }
176  if (password_view->priv->uri_file)
177  g_object_unref (password_view->priv->uri_file);
178  password_view->priv->uri_file = file;
179 
180  file_name = g_file_get_basename (password_view->priv->uri_file);
181  markup = g_markup_printf_escaped ("<span size=\"x-large\" weight=\"bold\">%s</span>",
182  file_name);
183  g_free (file_name);
184 
185  gtk_label_set_markup (GTK_LABEL (password_view->priv->label), markup);
186  g_free (markup);
187 }
188 
189 static void
191  gint response_id,
192  EvPasswordView *password_view)
193 {
194  gtk_widget_set_sensitive (GTK_WIDGET (password_view), TRUE);
195 
196  if (response_id == GTK_RESPONSE_OK) {
197  g_free (password_view->priv->password);
198  password_view->priv->password =
199  g_strdup (gtk_entry_get_text (GTK_ENTRY (password_view->priv->password_entry)));
200 
201  g_signal_emit (password_view, password_view_signals[UNLOCK], 0);
202  }
203 
204  gtk_widget_destroy (GTK_WIDGET (dialog));
205 }
206 
207 static void
209  EvPasswordView *password_view)
210 {
211  if (gtk_toggle_button_get_active (button)) {
212  gpointer data;
213 
214  data = g_object_get_data (G_OBJECT (button), "password-save");
215  password_view->priv->password_save = GPOINTER_TO_INT (data);
216  }
217 }
218 
219 static void
220 ev_password_dialog_entry_changed_cb (GtkEditable *editable,
221  GtkDialog *dialog)
222 {
223  const char *text;
224 
225  text = gtk_entry_get_text (GTK_ENTRY (editable));
226 
227  gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK,
228  (text != NULL && *text != '\0'));
229 }
230 
231 static void
233  GtkDialog *dialog)
234 {
235  gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
236 }
237 
238 void
240 {
241  GtkDialog *dialog;
242  GtkWidget *content_area, *action_area;
243  GtkWidget *entry_container;
244  GtkWidget *hbox, *main_vbox, *vbox, *icon;
245  GtkWidget *grid;
246  GtkWidget *label;
247  gchar *text, *markup, *file_name;
248 
249  gtk_widget_set_sensitive (GTK_WIDGET (password_view), FALSE);
250 
251  dialog = GTK_DIALOG (gtk_dialog_new ());
252  content_area = gtk_dialog_get_content_area (dialog);
253  action_area = gtk_dialog_get_action_area (dialog);
254 
255  /* Set the dialog up with HIG properties */
256  gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
257  gtk_box_set_spacing (GTK_BOX (content_area), 2); /* 2 * 5 + 2 = 12 */
258  gtk_container_set_border_width (GTK_CONTAINER (action_area), 5);
259  gtk_box_set_spacing (GTK_BOX (action_area), 6);
260 
261  gtk_window_set_title (GTK_WINDOW (dialog), _("Enter password"));
262  gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
263  gtk_window_set_icon_name (GTK_WINDOW (dialog), GTK_STOCK_DIALOG_AUTHENTICATION);
264  gtk_window_set_transient_for (GTK_WINDOW (dialog), password_view->priv->parent_window);
265  gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
266 
267  gtk_dialog_add_buttons (dialog,
268  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
269  _("_Unlock Document"), GTK_RESPONSE_OK,
270  NULL);
271  gtk_dialog_set_default_response (dialog, GTK_RESPONSE_OK);
272  gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
273  GTK_RESPONSE_OK, FALSE);
274  gtk_dialog_set_alternative_button_order (dialog,
275  GTK_RESPONSE_OK,
276  GTK_RESPONSE_CANCEL,
277  -1);
278 
279  /* Build contents */
280  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
281  gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
282  gtk_box_pack_start (GTK_BOX (content_area), hbox, TRUE, TRUE, 0);
283  gtk_widget_show (hbox);
284 
285  icon = gtk_image_new_from_stock (GTK_STOCK_DIALOG_AUTHENTICATION,
286  GTK_ICON_SIZE_DIALOG);
287 
288  gtk_misc_set_alignment (GTK_MISC (icon), 0.5, 0.0);
289  gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, FALSE, 0);
290  gtk_widget_show (icon);
291 
292  main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 18);
293  gtk_box_pack_start (GTK_BOX (hbox), main_vbox, TRUE, TRUE, 0);
294  gtk_widget_show (main_vbox);
295 
296  label = gtk_label_new (NULL);
297  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
298  gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
299  file_name = g_file_get_basename (password_view->priv->uri_file);
300  text = g_markup_printf_escaped (_("The document ā€œ%sā€ is locked and requires a password before it can be opened."),
301  file_name);
302  markup = g_strdup_printf ("<span size=\"larger\" weight=\"bold\">%s</span>\n\n%s",
303  _("Password required"),
304  text);
305  gtk_label_set_markup (GTK_LABEL (label), markup);
306  g_free (text);
307  g_free (markup);
308  g_free (file_name);
309  gtk_box_pack_start (GTK_BOX (main_vbox), label,
310  FALSE, FALSE, 0);
311  gtk_widget_show (label);
312 
313  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
314  gtk_box_pack_start (GTK_BOX (main_vbox), vbox, FALSE, FALSE, 0);
315  gtk_widget_show (vbox);
316 
317  /* The table that holds the entries */
318  entry_container = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
319 
320  gtk_alignment_set_padding (GTK_ALIGNMENT (entry_container),
321  0, 0, 0, 0);
322 
323  gtk_box_pack_start (GTK_BOX (vbox), entry_container,
324  FALSE, FALSE, 0);
325  gtk_widget_show (entry_container);
326 
327  grid = gtk_grid_new ();
328  gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
329  gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
330  gtk_container_add (GTK_CONTAINER (entry_container), grid);
331  gtk_widget_show (grid);
332 
333  label = gtk_label_new_with_mnemonic (_("_Password:"));
334  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
335 
336  password_view->priv->password_entry = gtk_entry_new ();
337  gtk_entry_set_visibility (GTK_ENTRY (password_view->priv->password_entry), FALSE);
338  g_signal_connect (password_view->priv->password_entry, "changed",
340  dialog);
341  g_signal_connect (password_view->priv->password_entry, "activate",
343  dialog);
344  gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
345  gtk_widget_show (label);
346 
347  gtk_grid_attach (GTK_GRID (grid), password_view->priv->password_entry, 1, 0, 1, 1);
348  gtk_widget_set_hexpand (password_view->priv->password_entry, TRUE);
349  gtk_widget_show (password_view->priv->password_entry);
350 
351  gtk_label_set_mnemonic_widget (GTK_LABEL (label),
352  password_view->priv->password_entry);
353 
354  if (ev_keyring_is_available ()) {
355  GtkWidget *choice;
356  GtkWidget *remember_box;
357  GSList *group;
358 
359  remember_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
360  gtk_box_pack_start (GTK_BOX (vbox), remember_box,
361  FALSE, FALSE, 0);
362  gtk_widget_show (remember_box);
363 
364  choice = gtk_radio_button_new_with_mnemonic (NULL, _("Forget password _immediately"));
365  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (choice),
366  password_view->priv->password_save == G_PASSWORD_SAVE_NEVER);
367  g_object_set_data (G_OBJECT (choice), "password-save",
368  GINT_TO_POINTER (G_PASSWORD_SAVE_NEVER));
369  g_signal_connect (choice, "toggled",
371  password_view);
372  gtk_box_pack_start (GTK_BOX (remember_box), choice, FALSE, FALSE, 0);
373  gtk_widget_show (choice);
374 
375  group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (choice));
376  choice = gtk_radio_button_new_with_mnemonic (group, _("Remember password until you _log out"));
377  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (choice),
378  password_view->priv->password_save == G_PASSWORD_SAVE_FOR_SESSION);
379  g_object_set_data (G_OBJECT (choice), "password-save",
380  GINT_TO_POINTER (G_PASSWORD_SAVE_FOR_SESSION));
381  g_signal_connect (choice, "toggled",
383  password_view);
384  gtk_box_pack_start (GTK_BOX (remember_box), choice, FALSE, FALSE, 0);
385  gtk_widget_show (choice);
386 
387  group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (choice));
388  choice = gtk_radio_button_new_with_mnemonic (group, _("Remember _forever"));
389  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (choice),
390  password_view->priv->password_save == G_PASSWORD_SAVE_PERMANENTLY);
391  g_object_set_data (G_OBJECT (choice), "password-save",
392  GINT_TO_POINTER (G_PASSWORD_SAVE_PERMANENTLY));
393  g_signal_connect (choice, "toggled",
395  password_view);
396  gtk_box_pack_start (GTK_BOX (remember_box), choice, FALSE, FALSE, 0);
397  gtk_widget_show (choice);
398  }
399 
400  g_signal_connect (dialog, "response",
401  G_CALLBACK (ev_password_dialog_got_response),
402  password_view);
403 
404  gtk_widget_show (GTK_WIDGET (dialog));
405 }
406 
407 const gchar *
409 {
410  return password_view->priv->password;
411 }
412 
413 GPasswordSave
415 {
416  return password_view->priv->password_save;
417 }
418 
419 GtkWidget *
420 ev_password_view_new (GtkWindow *parent)
421 {
422  EvPasswordView *retval;
423 
424  retval = EV_PASSWORD_VIEW (g_object_new (EV_TYPE_PASSWORD_VIEW, NULL));
425 
426  retval->priv->parent_window = parent;
427 
428  return GTK_WIDGET (retval);
429 }
430