]> www.fi.muni.cz Git - evince.git/blob - properties/ev-properties-view.c
Check if date is invalid. Fix for bug 318134.
[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 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "ev-properties-view.h"
26 #include "ev-document-fonts.h"
27
28 #include <glib/gi18n.h>
29 #include <gtk/gtk.h>
30 #include <glade/glade.h>
31 #include <time.h>
32 #include <sys/time.h>
33 #include <string.h>
34
35 typedef enum
36 {
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 } Property;
50
51 typedef struct
52 {
53         Property property;
54         const char *label_id;
55 } PropertyInfo;
56
57 static const PropertyInfo properties_info[] = {
58         { TITLE_PROPERTY, "title" },
59         { SUBJECT_PROPERTY, "subject" },
60         { AUTHOR_PROPERTY, "author" },
61         { KEYWORDS_PROPERTY, "keywords" },
62         { PRODUCER_PROPERTY, "producer" },
63         { CREATOR_PROPERTY, "creator" },
64         { CREATION_DATE_PROPERTY, "created" },
65         { MOD_DATE_PROPERTY, "modified" },
66         { N_PAGES_PROPERTY, "pages" },
67         { LINEARIZED_PROPERTY, "optimized" },
68         { FORMAT_PROPERTY, "version" },
69         { SECURITY_PROPERTY, "security" }
70 };
71
72 struct _EvPropertiesView {
73         GtkVBox base_instance;
74
75         GladeXML *xml;
76 };
77
78 struct _EvPropertiesViewClass {
79         GtkVBoxClass base_class;
80 };
81
82 G_DEFINE_TYPE (EvPropertiesView, ev_properties_view, GTK_TYPE_VBOX)
83
84 static void
85 ev_properties_view_dispose (GObject *object)
86 {
87         EvPropertiesView *properties = EV_PROPERTIES_VIEW (object);
88
89         if (properties->xml) {
90                 g_object_unref (properties->xml);
91                 properties->xml = NULL;
92         }
93 }
94
95 static void
96 ev_properties_view_class_init (EvPropertiesViewClass *properties_class)
97 {
98         GObjectClass *g_object_class = G_OBJECT_CLASS (properties_class);
99
100         g_object_class->dispose = ev_properties_view_dispose;
101 }
102
103 /* Returns a locale specific date and time representation */
104 static char *
105 ev_properties_view_format_date (GTime utime)
106 {
107         time_t time = (time_t) utime;
108         struct tm t;
109         char s[256];
110         const char *fmt_hack = "%c";
111         size_t len;
112
113         if (time == 0 || !localtime_r (&time, &t)) return NULL;
114
115         len = strftime (s, sizeof (s), fmt_hack, &t);
116         if (len == 0 || s[0] == '\0') return NULL;
117
118         return g_locale_to_utf8 (s, -1, NULL, NULL, NULL);
119 }
120
121 /* This is cut out of gconvert.c from glib (and mildly modified).  Not all
122    backends give valid UTF-8 for properties, so we make sure that is.
123  */
124 static gchar *
125 make_valid_utf8 (const gchar *name)
126 {
127   GString *string;
128   const gchar *remainder, *invalid;
129   gint remaining_bytes, valid_bytes;
130   
131   string = NULL;
132   remainder = name;
133   remaining_bytes = strlen (name);
134   
135   while (remaining_bytes != 0) 
136     {
137       if (g_utf8_validate (remainder, remaining_bytes, &invalid)) 
138         break;
139       valid_bytes = invalid - remainder;
140     
141       if (string == NULL) 
142         string = g_string_sized_new (remaining_bytes);
143
144       g_string_append_len (string, remainder, valid_bytes);
145       g_string_append_c (string, '?');
146       
147       remaining_bytes -= valid_bytes + 1;
148       remainder = invalid + 1;
149     }
150   
151   if (string == NULL)
152     return g_strdup (name);
153   
154   g_string_append (string, remainder);
155
156   g_assert (g_utf8_validate (string->str, -1, NULL));
157   
158   return g_string_free (string, FALSE);
159 }
160
161 static void
162 set_property (GladeXML *xml, Property property, const char *text)
163 {
164         GtkWidget *widget;
165         char *valid_text;
166
167         widget = glade_xml_get_widget (xml, properties_info[property].label_id);
168         g_return_if_fail (GTK_IS_LABEL (widget));
169
170         if (text == NULL || text[0] == '\000') {
171                 gchar *markup;
172
173                 markup = g_markup_printf_escaped ("<i>%s</i>", _("None"));
174                 gtk_label_set_markup (GTK_LABEL (widget), markup);
175                 g_free (markup);
176
177                 return;
178         }
179         text = text ? text : "";
180
181         valid_text = make_valid_utf8 (text);
182
183         gtk_label_set_text (GTK_LABEL (widget), valid_text);
184
185         g_free (valid_text);
186 }
187
188 void
189 ev_properties_view_set_info (EvPropertiesView *properties, const EvDocumentInfo *info)
190 {
191         GladeXML *xml = properties->xml;
192         char *text;
193
194         if (info->fields_mask & EV_DOCUMENT_INFO_TITLE) {
195                 set_property (xml, TITLE_PROPERTY, info->title);
196         }
197         if (info->fields_mask & EV_DOCUMENT_INFO_SUBJECT) {
198                 set_property (xml, SUBJECT_PROPERTY, info->subject);
199         }
200         if (info->fields_mask & EV_DOCUMENT_INFO_AUTHOR) {
201                 set_property (xml, AUTHOR_PROPERTY, info->author);
202         }
203         if (info->fields_mask & EV_DOCUMENT_INFO_KEYWORDS) {
204                 set_property (xml, KEYWORDS_PROPERTY, info->keywords);
205         }
206         if (info->fields_mask & EV_DOCUMENT_INFO_PRODUCER) {
207                 set_property (xml, PRODUCER_PROPERTY, info->producer);
208         }
209         if (info->fields_mask & EV_DOCUMENT_INFO_CREATOR) {
210                 set_property (xml, CREATOR_PROPERTY, info->creator);
211         }
212         if (info->fields_mask & EV_DOCUMENT_INFO_CREATION_DATE) {
213                 text = ev_properties_view_format_date (info->creation_date);
214                 set_property (xml, CREATION_DATE_PROPERTY, text);
215                 g_free (text);
216         }
217         if (info->fields_mask & EV_DOCUMENT_INFO_MOD_DATE) {
218                 text = ev_properties_view_format_date (info->modified_date);
219                 set_property (xml, MOD_DATE_PROPERTY, text);
220                 g_free (text);
221         }
222         if (info->fields_mask & EV_DOCUMENT_INFO_FORMAT) {
223                 text = g_strdup_printf ("%s", info->format);
224                 set_property (xml, FORMAT_PROPERTY, text);
225                 g_free (text);
226         }
227         if (info->fields_mask & EV_DOCUMENT_INFO_N_PAGES) {
228                 text = g_strdup_printf ("%d", info->n_pages);
229                 set_property (xml, N_PAGES_PROPERTY, text);
230                 g_free (text);
231         }
232         if (info->fields_mask & EV_DOCUMENT_INFO_LINEARIZED) {
233                 set_property (xml, LINEARIZED_PROPERTY, info->linearized);
234         }
235         if (info->fields_mask & EV_DOCUMENT_INFO_SECURITY) {
236                 set_property (xml, SECURITY_PROPERTY, info->security);
237         }
238 }
239
240 static void
241 ev_properties_view_init (EvPropertiesView *properties)
242 {
243         GladeXML *xml;
244
245         /* Create a new GladeXML object from XML file glade_file */
246         xml = glade_xml_new (DATADIR "/evince-properties.glade", "general_page_root", GETTEXT_PACKAGE);
247         properties->xml = xml;
248         g_assert (xml != NULL);
249
250         gtk_box_pack_start (GTK_BOX (properties),
251                             glade_xml_get_widget (xml, "general_page_root"),
252                             TRUE, TRUE, 0);
253 }
254
255 void
256 ev_properties_view_register_type (GTypeModule *module)
257 {
258         ev_properties_view_get_type ();
259 }
260
261 GtkWidget *
262 ev_properties_view_new (void)
263 {
264         EvPropertiesView *properties;
265
266         properties = g_object_new (EV_TYPE_PROPERTIES, NULL);
267
268         return GTK_WIDGET (properties);
269 }