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
21 #include "outline.h"
22 #include "utils.h"
23
24 enum
25 {
26 OUTLINE_TITLE_COLUMN,
27 OUTLINE_ACTION_TYPE_COLUMN,
28 OUTLINE_EXPAND_COLUMN,
29 OUTLINE_ACTION_COLUMN,
30 N_COLUMNS
31 };
32
build_tree(PopplerDocument * document,GtkTreeModel * model,GtkTreeIter * parent,PopplerIndexIter * iter)33 static void build_tree(PopplerDocument *document, GtkTreeModel *model, GtkTreeIter *parent, PopplerIndexIter *iter)
34 {
35
36 do {
37 GtkTreeIter tree_iter;
38 PopplerIndexIter *child;
39 PopplerAction *action;
40 gboolean expand;
41 gchar *markup;
42 GEnumValue *enum_value;
43
44 action = poppler_index_iter_get_action(iter);
45 expand = poppler_index_iter_is_open(iter);
46
47 if (!action)
48 continue;
49
50 markup = g_markup_escape_text(action->any.title, -1);
51 enum_value = g_enum_get_value((GEnumClass *)g_type_class_ref(POPPLER_TYPE_ACTION_TYPE), action->type);
52
53 if (action->type == POPPLER_ACTION_GOTO_DEST && action->goto_dest.dest->type == POPPLER_DEST_NAMED) {
54 /* TODO */
55 }
56
57 gtk_tree_store_append(GTK_TREE_STORE(model), &tree_iter, parent);
58 gtk_tree_store_set(GTK_TREE_STORE(model), &tree_iter, OUTLINE_TITLE_COLUMN, markup, OUTLINE_ACTION_TYPE_COLUMN, enum_value->value_name, OUTLINE_EXPAND_COLUMN, expand, OUTLINE_ACTION_COLUMN, action, -1);
59 g_object_weak_ref(G_OBJECT(model), (GWeakNotify)poppler_action_free, action);
60
61 g_free(markup);
62
63 child = poppler_index_iter_get_child(iter);
64 if (child)
65 build_tree(document, model, &tree_iter, child);
66 poppler_index_iter_free(child);
67 } while (poppler_index_iter_next(iter));
68 }
69
pgd_outline_create_model(PopplerDocument * document)70 GtkTreeModel *pgd_outline_create_model(PopplerDocument *document)
71 {
72 GtkTreeModel *model;
73 PopplerIndexIter *iter;
74
75 iter = poppler_index_iter_new(document);
76 if (iter) {
77 model = GTK_TREE_MODEL(gtk_tree_store_new(N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_POINTER));
78 build_tree(document, model, NULL, iter);
79 poppler_index_iter_free(iter);
80 } else {
81 GtkTreeIter tree_iter;
82 gchar *markup;
83
84 model = GTK_TREE_MODEL(gtk_list_store_new(1, G_TYPE_STRING));
85 gtk_list_store_append(GTK_LIST_STORE(model), &tree_iter);
86 markup = g_strdup_printf("<span size=\"larger\" style=\"italic\">%s</span>", "The document doesn't contain outline");
87 gtk_list_store_set(GTK_LIST_STORE(model), &tree_iter, 0, markup, -1);
88 g_free(markup);
89 }
90
91 return model;
92 }
93
expand_open_links(GtkTreeView * tree_view,GtkTreeModel * model,GtkTreeIter * parent)94 static void expand_open_links(GtkTreeView *tree_view, GtkTreeModel *model, GtkTreeIter *parent)
95 {
96 GtkTreeIter iter;
97 gboolean expand;
98
99 if (gtk_tree_model_iter_children(model, &iter, parent)) {
100 do {
101 gtk_tree_model_get(model, &iter, OUTLINE_EXPAND_COLUMN, &expand, -1);
102 if (expand) {
103 GtkTreePath *path;
104
105 path = gtk_tree_model_get_path(model, &iter);
106 gtk_tree_view_expand_row(tree_view, path, FALSE);
107 gtk_tree_path_free(path);
108 }
109
110 expand_open_links(tree_view, model, &iter);
111 } while (gtk_tree_model_iter_next(model, &iter));
112 }
113 }
114
pgd_outline_selection_changed(GtkTreeSelection * treeselection,GtkWidget * action_view)115 static void pgd_outline_selection_changed(GtkTreeSelection *treeselection, GtkWidget *action_view)
116 {
117 GtkTreeModel *model;
118 GtkTreeIter iter;
119
120 if (gtk_tree_selection_get_selected(treeselection, &model, &iter)) {
121 PopplerAction *action;
122
123 gtk_tree_model_get(model, &iter, OUTLINE_ACTION_COLUMN, &action, -1);
124 pgd_action_view_set_action(action_view, action);
125 }
126 }
127
pgd_outline_create_widget(PopplerDocument * document)128 GtkWidget *pgd_outline_create_widget(PopplerDocument *document)
129 {
130 GtkWidget *swindow;
131 GtkWidget *treeview;
132 GtkTreeModel *model;
133 GtkCellRenderer *renderer;
134 GtkTreeSelection *selection;
135 GtkWidget *hpaned, *action;
136
137 hpaned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
138
139 action = pgd_action_view_new(document);
140
141 swindow = gtk_scrolled_window_new(NULL, NULL);
142 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
143
144 model = pgd_outline_create_model(document);
145 treeview = gtk_tree_view_new_with_model(model);
146 g_object_unref(model);
147
148 renderer = gtk_cell_renderer_text_new();
149 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(treeview), 0, "Title", renderer, "markup", OUTLINE_TITLE_COLUMN, NULL);
150 g_object_set(G_OBJECT(renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
151 g_object_set(G_OBJECT(gtk_tree_view_get_column(GTK_TREE_VIEW(treeview), 0)), "expand", TRUE, NULL);
152
153 if (GTK_IS_TREE_STORE(model)) {
154 renderer = gtk_cell_renderer_text_new();
155 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(treeview), 1, "Action Type", renderer, "text", OUTLINE_ACTION_TYPE_COLUMN, NULL);
156
157 expand_open_links(GTK_TREE_VIEW(treeview), model, NULL);
158
159 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
160 g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(pgd_outline_selection_changed), (gpointer)action);
161 } else {
162 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)), GTK_SELECTION_NONE);
163 }
164
165 gtk_container_add(GTK_CONTAINER(swindow), treeview);
166 gtk_widget_show(treeview);
167
168 gtk_paned_add1(GTK_PANED(hpaned), swindow);
169 gtk_widget_show(swindow);
170
171 gtk_paned_add2(GTK_PANED(hpaned), action);
172 gtk_widget_show(action);
173
174 gtk_paned_set_position(GTK_PANED(hpaned), 300);
175
176 return hpaned;
177 }
178