Spaces:
Running
Running
/* | |
* Copyright (C) 2007 Carlos Garcia Campos <[email protected]> | |
* | |
* This program is free software; you can redistribute it and/or modify | |
* it under the terms of the GNU General Public License as published by | |
* the Free Software Foundation; either version 2, or (at your option) | |
* any later version. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License | |
* along with this program; if not, write to the Free Software | |
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. | |
*/ | |
void pgd_table_add_property_with_custom_widget(GtkGrid *table, const gchar *markup, GtkWidget *widget, gint *row) | |
{ | |
GtkWidget *label; | |
label = gtk_label_new(NULL); | |
g_object_set(G_OBJECT(label), "xalign", 0.0, "yalign", 0.0, NULL); | |
gtk_label_set_markup(GTK_LABEL(label), markup); | |
gtk_grid_attach(GTK_GRID(table), label, 0, *row, 1, 1); | |
gtk_widget_show(label); | |
gtk_grid_attach(GTK_GRID(table), widget, 1, *row, 1, 1); | |
gtk_widget_set_hexpand(widget, TRUE); | |
gtk_widget_show(widget); | |
*row += 1; | |
} | |
void pgd_table_add_property_with_value_widget(GtkGrid *table, const gchar *markup, GtkWidget **value_widget, const gchar *value, gint *row) | |
{ | |
GtkWidget *label; | |
*value_widget = label = gtk_label_new(value); | |
g_object_set(G_OBJECT(label), "xalign", 0.0, "selectable", TRUE, "ellipsize", PANGO_ELLIPSIZE_END, NULL); | |
pgd_table_add_property_with_custom_widget(table, markup, label, row); | |
} | |
void pgd_table_add_property(GtkGrid *table, const gchar *markup, const gchar *value, gint *row) | |
{ | |
GtkWidget *label; | |
pgd_table_add_property_with_value_widget(table, markup, &label, value, row); | |
} | |
GtkWidget *pgd_action_view_new(PopplerDocument *document) | |
{ | |
GtkWidget *frame, *label; | |
frame = gtk_frame_new(NULL); | |
gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_NONE); | |
label = gtk_label_new(NULL); | |
gtk_label_set_markup(GTK_LABEL(label), "<b>Action Properties</b>"); | |
gtk_frame_set_label_widget(GTK_FRAME(frame), label); | |
gtk_widget_show(label); | |
g_object_set_data(G_OBJECT(frame), "document", document); | |
return frame; | |
} | |
static void pgd_action_view_add_destination(GtkWidget *action_view, GtkGrid *table, PopplerDest *dest, gboolean remote, gint *row) | |
{ | |
PopplerDocument *document; | |
GEnumValue *enum_value; | |
gchar *str; | |
pgd_table_add_property(table, "<b>Type:</b>", "Destination", row); | |
enum_value = g_enum_get_value((GEnumClass *)g_type_class_ref(POPPLER_TYPE_DEST_TYPE), dest->type); | |
pgd_table_add_property(table, "<b>Destination Type:</b>", enum_value->value_name, row); | |
document = g_object_get_data(G_OBJECT(action_view), "document"); | |
if (dest->type != POPPLER_DEST_NAMED) { | |
str = NULL; | |
if (document && !remote) { | |
PopplerPage *poppler_page; | |
gchar *page_label; | |
poppler_page = poppler_document_get_page(document, MAX(0, dest->page_num - 1)); | |
g_object_get(G_OBJECT(poppler_page), "label", &page_label, NULL); | |
if (page_label) { | |
str = g_strdup_printf("%d (%s)", dest->page_num, page_label); | |
g_free(page_label); | |
} | |
} | |
if (!str) { | |
str = g_strdup_printf("%d", dest->page_num); | |
} | |
pgd_table_add_property(table, "<b>Page:</b>", str, row); | |
g_free(str); | |
str = g_strdup_printf("%.2f", dest->left); | |
pgd_table_add_property(table, "<b>Left:</b>", str, row); | |
g_free(str); | |
str = g_strdup_printf("%.2f", dest->right); | |
pgd_table_add_property(table, "<b>Right:</b>", str, row); | |
g_free(str); | |
str = g_strdup_printf("%.2f", dest->top); | |
pgd_table_add_property(table, "<b>Top:</b>", str, row); | |
g_free(str); | |
str = g_strdup_printf("%.2f", dest->bottom); | |
pgd_table_add_property(table, "<b>Bottom:</b>", str, row); | |
g_free(str); | |
str = g_strdup_printf("%.2f", dest->zoom); | |
pgd_table_add_property(table, "<b>Zoom:</b>", str, row); | |
g_free(str); | |
} else { | |
if (document && !remote) { | |
PopplerDest *new_dest; | |
new_dest = poppler_document_find_dest(document, dest->named_dest); | |
if (new_dest) { | |
GtkWidget *new_table; | |
gint new_row = 0; | |
new_table = gtk_grid_new(); | |
gtk_widget_set_margin_top(new_table, 5); | |
gtk_widget_set_margin_bottom(new_table, 5); | |
gtk_widget_set_margin_start(new_table, 12); | |
gtk_widget_set_margin_end(new_table, 5); | |
gtk_widget_set_margin_left(new_table, 12); | |
gtk_widget_set_margin_right(new_table, 5); | |
gtk_grid_set_column_spacing(GTK_GRID(new_table), 6); | |
gtk_grid_set_row_spacing(GTK_GRID(new_table), 6); | |
pgd_action_view_add_destination(action_view, GTK_GRID(new_table), new_dest, FALSE, &new_row); | |
poppler_dest_free(new_dest); | |
gtk_grid_attach(GTK_GRID(table), new_table, 0, *row, 1, 1); | |
gtk_widget_show(new_table); | |
*row += 1; | |
} | |
} | |
} | |
} | |
static const gchar *get_movie_op(PopplerActionMovieOperation op) | |
{ | |
switch (op) { | |
case POPPLER_ACTION_MOVIE_PLAY: | |
return "Play"; | |
case POPPLER_ACTION_MOVIE_PAUSE: | |
return "Pause"; | |
case POPPLER_ACTION_MOVIE_RESUME: | |
return "Resume"; | |
case POPPLER_ACTION_MOVIE_STOP: | |
return "Stop"; | |
} | |
return NULL; | |
} | |
static void free_tmp_file(GFile *tmp_file) | |
{ | |
g_file_delete(tmp_file, NULL, NULL); | |
g_object_unref(tmp_file); | |
} | |
static gboolean save_helper(const gchar *buf, gsize count, gpointer data, GError **error) | |
{ | |
gint fd = GPOINTER_TO_INT(data); | |
return write(fd, buf, count) == count; | |
} | |
static void pgd_action_view_play_rendition(GtkWidget *button, PopplerMedia *media) | |
{ | |
GFile *file = NULL; | |
gchar *uri; | |
if (poppler_media_is_embedded(media)) { | |
gint fd; | |
gchar *tmp_filename = NULL; | |
fd = g_file_open_tmp(NULL, &tmp_filename, NULL); | |
if (fd != -1) { | |
if (poppler_media_save_to_callback(media, save_helper, GINT_TO_POINTER(fd), NULL)) { | |
file = g_file_new_for_path(tmp_filename); | |
g_object_set_data_full(G_OBJECT(media), "tmp-file", g_object_ref(file), (GDestroyNotify)free_tmp_file); | |
} else { | |
g_free(tmp_filename); | |
} | |
close(fd); | |
} else if (tmp_filename) { | |
g_free(tmp_filename); | |
} | |
} else { | |
const gchar *filename; | |
filename = poppler_media_get_filename(media); | |
if (g_path_is_absolute(filename)) { | |
file = g_file_new_for_path(filename); | |
} else if (g_strrstr(filename, "://")) { | |
file = g_file_new_for_uri(filename); | |
} else { | |
gchar *cwd; | |
gchar *path; | |
// FIXME: relative to doc uri, not cwd | |
cwd = g_get_current_dir(); | |
path = g_build_filename(cwd, filename, NULL); | |
g_free(cwd); | |
file = g_file_new_for_path(path); | |
g_free(path); | |
} | |
} | |
if (file) { | |
uri = g_file_get_uri(file); | |
g_object_unref(file); | |
if (uri) { | |
GtkWidget *toplevel; | |
toplevel = gtk_widget_get_toplevel(button); | |
gtk_show_uri_on_window(gtk_widget_is_toplevel(toplevel) ? GTK_WINDOW(toplevel) : NULL, uri, GDK_CURRENT_TIME, NULL); | |
gtk_show_uri(gtk_widget_get_screen(button), uri, GDK_CURRENT_TIME, NULL); | |
g_free(uri); | |
} | |
} | |
} | |
static void pgd_action_view_do_action_layer(GtkWidget *button, GList *state_list) | |
{ | |
GList *l, *m; | |
for (l = state_list; l; l = g_list_next(l)) { | |
PopplerActionLayer *action_layer = (PopplerActionLayer *)l->data; | |
for (m = action_layer->layers; m; m = g_list_next(m)) { | |
PopplerLayer *layer = (PopplerLayer *)m->data; | |
switch (action_layer->action) { | |
case POPPLER_ACTION_LAYER_ON: | |
poppler_layer_show(layer); | |
break; | |
case POPPLER_ACTION_LAYER_OFF: | |
poppler_layer_hide(layer); | |
break; | |
case POPPLER_ACTION_LAYER_TOGGLE: | |
if (poppler_layer_is_visible(layer)) { | |
poppler_layer_hide(layer); | |
} else { | |
poppler_layer_show(layer); | |
} | |
break; | |
} | |
} | |
} | |
} | |
void pgd_action_view_set_action(GtkWidget *action_view, PopplerAction *action) | |
{ | |
GtkWidget *table; | |
gint row = 0; | |
table = gtk_bin_get_child(GTK_BIN(action_view)); | |
if (table) { | |
gtk_container_remove(GTK_CONTAINER(action_view), table); | |
} | |
if (!action) { | |
return; | |
} | |
table = gtk_grid_new(); | |
gtk_widget_set_margin_top(table, 5); | |
gtk_widget_set_margin_bottom(table, 5); | |
gtk_widget_set_margin_start(table, 12); | |
gtk_widget_set_margin_end(table, 5); | |
gtk_widget_set_margin_left(table, 12); | |
gtk_widget_set_margin_right(table, 5); | |
gtk_grid_set_column_spacing(GTK_GRID(table), 6); | |
gtk_grid_set_row_spacing(GTK_GRID(table), 6); | |
pgd_table_add_property(GTK_GRID(table), "<b>Title:</b>", action->any.title, &row); | |
switch (action->type) { | |
case POPPLER_ACTION_UNKNOWN: | |
pgd_table_add_property(GTK_GRID(table), "<b>Type:</b>", "Unknown", &row); | |
break; | |
case POPPLER_ACTION_NONE: | |
pgd_table_add_property(GTK_GRID(table), "<b>Type:</b>", "None", &row); | |
break; | |
case POPPLER_ACTION_GOTO_DEST: | |
pgd_action_view_add_destination(action_view, GTK_GRID(table), action->goto_dest.dest, FALSE, &row); | |
break; | |
case POPPLER_ACTION_GOTO_REMOTE: | |
pgd_table_add_property(GTK_GRID(table), "<b>Type:</b>", "Remote Destination", &row); | |
pgd_table_add_property(GTK_GRID(table), "<b>Filename:</b>", action->goto_remote.file_name, &row); | |
pgd_action_view_add_destination(action_view, GTK_GRID(table), action->goto_remote.dest, TRUE, &row); | |
break; | |
case POPPLER_ACTION_LAUNCH: | |
pgd_table_add_property(GTK_GRID(table), "<b>Type:</b>", "Launch", &row); | |
pgd_table_add_property(GTK_GRID(table), "<b>Filename:</b>", action->launch.file_name, &row); | |
pgd_table_add_property(GTK_GRID(table), "<b>Params:</b>", action->launch.params, &row); | |
break; | |
case POPPLER_ACTION_URI: | |
pgd_table_add_property(GTK_GRID(table), "<b>Type:</b>", "External URI", &row); | |
pgd_table_add_property(GTK_GRID(table), "<b>URI</b>", action->uri.uri, &row); | |
break; | |
case POPPLER_ACTION_NAMED: | |
pgd_table_add_property(GTK_GRID(table), "<b>Type:</b>", "Named Action", &row); | |
pgd_table_add_property(GTK_GRID(table), "<b>Name:</b>", action->named.named_dest, &row); | |
break; | |
case POPPLER_ACTION_MOVIE: { | |
GtkWidget *movie_view = pgd_movie_view_new(); | |
pgd_table_add_property(GTK_GRID(table), "<b>Type:</b>", "Movie", &row); | |
pgd_table_add_property(GTK_GRID(table), "<b>Operation:</b>", get_movie_op(action->movie.operation), &row); | |
pgd_movie_view_set_movie(movie_view, action->movie.movie); | |
pgd_table_add_property_with_custom_widget(GTK_GRID(table), "<b>Movie:</b>", movie_view, &row); | |
} break; | |
case POPPLER_ACTION_RENDITION: { | |
gchar *text; | |
pgd_table_add_property(GTK_GRID(table), "<b>Type:</b>", "Rendition", &row); | |
text = g_strdup_printf("%d", action->rendition.op); | |
pgd_table_add_property(GTK_GRID(table), "<b>Operation:</b>", text, &row); | |
g_free(text); | |
if (action->rendition.media) { | |
gboolean embedded = poppler_media_is_embedded(action->rendition.media); | |
GtkWidget *button; | |
pgd_table_add_property(GTK_GRID(table), "<b>Embedded:</b>", embedded ? "Yes" : "No", &row); | |
if (embedded) { | |
const gchar *mime_type = poppler_media_get_mime_type(action->rendition.media); | |
pgd_table_add_property(GTK_GRID(table), "<b>Mime type:</b>", mime_type ? mime_type : "", &row); | |
} else { | |
pgd_table_add_property(GTK_GRID(table), "<b>Filename:</b>", poppler_media_get_filename(action->rendition.media), &row); | |
} | |
button = gtk_button_new_with_mnemonic("_Play"); | |
g_signal_connect(button, "clicked", G_CALLBACK(pgd_action_view_play_rendition), action->rendition.media); | |
pgd_table_add_property_with_custom_widget(GTK_GRID(table), NULL, button, &row); | |
gtk_widget_show(button); | |
} | |
} break; | |
case POPPLER_ACTION_OCG_STATE: { | |
GList *l; | |
GtkWidget *button; | |
pgd_table_add_property(GTK_GRID(table), "<b>Type:</b>", "OCGState", &row); | |
for (l = action->ocg_state.state_list; l; l = g_list_next(l)) { | |
PopplerActionLayer *action_layer = (PopplerActionLayer *)l->data; | |
gchar *text = NULL; | |
gint n_layers = g_list_length(action_layer->layers); | |
switch (action_layer->action) { | |
case POPPLER_ACTION_LAYER_ON: | |
text = g_strdup_printf("%d layers On", n_layers); | |
break; | |
case POPPLER_ACTION_LAYER_OFF: | |
text = g_strdup_printf("%d layers Off", n_layers); | |
break; | |
case POPPLER_ACTION_LAYER_TOGGLE: | |
text = g_strdup_printf("%d layers Toggle", n_layers); | |
break; | |
} | |
pgd_table_add_property(GTK_GRID(table), "<b>Action:</b>", text, &row); | |
g_free(text); | |
} | |
button = gtk_button_new_with_label("Do action"); | |
g_signal_connect(button, "clicked", G_CALLBACK(pgd_action_view_do_action_layer), action->ocg_state.state_list); | |
pgd_table_add_property_with_custom_widget(GTK_GRID(table), NULL, button, &row); | |
gtk_widget_show(button); | |
} break; | |
case POPPLER_ACTION_JAVASCRIPT: { | |
GtkTextBuffer *buffer; | |
GtkWidget *textview; | |
GtkWidget *swindow; | |
pgd_table_add_property(GTK_GRID(table), "<b>Type:</b>", "JavaScript", &row); | |
buffer = gtk_text_buffer_new(NULL); | |
if (action->javascript.script) { | |
gtk_text_buffer_set_text(buffer, action->javascript.script, -1); | |
} | |
textview = gtk_text_view_new_with_buffer(buffer); | |
gtk_text_view_set_editable(GTK_TEXT_VIEW(textview), FALSE); | |
g_object_unref(buffer); | |
swindow = gtk_scrolled_window_new(NULL, NULL); | |
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); | |
gtk_container_add(GTK_CONTAINER(swindow), textview); | |
gtk_widget_show(textview); | |
pgd_table_add_property_with_custom_widget(GTK_GRID(table), NULL, swindow, &row); | |
gtk_widget_show(swindow); | |
} break; | |
case POPPLER_ACTION_RESET_FORM: | |
pgd_table_add_property(GTK_GRID(table), "<b>Type:</b>", "ResetForm", &row); | |
break; | |
default: | |
g_assert_not_reached(); | |
} | |
gtk_container_add(GTK_CONTAINER(action_view), table); | |
gtk_widget_show(table); | |
} | |
gchar *pgd_format_date(time_t utime) | |
{ | |
GDateTime *dt = NULL; | |
gchar *s = NULL; | |
if (utime == 0) { | |
return NULL; | |
} | |
dt = g_date_time_new_from_unix_local(utime); | |
if (dt == NULL) { | |
return NULL; | |
} | |
s = g_date_time_format(dt, "%c"); | |
g_date_time_unref(dt); | |
return s; | |
} | |
GtkWidget *pgd_movie_view_new(void) | |
{ | |
GtkWidget *frame, *label; | |
frame = gtk_frame_new(NULL); | |
gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_NONE); | |
label = gtk_label_new(NULL); | |
gtk_label_set_markup(GTK_LABEL(label), "<b>Movie Properties</b>"); | |
gtk_frame_set_label_widget(GTK_FRAME(frame), label); | |
gtk_widget_show(label); | |
return frame; | |
} | |
static void pgd_movie_view_play_movie(GtkWidget *button, PopplerMovie *movie) | |
{ | |
const gchar *filename; | |
GFile *file; | |
gchar *uri; | |
filename = poppler_movie_get_filename(movie); | |
if (g_path_is_absolute(filename)) { | |
file = g_file_new_for_path(filename); | |
} else if (g_strrstr(filename, "://")) { | |
file = g_file_new_for_uri(filename); | |
} else { | |
gchar *cwd; | |
gchar *path; | |
// FIXME: relative to doc uri, not cwd | |
cwd = g_get_current_dir(); | |
path = g_build_filename(cwd, filename, NULL); | |
g_free(cwd); | |
file = g_file_new_for_path(path); | |
g_free(path); | |
} | |
uri = g_file_get_uri(file); | |
g_object_unref(file); | |
if (uri) { | |
GtkWidget *toplevel; | |
toplevel = gtk_widget_get_toplevel(button); | |
gtk_show_uri_on_window(gtk_widget_is_toplevel(toplevel) ? GTK_WINDOW(toplevel) : NULL, uri, GDK_CURRENT_TIME, NULL); | |
gtk_show_uri(gtk_widget_get_screen(button), uri, GDK_CURRENT_TIME, NULL); | |
g_free(uri); | |
} | |
} | |
void pgd_movie_view_set_movie(GtkWidget *movie_view, PopplerMovie *movie) | |
{ | |
GtkWidget *table; | |
GtkWidget *button; | |
GEnumValue *enum_value; | |
gint width, height; | |
gint row = 0; | |
table = gtk_bin_get_child(GTK_BIN(movie_view)); | |
if (table) { | |
gtk_container_remove(GTK_CONTAINER(movie_view), table); | |
} | |
if (!movie) { | |
return; | |
} | |
table = gtk_grid_new(); | |
gtk_widget_set_margin_top(table, 5); | |
gtk_widget_set_margin_bottom(table, 5); | |
gtk_widget_set_margin_start(table, 12); | |
gtk_widget_set_margin_end(table, 5); | |
gtk_widget_set_margin_left(table, 12); | |
gtk_widget_set_margin_right(table, 5); | |
gtk_grid_set_column_spacing(GTK_GRID(table), 6); | |
gtk_grid_set_row_spacing(GTK_GRID(table), 6); | |
pgd_table_add_property(GTK_GRID(table), "<b>Filename:</b>", poppler_movie_get_filename(movie), &row); | |
pgd_table_add_property(GTK_GRID(table), "<b>Need Poster:</b>", poppler_movie_need_poster(movie) ? "Yes" : "No", &row); | |
pgd_table_add_property(GTK_GRID(table), "<b>Show Controls:</b>", poppler_movie_show_controls(movie) ? "Yes" : "No", &row); | |
enum_value = g_enum_get_value((GEnumClass *)g_type_class_ref(POPPLER_TYPE_MOVIE_PLAY_MODE), poppler_movie_get_play_mode(movie)); | |
pgd_table_add_property(GTK_GRID(table), "<b>Play Mode:</b>", enum_value->value_name, &row); | |
pgd_table_add_property(GTK_GRID(table), "<b>Synchronous Play:</b>", poppler_movie_is_synchronous(movie) ? "Yes" : "No", &row); | |
pgd_table_add_property(GTK_GRID(table), "<b>Volume:</b>", g_strdup_printf("%g", poppler_movie_get_volume(movie)), &row); | |
pgd_table_add_property(GTK_GRID(table), "<b>Rate:</b>", g_strdup_printf("%g", poppler_movie_get_rate(movie)), &row); | |
pgd_table_add_property(GTK_GRID(table), "<b>Start:</b>", g_strdup_printf("%g s", poppler_movie_get_start(movie) / 1e9), &row); | |
pgd_table_add_property(GTK_GRID(table), "<b>Duration:</b>", g_strdup_printf("%g s", poppler_movie_get_duration(movie) / 1e9), &row); | |
pgd_table_add_property(GTK_GRID(table), "<b>Rotation Angle:</b>", g_strdup_printf("%u", poppler_movie_get_rotation_angle(movie)), &row); | |
poppler_movie_get_aspect(movie, &width, &height); | |
pgd_table_add_property(GTK_GRID(table), "<b>Aspect:</b>", g_strdup_printf("%dx%d", width, height), &row); | |
button = gtk_button_new_with_mnemonic("_Play"); | |
g_signal_connect(button, "clicked", G_CALLBACK(pgd_movie_view_play_movie), movie); | |
pgd_table_add_property_with_custom_widget(GTK_GRID(table), NULL, button, &row); | |
gtk_widget_show(button); | |
gtk_container_add(GTK_CONTAINER(movie_view), table); | |
gtk_widget_show(table); | |
} | |
GdkPixbuf *pgd_pixbuf_new_for_color(PopplerColor *poppler_color) | |
{ | |
GdkPixbuf *pixbuf; | |
gint num, x; | |
guchar *pixels; | |
if (!poppler_color) { | |
return NULL; | |
} | |
pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, 64, 16); | |
pixels = gdk_pixbuf_get_pixels(pixbuf); | |
num = gdk_pixbuf_get_width(pixbuf) * gdk_pixbuf_get_height(pixbuf); | |
for (x = 0; x < num; x++) { | |
pixels[0] = poppler_color->red; | |
pixels[1] = poppler_color->green; | |
pixels[2] = poppler_color->blue; | |
pixels += 3; | |
} | |
return pixbuf; | |
} | |