1 #include <glib.h>
2 #include <gio/gio.h>
3 #include <cairo.h>
4 #include <gtk/gtk.h>
5 #include <stdlib.h>
6
7 #include <libgxps/gxps.h>
8
9 typedef struct {
10 GtkWidget *darea;
11 GtkWidget *spin_button;
12
13 GXPSDocument *doc;
14 cairo_surface_t *surface;
15 } GXPSView;
16
17 static gboolean
drawing_area_draw(GtkWidget * drawing_area,cairo_t * cr,GXPSView * view)18 drawing_area_draw (GtkWidget *drawing_area,
19 cairo_t *cr,
20 GXPSView *view)
21 {
22 if (!view->surface)
23 return FALSE;
24
25 cairo_set_source_rgb (cr, 1., 1., 1.);
26 cairo_rectangle (cr, 0, 0,
27 cairo_image_surface_get_width (view->surface),
28 cairo_image_surface_get_height (view->surface));
29 cairo_fill (cr);
30 cairo_set_source_surface (cr, view->surface, 0, 0);
31 cairo_paint (cr);
32
33 return TRUE;
34 }
35
36 static void
page_changed_callback(GtkSpinButton * button,GXPSView * view)37 page_changed_callback (GtkSpinButton *button,
38 GXPSView *view)
39 {
40 GXPSPage *xps_page;
41 gint page;
42 gdouble width, height;
43 cairo_t *cr;
44 GError *error = NULL;
45
46 page = gtk_spin_button_get_value_as_int (button);
47
48 xps_page = gxps_document_get_page (view->doc, page, &error);
49 if (error) {
50 g_printerr ("Error getting page %d: %s\n", page, error->message);
51 g_error_free (error);
52
53 return;
54 }
55 gxps_page_get_size (xps_page, &width, &height);
56
57 cairo_surface_destroy (view->surface);
58 view->surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
59 width, height);
60
61 cr = cairo_create (view->surface);
62 gxps_page_render (xps_page, cr, &error);
63 if (error) {
64 g_printerr ("Error rendering page: %d: %s\n", page, error->message);
65 g_error_free (error);
66 }
67 cairo_destroy (cr);
68
69 gtk_widget_set_size_request (view->darea, width, height);
70 gtk_widget_queue_draw (view->darea);
71
72 g_object_unref (xps_page);
73 }
74
75 static gchar *
format_date(time_t utime)76 format_date (time_t utime)
77 {
78 time_t time = (time_t) utime;
79 char s[256];
80 const char *fmt_hack = "%c";
81 size_t len;
82 #ifdef HAVE_LOCALTIME_R
83 struct tm t;
84 if (time == 0 || !localtime_r (&time, &t))
85 return NULL;
86 len = strftime (s, sizeof (s), fmt_hack, &t);
87 #else
88 struct tm *t;
89 if (time == 0 || !(t = localtime (&time)) )
90 return NULL;
91 #pragma GCC diagnostic push
92 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
93 len = strftime (s, sizeof (s), fmt_hack, t);
94 #pragma GCC diagnostic pop
95 #endif
96
97 if (len == 0 || s[0] == '\0')
98 return NULL;
99
100 return g_locale_to_utf8 (s, -1, NULL, NULL, NULL);
101 }
102
103
104 static void
append_row_to_table(GtkWidget * table,const gchar * key,const gchar * value)105 append_row_to_table (GtkWidget *table,
106 const gchar *key,
107 const gchar *value)
108 {
109 GtkWidget *key_label;
110 GtkWidget *value_label;
111
112 if (!value)
113 return;
114
115 key_label = gtk_label_new (NULL);
116 g_object_set (G_OBJECT (key_label), "xalign", 0.0, NULL);
117 gtk_label_set_markup (GTK_LABEL (key_label), key);
118 gtk_container_add (GTK_CONTAINER (table), key_label);
119 gtk_widget_show (key_label);
120
121 value_label = gtk_label_new (value);
122 g_object_set (G_OBJECT (value_label),
123 "xalign", 0.0,
124 "selectable", TRUE,
125 "ellipsize", PANGO_ELLIPSIZE_END,
126 "hexpand", TRUE,
127 NULL);
128 gtk_grid_attach_next_to (GTK_GRID (table),
129 value_label,
130 key_label,
131 GTK_POS_RIGHT,
132 1, 1);
133 gtk_widget_show (value_label);
134 }
135
136 static void
properties_button_clicked(GtkWidget * button,GXPSFile * xps)137 properties_button_clicked (GtkWidget *button, GXPSFile *xps)
138 {
139 GtkWidget *dialog;
140 GtkWidget *table;
141 GXPSCoreProperties *core_props;
142 gchar *date;
143 GError *error = NULL;
144
145 core_props = gxps_file_get_core_properties (xps, &error);
146 if (!core_props) {
147 if (error) {
148 g_printerr ("Error getting core properties: %s\n", error->message);
149 g_error_free (error);
150 }
151 return;
152 }
153
154 dialog = gtk_dialog_new_with_buttons ("Document Properties",
155 GTK_WINDOW (gtk_widget_get_toplevel (button)),
156 GTK_DIALOG_DESTROY_WITH_PARENT,
157 "Close", GTK_RESPONSE_CLOSE,
158 NULL);
159 g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
160
161 table = gtk_grid_new ();
162 gtk_container_set_border_width (GTK_CONTAINER (table), 5);
163 gtk_orientable_set_orientation (GTK_ORIENTABLE (table), GTK_ORIENTATION_VERTICAL);
164 gtk_grid_set_column_spacing (GTK_GRID (table), 6);
165 gtk_grid_set_row_spacing (GTK_GRID (table), 6);
166
167 append_row_to_table (table, "<b>Title:</b>", gxps_core_properties_get_title (core_props));
168 append_row_to_table (table, "<b>Creator:</b>", gxps_core_properties_get_creator (core_props));
169 append_row_to_table (table, "<b>Description:</b>", gxps_core_properties_get_description (core_props));
170 append_row_to_table (table, "<b>Subject:</b>", gxps_core_properties_get_subject (core_props));
171 append_row_to_table (table, "<b>Keywords:</b>", gxps_core_properties_get_keywords (core_props));
172 append_row_to_table (table, "<b>Version:</b>", gxps_core_properties_get_version (core_props));
173 append_row_to_table (table, "<b>Revision:</b>", gxps_core_properties_get_revision (core_props));
174 append_row_to_table (table, "<b>Identifier:</b>", gxps_core_properties_get_identifier (core_props));
175 append_row_to_table (table, "<b>Language:</b>", gxps_core_properties_get_language (core_props));
176 append_row_to_table (table, "<b>Category:</b>", gxps_core_properties_get_category (core_props));
177 append_row_to_table (table, "<b>Content Status:</b>", gxps_core_properties_get_content_status (core_props));
178 append_row_to_table (table, "<b>Content Type:</b>", gxps_core_properties_get_content_type (core_props));
179 date = format_date (gxps_core_properties_get_created (core_props));
180 append_row_to_table (table, "<b>Created:</b>", date);
181 g_free (date);
182 append_row_to_table (table, "<b>Last Modified By:</b>", gxps_core_properties_get_last_modified_by (core_props));
183 date = format_date (gxps_core_properties_get_modified (core_props));
184 append_row_to_table (table, "<b>Modified:</b>", date);
185 g_free (date);
186 date = format_date (gxps_core_properties_get_last_printed (core_props));
187 append_row_to_table (table, "<b>Las Printed:</b>", date);
188 g_free (date);
189
190 gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), table);
191 gtk_widget_show (table);
192
193 gtk_widget_show (dialog);
194
195 g_object_unref (core_props);
196 }
197
main(gint argc,gchar ** argv)198 gint main (gint argc, gchar **argv)
199 {
200 GFile *file;
201 GXPSFile *xps;
202 GXPSView *view;
203 GtkWidget *win;
204 GtkWidget *hbox, *vbox, *sw;
205 GtkWidget *button;
206 guint page = 0;
207 GError *error = NULL;
208
209 if (argc < 2) {
210 g_printerr ("Use: test-xps file\n");
211
212 return 1;
213 }
214
215 gtk_init (&argc, &argv);
216
217 file = g_file_new_for_commandline_arg (argv[1]);
218 xps = gxps_file_new (file, &error);
219 g_object_unref (file);
220
221 if (error) {
222 g_printerr ("Error creating file: %s\n", error->message);
223 g_error_free (error);
224 g_object_unref (xps);
225
226 return 1;
227 }
228
229 view = g_new0 (GXPSView, 1);
230 view->doc = gxps_file_get_document (xps, 0, &error);
231 if (error) {
232 g_printerr ("Error getting document 0: %s\n", error->message);
233 g_error_free (error);
234 g_object_unref (xps);
235
236 return 1;
237 }
238
239 win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
240 gtk_window_set_default_size (GTK_WINDOW (win), 600, 600);
241 g_signal_connect (win, "delete-event",
242 G_CALLBACK (gtk_main_quit),
243 NULL);
244
245 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
246
247 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
248 view->spin_button = gtk_spin_button_new_with_range (0,
249 gxps_document_get_n_pages (view->doc) - 1,
250 1);
251 g_signal_connect (view->spin_button,
252 "value-changed",
253 G_CALLBACK (page_changed_callback),
254 view);
255 gtk_box_pack_end (GTK_BOX (hbox), view->spin_button, FALSE, TRUE, 0);
256 gtk_widget_show (view->spin_button);
257
258 button = gtk_button_new ();
259 g_signal_connect (button, "clicked",
260 G_CALLBACK (properties_button_clicked),
261 xps);
262 gtk_button_set_image (GTK_BUTTON (button),
263 gtk_image_new_from_icon_name ("document-properties", GTK_ICON_SIZE_SMALL_TOOLBAR));
264 gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
265 gtk_widget_show (button);
266
267 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
268 gtk_widget_show (hbox);
269
270 view->darea = gtk_drawing_area_new ();
271 g_signal_connect (view->darea, "draw",
272 G_CALLBACK (drawing_area_draw),
273 view);
274
275 sw = gtk_scrolled_window_new (NULL, NULL);
276 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
277 GTK_POLICY_AUTOMATIC,
278 GTK_POLICY_AUTOMATIC);
279 gtk_container_add (GTK_CONTAINER (sw), view->darea);
280 gtk_widget_show (view->darea);
281
282 gtk_box_pack_end (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
283 gtk_widget_show (sw);
284
285 gtk_container_add (GTK_CONTAINER (win), vbox);
286 gtk_widget_show (vbox);
287
288 gtk_widget_show (win);
289
290 if (argc > 2)
291 page = atoi (argv[2]);
292 gtk_spin_button_set_value (GTK_SPIN_BUTTON (view->spin_button), page);
293 if (page == 0)
294 page_changed_callback (GTK_SPIN_BUTTON (view->spin_button), view);
295
296 gtk_main ();
297
298 g_object_unref (view->doc);
299 g_object_unref (xps);
300 cairo_surface_destroy (view->surface);
301 g_free (view);
302
303 return 0;
304 }
305