2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 * See the COPYING file for license information.
18 * Guillaume Chazarain <guichaz@yahoo.fr>
21 /*****************************************
22 * The thumbnails browser in a tree view *
23 *****************************************/
25 #include <string.h> /* memset() */
28 #include "tree_browser.h"
30 #include "thumbnails.h"
31 #include "images_menus.h"
32 #include "next_image.h"
35 #include "rendering.h"
37 extern GlivImage
*current_image
;
39 static GtkTreeStore
*tree_store
;
40 static GtkTreeView
*tree_view
;
43 * Association between a directory and a GtkTreePath
44 * Used when adding filenames.
46 static GHashTable
*dir_path_hash
= NULL
;
48 /* Avoid reentrance */
49 static gint disable_tree
= 0;
52 * If a row is selected when we cannot load an image, we
53 * record the filename to load it when possible.
55 static const gchar
*next_filename
;
57 /* The tree columns (they are not all displayed) */
65 static tree_item
*make_tree_rec(GtkTreeIter
* where
, GNode
* node
)
67 static const gchar
*browser
= NULL
;
68 static gint percent
= 0, number
= 0;
69 tree_item
*item
, *first_item
;
73 /* First time for this browser */
76 set_progress(NULL
, NULL
, -1);
80 browser
= _("Browser");
86 if (G_NODE_IS_LEAF(node
)) {
88 gtk_tree_store_set(tree_store
, where
,
89 PIXBUF_COLUMN
, item
->thumb
,
90 NAME_COLUMN
, item
->name
,
91 PATH_COLUMN
, item
->path
, -1);
92 set_progress(browser
, &percent
, number
);
97 g_hash_table_insert(dir_path_hash
, item
->path
,
98 gtk_tree_model_get_path(GTK_TREE_MODEL(tree_store
),
102 for (child
= g_node_first_child(node
); child
; child
= child
->next
) {
104 gtk_tree_store_append(tree_store
, &iter
, where
);
105 item
= make_tree_rec(&iter
, child
);
106 if (first_item
== NULL
&& item
!= NULL
&& item
->thumb
!= NULL
)
111 gtk_tree_store_set(tree_store
, where
,
112 PIXBUF_COLUMN
, first_item
? first_item
->thumb
: NULL
,
113 NAME_COLUMN
, item
->path
,
114 PATH_COLUMN
, first_item
? first_item
->path
: NULL
, -1);
119 void load_later(void)
121 if (next_filename
!= NULL
&& !currently_loading() && current_image
->node
) {
122 menu_load(next_filename
);
123 if (current_image
->node
->data
== next_filename
)
124 next_filename
= NULL
;
128 static void activate_row(GtkTreeSelection
* selection
)
134 if (!gtk_tree_selection_get_selected(selection
, &model
, &iter
))
137 gtk_tree_model_get(model
, &iter
, PATH_COLUMN
, &path
, -1);
138 next_filename
= path
;
139 do_later(G_PRIORITY_DEFAULT
, load_later
);
142 static gboolean
build_tree_browser(void)
151 if (dir_path_hash
!= NULL
)
152 g_hash_table_destroy(dir_path_hash
);
154 dir_path_hash
= g_hash_table_new_full(g_str_hash
, g_str_equal
, NULL
,
155 (GDestroyNotify
) gtk_tree_path_free
);
157 if (tree_store
== NULL
)
159 tree_store
= gtk_tree_store_new(N_COLUMNS
,
160 GDK_TYPE_PIXBUF
, G_TYPE_STRING
,
163 gtk_tree_store_clear(tree_store
);
165 gtk_tree_store_append(tree_store
, &iter
, NULL
);
166 make_tree_rec(NULL
, NULL
);
167 make_tree_rec(&iter
, tree
);
169 set_progress(NULL
, NULL
, 0);
174 static void destroy_tree_view(GtkWindow
* window
)
176 gtk_widget_destroy(GTK_WIDGET(window
));
180 void show_tree_browser(void)
182 GtkCellRenderer
*name_renderer
;
183 GtkTreeViewColumn
*col
;
184 GtkTreeSelection
*selection
;
185 GtkScrolledWindow
*scroll
;
188 if (tree_view
!= NULL
)
189 /* Currently displayed */
192 if (tree_store
== NULL
&& !build_tree_browser())
196 GTK_TREE_VIEW(gtk_tree_view_new_with_model(GTK_TREE_MODEL(tree_store
)));
198 gtk_tree_view_set_enable_search(tree_view
, TRUE
);
201 gtk_tree_view_column_new_with_attributes(_("Thumb"),
202 gtk_cell_renderer_pixbuf_new(),
203 "pixbuf", PIXBUF_COLUMN
, NULL
);
204 gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view
), col
);
206 name_renderer
= gtk_cell_renderer_text_new();
207 g_object_set(name_renderer
,
208 "ellipsize-set", TRUE
,
209 "ellipsize", PANGO_ELLIPSIZE_START
, NULL
);
211 gtk_tree_view_column_new_with_attributes(_("Name"), name_renderer
,
212 "text", NAME_COLUMN
, NULL
);
213 gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view
), col
);
214 gtk_widget_show_all(GTK_WIDGET(tree_view
));
216 scroll
= GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL
, NULL
));
217 gtk_scrolled_window_set_policy(scroll
,
218 GTK_POLICY_NEVER
, GTK_POLICY_AUTOMATIC
);
219 gtk_container_add(GTK_CONTAINER(scroll
), GTK_WIDGET(tree_view
));
220 gtk_widget_show_all(GTK_WIDGET(scroll
));
222 window
= new_window(_("Thumbnails browser"));
223 gtk_container_add(GTK_CONTAINER(window
), GTK_WIDGET(scroll
));
224 gtk_window_set_default_size(window
, 300, 600);
225 gtk_widget_show_all(GTK_WIDGET(window
));
227 selection
= gtk_tree_view_get_selection(tree_view
);
228 g_signal_connect(selection
, "changed", G_CALLBACK(activate_row
), NULL
);
230 g_signal_connect(window
, "delete-event", G_CALLBACK(destroy_tree_view
),
233 highlight_current_image();
236 void highlight_current_image(void)
239 GtkTreePath
*tree_path
;
240 GtkTreeIter iter
, child
;
242 if (tree_view
== NULL
|| !GTK_WIDGET_VISIBLE(tree_view
) ||
243 current_image
->node
== NULL
)
247 do_later(G_PRIORITY_DEFAULT
, load_later
);
251 path
= g_strdup(current_image
->node
->data
);
253 gchar
*new_path
= g_path_get_dirname(path
);
258 tree_path
= g_hash_table_lookup(dir_path_hash
, path
);
259 } while (!tree_path
&& !g_str_equal(path
, "/") && !g_str_equal(path
, "."));
263 if (tree_path
== NULL
)
266 if (!gtk_tree_model_get_iter(GTK_TREE_MODEL(tree_store
), &iter
, tree_path
))
269 if (!gtk_tree_model_iter_children
270 (GTK_TREE_MODEL(tree_store
), &child
, &iter
))
274 GValue tree_filename
;
275 memset(&tree_filename
, 0, sizeof(tree_filename
));
277 gtk_tree_model_get_value(GTK_TREE_MODEL(tree_store
), &child
,
278 PATH_COLUMN
, &tree_filename
);
280 if (g_value_peek_pointer(&tree_filename
) == current_image
->node
->data
) {
282 gtk_tree_model_get_path(GTK_TREE_MODEL(tree_store
), &child
);
285 gtk_tree_view_expand_to_path(tree_view
, tree_path
);
286 gtk_tree_view_expand_row(tree_view
, tree_path
, FALSE
);
287 gtk_tree_view_scroll_to_cell(tree_view
, tree_path
,
288 NULL
, FALSE
, 0.0, 0.0);
289 gtk_tree_view_set_cursor(tree_view
, tree_path
, NULL
, FALSE
);
292 gtk_tree_path_free(tree_path
);
296 g_value_unset(&tree_filename
);
297 } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(tree_store
), &child
));
300 void cond_rebuild_tree_browser(void)
302 if (dir_path_hash
!= NULL
)
303 build_tree_browser();