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