1 /*
2 * Copyright (C) 2013 Igalia S.L.
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 <string.h>
20
21 #include "text.h"
22 #include "utils.h"
23
24 typedef struct
25 {
26 GtkWidget *view;
27 GtkTreeStore *store;
28 GtkWidget *type_value;
29 GtkWidget *lang_value;
30 GtkWidget *abbr_value;
31 GtkWidget *id_value;
32 GtkWidget *title_value;
33 GtkTextBuffer *text_buffer;
34 } PgdTaggedStructDemo;
35
pgd_taggedstruct_free(PgdTaggedStructDemo * demo)36 static void pgd_taggedstruct_free(PgdTaggedStructDemo *demo)
37 {
38 if (!demo)
39 return;
40
41 if (demo->store) {
42 g_object_unref(demo->store);
43 demo->store = NULL;
44 }
45
46 g_free(demo);
47 }
48
populate_store_aux(GtkTreeStore * store,GtkTreeIter * parent,PopplerStructureElementIter * iter)49 static void populate_store_aux(GtkTreeStore *store, GtkTreeIter *parent, PopplerStructureElementIter *iter)
50 {
51 do {
52 PopplerStructureElementIter *child = poppler_structure_element_iter_get_child(iter);
53 PopplerStructureElement *element = poppler_structure_element_iter_get_element(iter);
54 GEnumClass *enum_class = G_ENUM_CLASS(g_type_class_ref(POPPLER_TYPE_STRUCTURE_ELEMENT_KIND));
55 GEnumValue *enum_value = g_enum_get_value(enum_class, poppler_structure_element_get_kind(element));
56 GtkTreeIter pos;
57
58 gtk_tree_store_append(store, &pos, parent);
59 gtk_tree_store_set(store, &pos, 0, enum_value->value_nick, 1, element, -1);
60
61 if (child) {
62 populate_store_aux(store, &pos, child);
63 poppler_structure_element_iter_free(child);
64 }
65 } while (poppler_structure_element_iter_next(iter));
66 }
67
populate_store(PopplerStructureElementIter * iter)68 static GtkTreeStore *populate_store(PopplerStructureElementIter *iter)
69 {
70 GtkTreeStore *store = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_POINTER);
71
72 if (iter) {
73 populate_store_aux(store, NULL, iter);
74 } else {
75 GtkTreeIter pos;
76
77 gtk_tree_store_append(store, &pos, NULL);
78 gtk_tree_store_set(store, &pos, 0, "<b>Not a Tagged-PDF</b>", 1, NULL, -1);
79 }
80
81 return store;
82 }
83
84 /*static void
85 pgd_row_activated (GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, PgdTaggedStructDemo *demo)
86 {*/
pgd_selection_changed(GtkTreeSelection * selection,PgdTaggedStructDemo * demo)87 static void pgd_selection_changed(GtkTreeSelection *selection, PgdTaggedStructDemo *demo)
88 {
89 GtkTreeModel *model;
90 PopplerStructureElement *element;
91 GtkTreeIter iter;
92 gpointer elementptr;
93
94 if (!gtk_tree_selection_get_selected(selection, &model, &iter))
95 return;
96
97 gtk_tree_model_get(model, &iter, 1, &elementptr, -1);
98 element = POPPLER_STRUCTURE_ELEMENT(elementptr);
99
100 gtk_label_set_text(GTK_LABEL(demo->id_value), poppler_structure_element_get_id(element));
101 gtk_label_set_text(GTK_LABEL(demo->title_value), poppler_structure_element_get_title(element));
102 gtk_label_set_text(GTK_LABEL(demo->lang_value), poppler_structure_element_get_language(element));
103 gtk_label_set_text(GTK_LABEL(demo->abbr_value), poppler_structure_element_get_abbreviation(element));
104 gtk_text_buffer_set_text(demo->text_buffer, "", -1);
105
106 if (poppler_structure_element_is_content(element)) {
107 const gchar *text = poppler_structure_element_get_text(element, FALSE);
108
109 if (text)
110 gtk_text_buffer_set_text(demo->text_buffer, text, -1);
111 gtk_label_set_text(GTK_LABEL(demo->type_value), "Content");
112 } else {
113 if (poppler_structure_element_is_inline(element))
114 gtk_label_set_text(GTK_LABEL(demo->type_value), "Inline");
115 else if (poppler_structure_element_is_block(element))
116 gtk_label_set_text(GTK_LABEL(demo->type_value), "Block");
117 else
118 gtk_label_set_text(GTK_LABEL(demo->type_value), "Structure");
119 }
120 }
121
pgd_taggedstruct_create_widget(PopplerDocument * document)122 GtkWidget *pgd_taggedstruct_create_widget(PopplerDocument *document)
123 {
124 PopplerStructureElementIter *iter;
125 PgdTaggedStructDemo *demo;
126 GtkCellRenderer *renderer;
127 GtkTreeSelection *selection;
128 GtkWidget *hbox;
129 GtkWidget *vbox;
130 GtkWidget *grid;
131 GtkWidget *scroll;
132 GtkWidget *w;
133 gint row;
134
135 demo = g_new0(PgdTaggedStructDemo, 1);
136
137 iter = poppler_structure_element_iter_new(document);
138 demo->store = populate_store(iter);
139 poppler_structure_element_iter_free(iter);
140
141 demo->view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(demo->store));
142
143 renderer = gtk_cell_renderer_text_new();
144 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(demo->view), 0, "Type", renderer, "markup", 0, NULL);
145 g_object_set(G_OBJECT(gtk_tree_view_get_column(GTK_TREE_VIEW(demo->view), 0)), "expand", TRUE, NULL);
146
147 gtk_tree_view_expand_all(GTK_TREE_VIEW(demo->view));
148 gtk_tree_view_set_show_expanders(GTK_TREE_VIEW(demo->view), TRUE);
149 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(demo->view), TRUE);
150 gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(demo->view), FALSE);
151 gtk_tree_view_set_activate_on_single_click(GTK_TREE_VIEW(demo->view), TRUE);
152
153 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
154 scroll = gtk_scrolled_window_new(NULL, NULL);
155 gtk_container_add(GTK_CONTAINER(scroll), demo->view);
156 gtk_widget_show(demo->view);
157 gtk_box_pack_start(GTK_BOX(hbox), scroll, TRUE, TRUE, 0);
158 gtk_widget_show(scroll);
159
160 row = 0;
161 grid = gtk_grid_new();
162 gtk_container_set_border_width(GTK_CONTAINER(grid), 12);
163 gtk_grid_set_row_homogeneous(GTK_GRID(grid), FALSE);
164 gtk_grid_set_column_spacing(GTK_GRID(grid), 6);
165 gtk_grid_set_row_spacing(GTK_GRID(grid), 6);
166 pgd_table_add_property_with_value_widget(GTK_GRID(grid), "<b>Type:</b>", &demo->type_value, NULL, &row);
167 pgd_table_add_property_with_value_widget(GTK_GRID(grid), "<b>ID:</b>", &demo->id_value, NULL, &row);
168 pgd_table_add_property_with_value_widget(GTK_GRID(grid), "<b>Title:</b>", &demo->title_value, NULL, &row);
169 pgd_table_add_property_with_value_widget(GTK_GRID(grid), "<b>Language:</b>", &demo->lang_value, NULL, &row);
170 pgd_table_add_property_with_value_widget(GTK_GRID(grid), "<b>Abbreviation:</b>", &demo->abbr_value, NULL, &row);
171
172 vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
173 gtk_box_pack_start(GTK_BOX(vbox), grid, FALSE, FALSE, 0);
174 gtk_widget_show(grid);
175
176 scroll = gtk_scrolled_window_new(NULL, NULL);
177 gtk_container_set_border_width(GTK_CONTAINER(scroll), 12);
178 gtk_box_pack_end(GTK_BOX(vbox), scroll, TRUE, TRUE, 0);
179 gtk_widget_show(scroll);
180
181 gtk_container_add(GTK_CONTAINER(scroll), (w = gtk_text_view_new()));
182 gtk_widget_show(w);
183
184 demo->text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(w));
185 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(w), GTK_WRAP_WORD_CHAR);
186 gtk_text_view_set_editable(GTK_TEXT_VIEW(w), FALSE);
187 gtk_text_buffer_set_text(demo->text_buffer, "", -1);
188 gtk_widget_show(w);
189
190 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(demo->view));
191 g_signal_connect(selection, "changed", G_CALLBACK(pgd_selection_changed), demo);
192
193 gtk_box_pack_end(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
194 gtk_widget_show(vbox);
195
196 g_object_weak_ref(G_OBJECT(hbox), (GWeakNotify)pgd_taggedstruct_free, demo);
197
198 gtk_widget_show(hbox);
199 return hbox;
200 }
201