source: poppler/vendor/current/glib/demo/utils.c@ 1159

Last change on this file since 1159 was 1159, checked in by Silvan Scherrer, 10 years ago

poppler: update vendor to 0.35.0

File size: 17.7 KB
Line 
1/*
2 * Copyright (C) 2007 Carlos Garcia Campos <carlosgc@gnome.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19#include <gtk/gtk.h>
20#include <stdio.h>
21#include <unistd.h>
22#include <time.h>
23
24#include "utils.h"
25
26void
27pgd_table_add_property_with_custom_widget (GtkGrid *table,
28 const gchar *markup,
29 GtkWidget *widget,
30 gint *row)
31{
32 GtkWidget *label;
33
34 label = gtk_label_new (NULL);
35 g_object_set (G_OBJECT (label), "xalign", 0.0, NULL);
36 gtk_label_set_markup (GTK_LABEL (label), markup);
37 gtk_grid_attach (GTK_GRID (table), label, 0, *row, 1, 1);
38 gtk_widget_show (label);
39
40 gtk_grid_attach (GTK_GRID (table), widget, 1, *row, 1, 1);
41 gtk_widget_set_hexpand (widget, TRUE);
42 gtk_widget_show (widget);
43
44 *row += 1;
45}
46
47void
48pgd_table_add_property_with_value_widget (GtkGrid *table,
49 const gchar *markup,
50 GtkWidget **value_widget,
51 const gchar *value,
52 gint *row)
53{
54 GtkWidget *label;
55
56 *value_widget = label = gtk_label_new (value);
57 g_object_set (G_OBJECT (label),
58 "xalign", 0.0,
59 "selectable", TRUE,
60 "ellipsize", PANGO_ELLIPSIZE_END,
61 NULL);
62 pgd_table_add_property_with_custom_widget (table, markup, label, row);
63}
64
65void
66pgd_table_add_property (GtkGrid *table,
67 const gchar *markup,
68 const gchar *value,
69 gint *row)
70{
71 GtkWidget *label;
72
73 pgd_table_add_property_with_value_widget (table, markup, &label, value, row);
74}
75
76GtkWidget *
77pgd_action_view_new (PopplerDocument *document)
78{
79 GtkWidget *frame, *label;
80
81 frame = gtk_frame_new (NULL);
82 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
83 label = gtk_label_new (NULL);
84 gtk_label_set_markup (GTK_LABEL (label), "<b>Action Properties</b>");
85 gtk_frame_set_label_widget (GTK_FRAME (frame), label);
86 gtk_widget_show (label);
87
88 g_object_set_data (G_OBJECT (frame), "document", document);
89
90 return frame;
91}
92
93static void
94pgd_action_view_add_destination (GtkWidget *action_view,
95 GtkGrid *table,
96 PopplerDest *dest,
97 gboolean remote,
98 gint *row)
99{
100 PopplerDocument *document;
101 GEnumValue *enum_value;
102 gchar *str;
103
104 pgd_table_add_property (table, "<b>Type:</b>", "Destination", row);
105
106 enum_value = g_enum_get_value ((GEnumClass *) g_type_class_ref (POPPLER_TYPE_DEST_TYPE), dest->type);
107 pgd_table_add_property (table, "<b>Destination Type:</b>", enum_value->value_name, row);
108
109 document = g_object_get_data (G_OBJECT (action_view), "document");
110
111 if (dest->type != POPPLER_DEST_NAMED) {
112 str = NULL;
113
114 if (document && !remote) {
115 PopplerPage *poppler_page;
116 gchar *page_label;
117
118 poppler_page = poppler_document_get_page (document, MAX (0, dest->page_num - 1));
119
120 g_object_get (G_OBJECT (poppler_page),
121 "label", &page_label,
122 NULL);
123 if (page_label) {
124 str = g_strdup_printf ("%d (%s)", dest->page_num, page_label);
125 g_free (page_label);
126 }
127 }
128
129 if (!str)
130 str = g_strdup_printf ("%d", dest->page_num);
131 pgd_table_add_property (table, "<b>Page:</b>", str, row);
132 g_free (str);
133
134 str = g_strdup_printf ("%.2f", dest->left);
135 pgd_table_add_property (table, "<b>Left:</b>", str, row);
136 g_free (str);
137
138 str = g_strdup_printf ("%.2f", dest->right);
139 pgd_table_add_property (table, "<b>Right:</b>", str, row);
140 g_free (str);
141
142 str = g_strdup_printf ("%.2f", dest->top);
143 pgd_table_add_property (table, "<b>Top:</b>", str, row);
144 g_free (str);
145
146 str = g_strdup_printf ("%.2f", dest->bottom);
147 pgd_table_add_property (table, "<b>Bottom:</b>", str, row);
148 g_free (str);
149
150 str = g_strdup_printf ("%.2f", dest->zoom);
151 pgd_table_add_property (table, "<b>Zoom:</b>", str, row);
152 g_free (str);
153 } else {
154 pgd_table_add_property (table, "<b>Named Dest:</b>", dest->named_dest, row);
155
156 if (document && !remote) {
157 PopplerDest *new_dest;
158
159 new_dest = poppler_document_find_dest (document, dest->named_dest);
160 if (new_dest) {
161 GtkWidget *new_table;
162 gint new_row = 0;
163
164 new_table = gtk_grid_new ();
165 gtk_widget_set_margin_top (new_table, 5);
166 gtk_widget_set_margin_bottom (new_table, 5);
167#if GTK_CHECK_VERSION(3, 12, 0)
168 gtk_widget_set_margin_start (new_table, 12);
169 gtk_widget_set_margin_end (new_table, 5);
170#else
171 gtk_widget_set_margin_left (new_table, 12);
172 gtk_widget_set_margin_right (new_table, 5);
173#endif
174 gtk_grid_set_column_spacing (GTK_GRID (new_table), 6);
175 gtk_grid_set_row_spacing (GTK_GRID (new_table), 6);
176
177 pgd_action_view_add_destination (action_view, GTK_GRID (new_table),
178 new_dest, FALSE, &new_row);
179 poppler_dest_free (new_dest);
180
181 gtk_grid_attach (GTK_GRID(table), new_table, 0, *row, 1, 1);
182 gtk_widget_show (new_table);
183
184 *row += 1;
185 }
186 }
187 }
188}
189
190static const gchar *
191get_movie_op (PopplerActionMovieOperation op)
192{
193 switch (op) {
194 case POPPLER_ACTION_MOVIE_PLAY:
195 return "Play";
196 case POPPLER_ACTION_MOVIE_PAUSE:
197 return "Pause";
198 case POPPLER_ACTION_MOVIE_RESUME:
199 return "Resume";
200 case POPPLER_ACTION_MOVIE_STOP:
201 return "Stop";
202 }
203 return NULL;
204}
205
206static void
207free_tmp_file (GFile *tmp_file)
208{
209
210 g_file_delete (tmp_file, NULL, NULL);
211 g_object_unref (tmp_file);
212}
213
214static gboolean
215save_helper (const gchar *buf,
216 gsize count,
217 gpointer data,
218 GError **error)
219{
220 gint fd = GPOINTER_TO_INT (data);
221
222 return write (fd, buf, count) == count;
223}
224
225static void
226pgd_action_view_play_rendition (GtkWidget *button,
227 PopplerMedia *media)
228{
229 GFile *file = NULL;
230 gchar *uri;
231
232 if (poppler_media_is_embedded (media)) {
233 gint fd;
234 gchar *tmp_filename = NULL;
235
236 fd = g_file_open_tmp (NULL, &tmp_filename, NULL);
237 if (fd != -1) {
238 if (poppler_media_save_to_callback (media, save_helper, GINT_TO_POINTER (fd), NULL)) {
239 file = g_file_new_for_path (tmp_filename);
240 g_object_set_data_full (G_OBJECT (media),
241 "tmp-file", g_object_ref (file),
242 (GDestroyNotify)free_tmp_file);
243 } else {
244 g_free (tmp_filename);
245 }
246 close (fd);
247 } else if (tmp_filename) {
248 g_free (tmp_filename);
249 }
250
251 } else {
252 const gchar *filename;
253
254 filename = poppler_media_get_filename (media);
255 if (g_path_is_absolute (filename)) {
256 file = g_file_new_for_path (filename);
257 } else if (g_strrstr (filename, "://")) {
258 file = g_file_new_for_uri (filename);
259 } else {
260 gchar *cwd;
261 gchar *path;
262
263 // FIXME: relative to doc uri, not cwd
264 cwd = g_get_current_dir ();
265 path = g_build_filename (cwd, filename, NULL);
266 g_free (cwd);
267
268 file = g_file_new_for_path (path);
269 g_free (path);
270 }
271 }
272
273 if (file) {
274 uri = g_file_get_uri (file);
275 g_object_unref (file);
276 if (uri) {
277 gtk_show_uri (gtk_widget_get_screen (button),
278 uri, GDK_CURRENT_TIME, NULL);
279 g_free (uri);
280 }
281 }
282}
283
284static void
285pgd_action_view_do_action_layer (GtkWidget *button,
286 GList *state_list)
287{
288 GList *l, *m;
289
290 for (l = state_list; l; l = g_list_next (l)) {
291 PopplerActionLayer *action_layer = (PopplerActionLayer *)l->data;
292
293 for (m = action_layer->layers; m; m = g_list_next (m)) {
294 PopplerLayer *layer = (PopplerLayer *)m->data;
295
296 switch (action_layer->action) {
297 case POPPLER_ACTION_LAYER_ON:
298 poppler_layer_show (layer);
299 break;
300 case POPPLER_ACTION_LAYER_OFF:
301 poppler_layer_hide (layer);
302 break;
303 case POPPLER_ACTION_LAYER_TOGGLE:
304 if (poppler_layer_is_visible (layer))
305 poppler_layer_hide (layer);
306 else
307 poppler_layer_show (layer);
308 break;
309 }
310 }
311 }
312}
313
314void
315pgd_action_view_set_action (GtkWidget *action_view,
316 PopplerAction *action)
317{
318 GtkWidget *table;
319 gint row = 0;
320
321 table = gtk_bin_get_child (GTK_BIN (action_view));
322 if (table) {
323 gtk_container_remove (GTK_CONTAINER (action_view), table);
324 }
325
326 if (!action)
327 return;
328
329 table = gtk_grid_new ();
330 gtk_widget_set_margin_top (table, 5);
331 gtk_widget_set_margin_bottom (table, 5);
332#if GTK_CHECK_VERSION(3, 12, 0)
333 gtk_widget_set_margin_start (table, 12);
334 gtk_widget_set_margin_end (table, 5);
335#else
336 gtk_widget_set_margin_left (table, 12);
337 gtk_widget_set_margin_right (table, 5);
338#endif
339 gtk_grid_set_column_spacing (GTK_GRID (table), 6);
340 gtk_grid_set_row_spacing (GTK_GRID (table), 6);
341
342 pgd_table_add_property (GTK_GRID (table), "<b>Title:</b>", action->any.title, &row);
343
344 switch (action->type) {
345 case POPPLER_ACTION_UNKNOWN:
346 pgd_table_add_property (GTK_GRID (table), "<b>Type:</b>", "Unknown", &row);
347 break;
348 case POPPLER_ACTION_NONE:
349 pgd_table_add_property (GTK_GRID (table), "<b>Type:</b>", "None", &row);
350 break;
351 case POPPLER_ACTION_GOTO_DEST:
352 pgd_action_view_add_destination (action_view, GTK_GRID (table), action->goto_dest.dest, FALSE, &row);
353 break;
354 case POPPLER_ACTION_GOTO_REMOTE:
355 pgd_table_add_property (GTK_GRID (table), "<b>Type:</b>", "Remote Destination", &row);
356 pgd_table_add_property (GTK_GRID (table), "<b>Filename:</b>", action->goto_remote.file_name, &row);
357 pgd_action_view_add_destination (action_view, GTK_GRID (table), action->goto_remote.dest, TRUE, &row);
358 break;
359 case POPPLER_ACTION_LAUNCH:
360 pgd_table_add_property (GTK_GRID (table), "<b>Type:</b>", "Launch", &row);
361 pgd_table_add_property (GTK_GRID (table), "<b>Filename:</b>", action->launch.file_name, &row);
362 pgd_table_add_property (GTK_GRID (table), "<b>Params:</b>", action->launch.params, &row);
363 break;
364 case POPPLER_ACTION_URI:
365 pgd_table_add_property (GTK_GRID (table), "<b>Type:</b>", "External URI", &row);
366 pgd_table_add_property (GTK_GRID (table), "<b>URI</b>", action->uri.uri, &row);
367 break;
368 case POPPLER_ACTION_NAMED:
369 pgd_table_add_property (GTK_GRID (table), "<b>Type:</b>", "Named Action", &row);
370 pgd_table_add_property (GTK_GRID (table), "<b>Name:</b>", action->named.named_dest, &row);
371 break;
372 case POPPLER_ACTION_MOVIE: {
373 GtkWidget *movie_view = pgd_movie_view_new ();
374
375 pgd_table_add_property (GTK_GRID (table), "<b>Type:</b>", "Movie", &row);
376 pgd_table_add_property (GTK_GRID (table), "<b>Operation:</b>", get_movie_op (action->movie.operation), &row);
377 pgd_movie_view_set_movie (movie_view, action->movie.movie);
378 pgd_table_add_property_with_custom_widget (GTK_GRID (table), "<b>Movie:</b>", movie_view, &row);
379 }
380 break;
381 case POPPLER_ACTION_RENDITION: {
382 gchar *text;
383
384 pgd_table_add_property (GTK_GRID (table), "<b>Type:</b>", "Rendition", &row);
385 text = g_strdup_printf ("%d", action->rendition.op);
386 pgd_table_add_property (GTK_GRID (table), "<b>Operation:</b>", text, &row);
387 g_free (text);
388 if (action->rendition.media) {
389 gboolean embedded = poppler_media_is_embedded (action->rendition.media);
390 GtkWidget *button;
391
392 pgd_table_add_property (GTK_GRID (table), "<b>Embedded:</b>", embedded ? "Yes": "No", &row);
393 if (embedded) {
394 const gchar *mime_type = poppler_media_get_mime_type (action->rendition.media);
395 pgd_table_add_property (GTK_GRID (table), "<b>Mime type:</b>",
396 mime_type ? mime_type : "",
397 &row);
398 } else {
399 pgd_table_add_property (GTK_GRID (table), "<b>Filename:</b>",
400 poppler_media_get_filename (action->rendition.media),
401 &row);
402 }
403
404 button = gtk_button_new_with_mnemonic ("_Play");
405 g_signal_connect (button, "clicked",
406 G_CALLBACK (pgd_action_view_play_rendition),
407 action->rendition.media);
408 pgd_table_add_property_with_custom_widget (GTK_GRID (table), NULL, button, &row);
409 gtk_widget_show (button);
410 }
411 }
412 break;
413 case POPPLER_ACTION_OCG_STATE: {
414 GList *l;
415 GtkWidget *button;
416
417 pgd_table_add_property (GTK_GRID (table), "<b>Type:</b>", "OCGState", &row);
418
419 for (l = action->ocg_state.state_list; l; l = g_list_next (l)) {
420 PopplerActionLayer *action_layer = (PopplerActionLayer *)l->data;
421 gchar *text = NULL;
422 gint n_layers = g_list_length (action_layer->layers);
423
424 switch (action_layer->action) {
425 case POPPLER_ACTION_LAYER_ON:
426 text = g_strdup_printf ("%d layers On", n_layers);
427 break;
428 case POPPLER_ACTION_LAYER_OFF:
429 text = g_strdup_printf ("%d layers Off", n_layers);
430 break;
431 case POPPLER_ACTION_LAYER_TOGGLE:
432 text = g_strdup_printf ("%d layers Toggle", n_layers);
433 break;
434 }
435 pgd_table_add_property (GTK_GRID (table), "<b>Action:</b>", text, &row);
436 g_free (text);
437 }
438
439 button = gtk_button_new_with_label ("Do action");
440 g_signal_connect (button, "clicked",
441 G_CALLBACK (pgd_action_view_do_action_layer),
442 action->ocg_state.state_list);
443 pgd_table_add_property_with_custom_widget (GTK_GRID (table), NULL, button, &row);
444 gtk_widget_show (button);
445 }
446 break;
447 case POPPLER_ACTION_JAVASCRIPT: {
448 GtkTextBuffer *buffer;
449 GtkWidget *textview;
450 GtkWidget *swindow;
451
452 pgd_table_add_property (GTK_GRID (table), "<b>Type:</b>", "JavaScript", &row);
453
454 buffer = gtk_text_buffer_new (NULL);
455 if (action->javascript.script)
456 gtk_text_buffer_set_text (buffer, action->javascript.script, -1);
457
458 textview = gtk_text_view_new_with_buffer (buffer);
459 gtk_text_view_set_editable (GTK_TEXT_VIEW (textview), FALSE);
460 g_object_unref (buffer);
461
462 swindow = gtk_scrolled_window_new (NULL, NULL);
463 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow),
464 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
465 gtk_container_add (GTK_CONTAINER (swindow), textview);
466 gtk_widget_show (textview);
467
468 pgd_table_add_property_with_custom_widget (GTK_GRID (table), NULL, swindow, &row);
469 gtk_widget_show (swindow);
470 }
471 break;
472 default:
473 g_assert_not_reached ();
474 }
475
476 gtk_container_add (GTK_CONTAINER (action_view), table);
477 gtk_widget_show (table);
478}
479
480gchar *
481pgd_format_date (time_t utime)
482{
483 time_t time = (time_t) utime;
484 char s[256];
485 const char *fmt_hack = "%c";
486 size_t len;
487#ifdef HAVE_LOCALTIME_R
488 struct tm t;
489 if (time == 0 || !localtime_r (&time, &t)) return NULL;
490 len = strftime (s, sizeof (s), fmt_hack, &t);
491#else
492 struct tm *t;
493 if (time == 0 || !(t = localtime (&time)) ) return NULL;
494 len = strftime (s, sizeof (s), fmt_hack, t);
495#endif
496
497 if (len == 0 || s[0] == '\0') return NULL;
498
499 return g_locale_to_utf8 (s, -1, NULL, NULL, NULL);
500}
501
502GtkWidget *
503pgd_movie_view_new (void)
504{
505 GtkWidget *frame, *label;
506
507 frame = gtk_frame_new (NULL);
508 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
509 label = gtk_label_new (NULL);
510 gtk_label_set_markup (GTK_LABEL (label), "<b>Movie Properties</b>");
511 gtk_frame_set_label_widget (GTK_FRAME (frame), label);
512 gtk_widget_show (label);
513
514 return frame;
515}
516
517static void
518pgd_movie_view_play_movie (GtkWidget *button,
519 PopplerMovie *movie)
520{
521 const gchar *filename;
522 GFile *file;
523 gchar *uri;
524
525 filename = poppler_movie_get_filename (movie);
526 if (g_path_is_absolute (filename)) {
527 file = g_file_new_for_path (filename);
528 } else if (g_strrstr (filename, "://")) {
529 file = g_file_new_for_uri (filename);
530 } else {
531 gchar *cwd;
532 gchar *path;
533
534 // FIXME: relative to doc uri, not cwd
535 cwd = g_get_current_dir ();
536 path = g_build_filename (cwd, filename, NULL);
537 g_free (cwd);
538
539 file = g_file_new_for_path (path);
540 g_free (path);
541 }
542
543 uri = g_file_get_uri (file);
544 g_object_unref (file);
545 if (uri) {
546 gtk_show_uri (gtk_widget_get_screen (button),
547 uri, GDK_CURRENT_TIME, NULL);
548 g_free (uri);
549 }
550}
551
552void
553pgd_movie_view_set_movie (GtkWidget *movie_view,
554 PopplerMovie *movie)
555{
556 GtkWidget *table;
557 GtkWidget *button;
558 gint row = 0;
559
560 table = gtk_bin_get_child (GTK_BIN (movie_view));
561 if (table) {
562 gtk_container_remove (GTK_CONTAINER (movie_view), table);
563 }
564
565 if (!movie)
566 return;
567
568 table = gtk_grid_new ();
569 gtk_widget_set_margin_top (table, 5);
570 gtk_widget_set_margin_bottom (table, 5);
571#if GTK_CHECK_VERSION(3, 12, 0)
572 gtk_widget_set_margin_start (table, 12);
573 gtk_widget_set_margin_end (table, 5);
574#else
575 gtk_widget_set_margin_left (table, 12);
576 gtk_widget_set_margin_right (table, 5);
577#endif
578 gtk_grid_set_column_spacing (GTK_GRID (table), 6);
579 gtk_grid_set_row_spacing (GTK_GRID (table), 6);
580
581 pgd_table_add_property (GTK_GRID (table), "<b>Filename:</b>", poppler_movie_get_filename (movie), &row);
582 pgd_table_add_property (GTK_GRID (table), "<b>Need Poster:</b>", poppler_movie_need_poster (movie) ? "Yes" : "No", &row);
583 pgd_table_add_property (GTK_GRID (table), "<b>Show Controls:</b>", poppler_movie_show_controls (movie) ? "Yes" : "No", &row);
584
585 button = gtk_button_new_with_mnemonic ("_Play");
586 g_signal_connect (button, "clicked",
587 G_CALLBACK (pgd_movie_view_play_movie),
588 movie);
589 pgd_table_add_property_with_custom_widget (GTK_GRID (table), NULL, button, &row);
590 gtk_widget_show (button);
591
592 gtk_container_add (GTK_CONTAINER (movie_view), table);
593 gtk_widget_show (table);
594}
595
596GdkPixbuf *
597pgd_pixbuf_new_for_color (PopplerColor *poppler_color)
598{
599 GdkPixbuf *pixbuf;
600 gint num, x;
601 guchar *pixels;
602
603 if (!poppler_color)
604 return NULL;
605
606 pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
607 FALSE, 8,
608 64, 16);
609
610 pixels = gdk_pixbuf_get_pixels (pixbuf);
611 num = gdk_pixbuf_get_width (pixbuf) * gdk_pixbuf_get_height (pixbuf);
612
613 for (x = 0; x < num; x++) {
614 pixels[0] = poppler_color->red;
615 pixels[1] = poppler_color->green;
616 pixels[2] = poppler_color->blue;
617 pixels += 3;
618 }
619
620 return pixbuf;
621}
Note: See TracBrowser for help on using the repository browser.