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-window-title.c
Go to the documentation of this file.
1 /* this file is part of evince, a gnome document viewer
2  *
3  * Copyright (C) 2005 Red Hat, Inc
4  *
5  * Evince is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * Evince is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19 
20 #include <config.h>
21 #include "ev-window-title.h"
22 #include "ev-utils.h"
23 
24 #include <string.h>
25 #include <gio/gio.h>
26 #include <glib/gi18n.h>
27 
28 /* Known backends (for bad extensions fix) */
29 #define EV_BACKEND_PS "PSDocument"
30 #define EV_BACKEND_PDF "PdfDocument"
31 
32 typedef struct
33 {
34  const gchar *backend;
35  const gchar *text;
37 
39 {
43  char *uri;
44  char *doc_title;
45 };
46 
47 static const BadTitleEntry bad_extensions[] = {
48  { EV_BACKEND_PS, ".dvi" },
49  { EV_BACKEND_PDF, ".doc" },
50  { EV_BACKEND_PDF, ".dvi" },
51  { EV_BACKEND_PDF, ".indd" },
52  { EV_BACKEND_PDF, ".rtf" }
53 };
54 
55 static const BadTitleEntry bad_prefixes[] = {
56  { EV_BACKEND_PDF, "Microsoft Word - " },
57  { EV_BACKEND_PDF, "Microsoft PowerPoint - " }
58 };
59 
60 static char *
61 get_filename_from_uri (const char *uri)
62 {
63  char *filename;
64  char *basename;
65 
66  filename = g_uri_unescape_string (uri, NULL);
67  basename = g_path_get_basename (filename);
68  g_free(filename);
69 
70  return basename;
71 }
72 
73 /* Some docs report titles with confusing extensions (ex. .doc for pdf).
74  Erase the confusing extension of the title */
75 static void
76 ev_window_title_sanitize_title (EvWindowTitle *window_title, char **title) {
77  const gchar *backend;
78  int i;
79 
80  backend = G_OBJECT_TYPE_NAME (window_title->document);
81 
82  for (i = 0; i < G_N_ELEMENTS (bad_extensions); i++) {
83  if (g_ascii_strcasecmp (bad_extensions[i].backend, backend) == 0 &&
84  g_str_has_suffix (*title, bad_extensions[i].text)) {
85  char *new_title;
86  char *filename = get_filename_from_uri (window_title->uri);
87 
88  new_title = g_strndup (*title, strlen(*title) - strlen(bad_extensions[i].text));
89  g_free (*title);
90  *title = new_title;
91 
92  g_free (filename);
93  }
94  }
95  for (i = 0; i < G_N_ELEMENTS (bad_prefixes); i++) {
96  if (g_ascii_strcasecmp (bad_prefixes[i].backend, backend) == 0 &&
97  g_str_has_prefix (*title, bad_prefixes[i].text)) {
98  char *new_title;
99  int len = strlen(bad_prefixes[i].text);
100 
101  new_title = g_strdup_printf ("%s", (*title) + len);
102  g_free (*title);
103  *title = new_title;
104  }
105  }
106 }
107 
108 static void
110 {
111  GtkWindow *window = GTK_WINDOW (window_title->window);
112  GtkHeaderBar *toolbar = GTK_HEADER_BAR (ev_window_get_toolbar (EV_WINDOW (window)));
113  char *title = NULL, *p;
114  char *subtitle = NULL, *title_header = NULL;
115 
116  if (window_title->type == EV_WINDOW_TITLE_RECENT) {
117  gtk_header_bar_set_subtitle (toolbar, NULL);
118  gtk_window_set_title (window, _("Recent Documents"));
119  return;
120  }
121 
122  if (window_title->doc_title && window_title->uri) {
123  title = g_strdup (window_title->doc_title);
124  ev_window_title_sanitize_title (window_title, &title);
125 
126  subtitle = get_filename_from_uri (window_title->uri);
127 
128  title_header = title;
129  title = g_strdup_printf ("%s — %s", subtitle, title);
130 
131  for (p = title; *p; ++p) {
132  /* an '\n' byte is always ASCII, no need for UTF-8 special casing */
133  if (*p == '\n')
134  *p = ' ';
135  }
136  } else if (window_title->uri) {
137  title = get_filename_from_uri (window_title->uri);
138  } else if (!title) {
139  title = g_strdup (_("Document Viewer"));
140  }
141 
142  switch (window_title->type) {
144  gtk_window_set_title (window, title);
145  if (title_header && subtitle) {
146  gtk_header_bar_set_title (toolbar, title_header);
147  gtk_header_bar_set_subtitle (toolbar, subtitle);
148  }
149  break;
151  gchar *password_title;
152 
153  password_title = g_strdup_printf ("%s — %s", title, _("Password Required"));
154  gtk_window_set_title (window, password_title);
155  g_free (password_title);
156 
157  gtk_header_bar_set_title (toolbar, _("Password Required"));
158  gtk_header_bar_set_subtitle (toolbar, title);
159  }
160  break;
162  g_assert_not_reached ();
163  break;
164  }
165 
166  g_free (title);
167  g_free (subtitle);
168  g_free (title_header);
169 }
170 
173 {
174  EvWindowTitle *window_title;
175 
176  window_title = g_new0 (EvWindowTitle, 1);
177  window_title->window = window;
178  window_title->type = EV_WINDOW_TITLE_DOCUMENT;
179 
180  ev_window_title_update (window_title);
181 
182  return window_title;
183 }
184 
185 void
187 {
188  window_title->type = type;
189 
190  ev_window_title_update (window_title);
191 }
192 
193 static void
195  GObject *document)
196 {
197  window_title->document = NULL;
198  g_clear_pointer (&window_title->doc_title, g_free);
199 }
200 
201 void
203  EvDocument *document)
204 {
205  if (window_title->document == document)
206  return;
207 
208  if (window_title->document)
209  g_object_weak_unref (G_OBJECT (window_title->document), (GWeakNotify)document_destroyed_cb, window_title);
210  window_title->document = document;
211  g_object_weak_ref (G_OBJECT (window_title->document), (GWeakNotify)document_destroyed_cb, window_title);
212  g_clear_pointer (&window_title->doc_title, g_free);
213 
214  if (window_title->document != NULL) {
215  gchar *doc_title;
216 
217  doc_title = g_strdup (ev_document_get_title (window_title->document));
218 
219  /* Make sure we get a valid title back */
220  if (doc_title != NULL) {
221  doc_title = g_strstrip (doc_title);
222 
223  if (doc_title[0] != '\0' &&
224  g_utf8_validate (doc_title, -1, NULL)) {
225  window_title->doc_title = doc_title;
226  } else {
227  g_free (doc_title);
228  }
229  }
230  }
231 
232  ev_window_title_update (window_title);
233 }
234 
235 void
237  const char *uri)
238 {
239  if (g_strcmp0 (uri, window_title->uri) == 0)
240  return;
241 
242  g_free (window_title->uri);
243  window_title->uri = g_strdup (uri);
244 
245  ev_window_title_update (window_title);
246 }
247 
248 void
250 {
251  if (window_title->document)
252  g_object_weak_unref (G_OBJECT (window_title->document), (GWeakNotify)document_destroyed_cb, window_title);
253  g_free (window_title->doc_title);
254  g_free (window_title->uri);
255  g_free (window_title);
256 }