]> www.fi.muni.cz Git - evince.git/blob - properties/ev-properties-view.c
Removed Removed
[evince.git] / properties / ev-properties-view.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
2 /* this file is part of evince, a gnome document viewer
3  *
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
19  */
20
21 #include "config.h"
22
23 #include <string.h>
24 #include <sys/time.h>
25 #include <time.h>
26
27 #ifdef HAVE__NL_MEASUREMENT_MEASUREMENT
28 #include <langinfo.h>
29 #endif
30
31 #include <glib/gi18n.h>
32 #include <gtk/gtk.h>
33
34 #include "ev-properties-view.h"
35
36 typedef enum {
37         TITLE_PROPERTY,
38         SUBJECT_PROPERTY,
39         AUTHOR_PROPERTY,
40         KEYWORDS_PROPERTY,
41         PRODUCER_PROPERTY,
42         CREATOR_PROPERTY,
43         CREATION_DATE_PROPERTY,
44         MOD_DATE_PROPERTY,
45         N_PAGES_PROPERTY,
46         LINEARIZED_PROPERTY,
47         FORMAT_PROPERTY,
48         SECURITY_PROPERTY,
49         PAPER_SIZE_PROPERTY
50 } Property;
51
52 typedef struct {
53         Property property;
54         const char *label;
55 } PropertyInfo;
56
57 static const PropertyInfo properties_info[] = {
58         { TITLE_PROPERTY,         N_("Title") },
59         { SUBJECT_PROPERTY,       N_("Subject") },
60         { AUTHOR_PROPERTY,        N_("Author") },
61         { KEYWORDS_PROPERTY,      N_("Keywords") },
62         { PRODUCER_PROPERTY,      N_("Producer") },
63         { CREATOR_PROPERTY,       N_("Creator") },
64         { CREATION_DATE_PROPERTY, N_("Created") },
65         { MOD_DATE_PROPERTY,      N_("Modified") },
66         { N_PAGES_PROPERTY,       N_("Number of Pages") },
67         { LINEARIZED_PROPERTY,    N_("Optimized") },
68         { FORMAT_PROPERTY,        N_("Format") },
69         { SECURITY_PROPERTY,      N_("Security") },
70         { PAPER_SIZE_PROPERTY,    N_("Paper Size") }
71 };
72
73 struct _EvPropertiesView {
74         GtkVBox base_instance;
75
76         GtkWidget *table;
77 };
78
79 struct _EvPropertiesViewClass {
80         GtkVBoxClass base_class;
81 };
82
83 G_DEFINE_TYPE (EvPropertiesView, ev_properties_view, GTK_TYPE_VBOX)
84
85 static void
86 ev_properties_view_class_init (EvPropertiesViewClass *properties_class)
87 {
88 }
89
90 /* Returns a locale specific date and time representation */
91 static char *
92 ev_properties_view_format_date (GTime utime)
93 {
94         time_t time = (time_t) utime;
95         struct tm t;
96         char s[256];
97         const char *fmt_hack = "%c";
98         size_t len;
99
100         if (time == 0 || !localtime_r (&time, &t)) return NULL;
101
102         len = strftime (s, sizeof (s), fmt_hack, &t);
103         if (len == 0 || s[0] == '\0') return NULL;
104
105         return g_locale_to_utf8 (s, -1, NULL, NULL, NULL);
106 }
107
108 /* This is cut out of gconvert.c from glib (and mildly modified).  Not all
109    backends give valid UTF-8 for properties, so we make sure that is.
110  */
111 static gchar *
112 make_valid_utf8 (const gchar *name)
113 {
114   GString *string;
115   const gchar *remainder, *invalid;
116   gint remaining_bytes, valid_bytes;
117   
118   string = NULL;
119   remainder = name;
120   remaining_bytes = strlen (name);
121   
122   while (remaining_bytes != 0) 
123     {
124       if (g_utf8_validate (remainder, remaining_bytes, &invalid)) 
125         break;
126       valid_bytes = invalid - remainder;
127     
128       if (string == NULL) 
129         string = g_string_sized_new (remaining_bytes);
130
131       g_string_append_len (string, remainder, valid_bytes);
132       g_string_append_c (string, '?');
133       
134       remaining_bytes -= valid_bytes + 1;
135       remainder = invalid + 1;
136     }
137   
138   if (string == NULL)
139     return g_strdup (name);
140   
141   g_string_append (string, remainder);
142
143   g_assert (g_utf8_validate (string->str, -1, NULL));
144   
145   return g_string_free (string, FALSE);
146 }
147
148 static void
149 set_property (GtkTable    *table,
150               Property     property,
151               const gchar *text,
152               gint        *row)
153 {
154         GtkWidget *label;
155         gchar     *markup;
156         gchar     *valid_text;
157
158         label = gtk_label_new (NULL);
159         g_object_set (G_OBJECT (label), "xalign", 0.0, NULL);
160         markup = g_strdup_printf ("<b>%s:</b>", properties_info[property].label);
161         gtk_label_set_markup (GTK_LABEL (label), markup);
162         g_free (markup);
163         
164         gtk_table_attach (table, label, 0, 1, *row, *row + 1,
165                           GTK_FILL, GTK_FILL, 0, 0);
166         gtk_widget_show (label);
167
168         label = gtk_label_new (NULL);
169         g_object_set (G_OBJECT (label),
170                       "xalign", 0.0,
171                       "width_chars", 25,
172                       "selectable", TRUE,
173                       "ellipsize", PANGO_ELLIPSIZE_END,
174                       NULL);
175         
176
177         if (text == NULL || text[0] == '\000') {
178                 markup = g_markup_printf_escaped ("<i>%s</i>", _("None"));
179                 gtk_label_set_markup (GTK_LABEL (label), markup);
180                 g_free (markup);
181         } else {
182                 valid_text = make_valid_utf8 (text ? text : "");
183                 gtk_label_set_text (GTK_LABEL (label), valid_text);
184                 g_free (valid_text);
185         }
186
187         gtk_table_attach (table, label, 1, 2, *row, *row + 1,
188                           GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
189         gtk_widget_show (label);
190
191         *row += 1;
192 }
193
194 static GtkUnit
195 get_default_user_units (void)
196 {
197         /* Translate to the default units to use for presenting
198          * lengths to the user. Translate to default:inch if you
199          * want inches, otherwise translate to default:mm.
200          * Do *not* translate it to "predefinito:mm", if it
201          * it isn't default:mm or default:inch it will not work
202          */
203         gchar *e = _("default:mm");
204
205 #ifdef HAVE__NL_MEASUREMENT_MEASUREMENT
206         gchar *imperial = NULL;
207         
208         imperial = nl_langinfo (_NL_MEASUREMENT_MEASUREMENT);
209         if (imperial && imperial[0] == 2)
210                 return GTK_UNIT_INCH;  /* imperial */
211         if (imperial && imperial[0] == 1)
212                 return GTK_UNIT_MM;  /* metric */
213 #endif
214
215         if (strcmp (e, "default:mm") == 0)
216                 return GTK_UNIT_MM;
217         if (strcmp (e, "default:inch") == 0)
218                 return GTK_UNIT_INCH;
219         
220         g_warning ("Whoever translated default:mm did so wrongly.\n");
221                                 
222         return GTK_UNIT_MM;
223 }
224
225 static gdouble
226 get_tolerance (gdouble size)
227 {
228         if (size < 150.0f)
229                 return 1.5f;
230         else if (size >= 150.0f && size <= 600.0f)
231                 return 2.0f;
232         else
233                 return 3.0f;
234 }
235
236 static char *
237 ev_regular_paper_size (const EvDocumentInfo *info)
238 {
239         GList *paper_sizes, *l;
240         gchar *exact_size;
241         gchar *str = NULL;
242         GtkUnit units;
243
244         units = get_default_user_units ();
245
246         if (units == GTK_UNIT_MM) {
247                 exact_size = g_strdup_printf(_("%.0f x %.0f mm"),
248                                              info->paper_width,
249                                              info->paper_height);
250         } else {
251                 exact_size = g_strdup_printf (_("%.2f x %.2f inch"),
252                                               info->paper_width  / 25.4f,
253                                               info->paper_height / 25.4f);
254         }
255
256         paper_sizes = gtk_paper_size_get_paper_sizes (FALSE);
257         
258         for (l = paper_sizes; l && l->data; l = g_list_next (l)) {
259                 GtkPaperSize *size = (GtkPaperSize *) l->data;
260                 gdouble paper_width;
261                 gdouble paper_height;
262                 gdouble width_tolerance;
263                 gdouble height_tolerance;
264
265                 paper_width = gtk_paper_size_get_width (size, GTK_UNIT_MM);
266                 paper_height = gtk_paper_size_get_height (size, GTK_UNIT_MM);
267
268                 width_tolerance = get_tolerance (paper_width);
269                 height_tolerance = get_tolerance (paper_height);
270
271                 if (ABS (info->paper_height - paper_height) <= height_tolerance &&
272                     ABS (info->paper_width  - paper_width) <= width_tolerance) {
273                         /* Note to translators: first placeholder is the paper name (eg.
274                          * A4), second placeholder is the paper size (eg. 297x210 mm) */
275                         str = g_strdup_printf (_("%s, Portrait (%s)"),
276                                                gtk_paper_size_get_display_name (size),
277                                                exact_size);
278                 } else if (ABS (info->paper_width  - paper_height) <= height_tolerance &&
279                            ABS (info->paper_height - paper_width) <= width_tolerance) {
280                         /* Note to translators: first placeholder is the paper name (eg.
281                          * A4), second placeholder is the paper size (eg. 297x210 mm) */
282                         str = g_strdup_printf ( _("%s, Landscape (%s)"),
283                                                 gtk_paper_size_get_display_name (size),
284                                                 exact_size);
285                 }
286         }
287
288         g_list_foreach (paper_sizes, (GFunc) gtk_paper_size_free, NULL);
289         g_list_free (paper_sizes);
290
291         if (str != NULL) {
292                 g_free (exact_size);
293                 return str;
294         }
295         
296         return exact_size;
297 }
298
299 void
300 ev_properties_view_set_info (EvPropertiesView *properties, const EvDocumentInfo *info)
301 {
302         GtkWidget *table;
303         gchar     *text;
304         gint       row = 0;
305
306         table = properties->table;
307         
308         if (info->fields_mask & EV_DOCUMENT_INFO_TITLE) {
309                 set_property (GTK_TABLE (table), TITLE_PROPERTY, info->title, &row);
310         }
311         if (info->fields_mask & EV_DOCUMENT_INFO_SUBJECT) {
312                 set_property (GTK_TABLE (table), SUBJECT_PROPERTY, info->subject, &row);
313         }
314         if (info->fields_mask & EV_DOCUMENT_INFO_AUTHOR) {
315                 set_property (GTK_TABLE (table), AUTHOR_PROPERTY, info->author, &row);
316         }
317         if (info->fields_mask & EV_DOCUMENT_INFO_KEYWORDS) {
318                 set_property (GTK_TABLE (table), KEYWORDS_PROPERTY, info->keywords, &row);
319         }
320         if (info->fields_mask & EV_DOCUMENT_INFO_PRODUCER) {
321                 set_property (GTK_TABLE (table), PRODUCER_PROPERTY, info->producer, &row);
322         }
323         if (info->fields_mask & EV_DOCUMENT_INFO_CREATOR) {
324                 set_property (GTK_TABLE (table), CREATOR_PROPERTY, info->creator, &row);
325         }
326         if (info->fields_mask & EV_DOCUMENT_INFO_CREATION_DATE) {
327                 text = ev_properties_view_format_date (info->creation_date);
328                 set_property (GTK_TABLE (table), CREATION_DATE_PROPERTY, text, &row);
329                 g_free (text);
330         }
331         if (info->fields_mask & EV_DOCUMENT_INFO_MOD_DATE) {
332                 text = ev_properties_view_format_date (info->modified_date);
333                 set_property (GTK_TABLE (table), MOD_DATE_PROPERTY, text, &row);
334                 g_free (text);
335         }
336         if (info->fields_mask & EV_DOCUMENT_INFO_FORMAT) {
337                 set_property (GTK_TABLE (table), FORMAT_PROPERTY, info->format, &row);
338         }
339         if (info->fields_mask & EV_DOCUMENT_INFO_N_PAGES) {
340                 text = g_strdup_printf ("%d", info->n_pages);
341                 set_property (GTK_TABLE (table), N_PAGES_PROPERTY, text, &row);
342                 g_free (text);
343         }
344         if (info->fields_mask & EV_DOCUMENT_INFO_LINEARIZED) {
345                 set_property (GTK_TABLE (table), LINEARIZED_PROPERTY, info->linearized, &row);
346         }
347         if (info->fields_mask & EV_DOCUMENT_INFO_SECURITY) {
348                 set_property (GTK_TABLE (table), SECURITY_PROPERTY, info->security, &row);
349         }
350         if (info->fields_mask & EV_DOCUMENT_INFO_PAPER_SIZE) {
351                 text = ev_regular_paper_size (info);
352                 set_property (GTK_TABLE (table), PAPER_SIZE_PROPERTY, text, &row);
353                 g_free (text);
354         }
355 }
356
357 static void
358 ev_properties_view_init (EvPropertiesView *properties)
359 {
360         properties->table = gtk_table_new (13, 2, FALSE);
361         gtk_table_set_col_spacings (GTK_TABLE (properties->table), 12);
362         gtk_table_set_row_spacings (GTK_TABLE (properties->table), 6);
363         gtk_container_set_border_width (GTK_CONTAINER (properties->table), 12);
364         gtk_box_pack_start (GTK_BOX (properties), properties->table, 
365                             TRUE, TRUE, 0);
366         gtk_widget_show (properties->table);
367 }
368
369 void
370 ev_properties_view_register_type (GTypeModule *module)
371 {
372         ev_properties_view_get_type ();
373 }
374
375 GtkWidget *
376 ev_properties_view_new (void)
377 {
378         EvPropertiesView *properties;
379
380         properties = g_object_new (EV_TYPE_PROPERTIES, NULL);
381
382         return GTK_WIDGET (properties);
383 }