Mercurial > geeqie
annotate src/view_dir_tree.c @ 384:392dd6541d51
Merge parts of view_dir_list/tree constructors/destructors to
view_dir.
author | zas_ |
---|---|
date | Wed, 16 Apr 2008 16:54:38 +0000 |
parents | 499d7ba62261 |
children | 5186f8e38cb8 |
rev | line source |
---|---|
9 | 1 /* |
196 | 2 * Geeqie |
112
b15d4c18168f
Fri Nov 17 19:06:19 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
3 * (C) 2006 John Ellis |
9 | 4 * |
5 * Author: John Ellis | |
6 * | |
7 * This software is released under the GNU General Public License (GNU GPL). | |
8 * Please read the included file COPYING for more information. | |
9 * This software comes with no warranty of any kind, use at your own risk! | |
10 */ | |
11 | |
281 | 12 #include "main.h" |
9 | 13 #include "view_dir_tree.h" |
14 | |
15 | |
16 #include "dnd.h" | |
17 #include "dupe.h" | |
18 #include "filelist.h" | |
19 #include "layout.h" | |
20 #include "layout_image.h" | |
21 #include "layout_util.h" | |
22 #include "utilops.h" | |
23 #include "ui_bookmark.h" | |
24 #include "ui_fileops.h" | |
25 #include "ui_menu.h" | |
26 #include "ui_tree_edit.h" | |
380
5afe77bb563a
Introduce a new struct ViewDir to handle directory views common
zas_
parents:
356
diff
changeset
|
27 #include "view_dir.h" |
9 | 28 |
29 #include <gdk/gdkkeysyms.h> /* for keyboard values */ | |
30 | |
31 | |
32 #define VDTREE_INDENT 14 | |
33 #define VDTREE_PAD 4 | |
34 | |
380
5afe77bb563a
Introduce a new struct ViewDir to handle directory views common
zas_
parents:
356
diff
changeset
|
35 #define VDTREE_INFO(_vd_, _part_) (((ViewDirInfoTree *)(_vd_->info))->_part_) |
9 | 36 |
37 | |
38 typedef struct _PathData PathData; | |
39 struct _PathData | |
40 { | |
41 gchar *name; | |
42 FileData *node; | |
43 }; | |
44 | |
45 typedef struct _NodeData NodeData; | |
46 struct _NodeData | |
47 { | |
48 FileData *fd; | |
49 gint expanded; | |
50 time_t last_update; | |
51 }; | |
52 | |
53 | |
382 | 54 static gint vdtree_populate_path_by_iter(ViewDir *vd, GtkTreeIter *iter, gint force, const gchar *target_path); |
55 static FileData *vdtree_populate_path(ViewDir *vd, const gchar *path, gint expand, gint force); | |
9 | 56 |
57 | |
58 /* | |
59 *---------------------------------------------------------------------------- | |
60 * utils | |
61 *---------------------------------------------------------------------------- | |
62 */ | |
63 | |
64 static void set_cursor(GtkWidget *widget, GdkCursorType cursor_type) | |
65 { | |
66 GdkCursor *cursor = NULL; | |
67 | |
68 if (!widget || !widget->window) return; | |
69 | |
70 if (cursor_type > -1) cursor = gdk_cursor_new (cursor_type); | |
71 gdk_window_set_cursor (widget->window, cursor); | |
72 if (cursor) gdk_cursor_unref(cursor); | |
73 gdk_flush(); | |
74 } | |
75 | |
382 | 76 static void vdtree_busy_push(ViewDir *vd) |
9 | 77 { |
382 | 78 if (VDTREE_INFO(vd, busy_ref) == 0) set_cursor(vd->view, GDK_WATCH); |
79 VDTREE_INFO(vd, busy_ref)++; | |
9 | 80 } |
81 | |
382 | 82 static void vdtree_busy_pop(ViewDir *vd) |
9 | 83 { |
382 | 84 if (VDTREE_INFO(vd, busy_ref) == 1) set_cursor(vd->view, -1); |
85 if (VDTREE_INFO(vd, busy_ref) > 0) VDTREE_INFO(vd, busy_ref)--; | |
9 | 86 } |
87 | |
383
499d7ba62261
Move some dnd common code from view_dir_list.c and view_dir_tree.c
zas_
parents:
382
diff
changeset
|
88 gint vdtree_find_row(ViewDir *vd, FileData *fd, GtkTreeIter *iter, GtkTreeIter *parent) |
9 | 89 { |
90 GtkTreeModel *store; | |
91 gint valid; | |
92 | |
382 | 93 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vd->view)); |
9 | 94 if (parent) |
95 { | |
96 valid = gtk_tree_model_iter_children(store, iter, parent); | |
97 } | |
98 else | |
99 { | |
100 valid = gtk_tree_model_get_iter_first(store, iter); | |
101 } | |
102 while (valid) | |
103 { | |
104 NodeData *nd; | |
105 GtkTreeIter found; | |
106 | |
107 gtk_tree_model_get(GTK_TREE_MODEL(store), iter, DIR_COLUMN_POINTER, &nd, -1); | |
108 if (nd->fd == fd) return TRUE; | |
109 | |
382 | 110 if (vdtree_find_row(vd, fd, &found, iter)) |
9 | 111 { |
112 memcpy(iter, &found, sizeof(found)); | |
113 return TRUE; | |
114 } | |
115 | |
116 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), iter); | |
117 } | |
118 | |
119 return FALSE; | |
120 } | |
121 | |
382 | 122 static void vdtree_icon_set_by_iter(ViewDir *vd, GtkTreeIter *iter, GdkPixbuf *pixbuf) |
9 | 123 { |
124 GtkTreeModel *store; | |
125 GdkPixbuf *old; | |
126 | |
382 | 127 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vd->view)); |
9 | 128 gtk_tree_model_get(store, iter, DIR_COLUMN_ICON, &old, -1); |
382 | 129 if (old != vd->pf->deny) |
9 | 130 { |
131 gtk_tree_store_set(GTK_TREE_STORE(store), iter, DIR_COLUMN_ICON, pixbuf, -1); | |
132 } | |
133 } | |
134 | |
382 | 135 static void vdtree_expand_by_iter(ViewDir *vd, GtkTreeIter *iter, gint expand) |
9 | 136 { |
137 GtkTreeModel *store; | |
138 GtkTreePath *tpath; | |
139 | |
382 | 140 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vd->view)); |
9 | 141 tpath = gtk_tree_model_get_path(store, iter); |
142 if (expand) | |
143 { | |
382 | 144 gtk_tree_view_expand_row(GTK_TREE_VIEW(vd->view), tpath, FALSE); |
145 vdtree_icon_set_by_iter(vd, iter, vd->pf->open); | |
9 | 146 } |
147 else | |
148 { | |
382 | 149 gtk_tree_view_collapse_row(GTK_TREE_VIEW(vd->view), tpath); |
9 | 150 } |
151 gtk_tree_path_free(tpath); | |
152 } | |
153 | |
382 | 154 static void vdtree_expand_by_data(ViewDir *vd, FileData *fd, gint expand) |
9 | 155 { |
156 GtkTreeIter iter; | |
157 | |
382 | 158 if (vdtree_find_row(vd, fd, &iter, NULL)) |
9 | 159 { |
382 | 160 vdtree_expand_by_iter(vd, &iter, expand); |
9 | 161 } |
162 } | |
163 | |
164 static gint vdtree_rename_row_cb(TreeEditData *td, const gchar *old, const gchar *new, gpointer data) | |
165 { | |
382 | 166 ViewDir *vd = data; |
9 | 167 GtkTreeModel *store; |
168 GtkTreeIter iter; | |
169 NodeData *nd; | |
170 gchar *old_path; | |
171 gchar *new_path; | |
172 gchar *base; | |
173 | |
382 | 174 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vd->view)); |
9 | 175 if (!gtk_tree_model_get_iter(store, &iter, td->path)) return FALSE; |
176 gtk_tree_model_get(store, &iter, DIR_COLUMN_POINTER, &nd, -1); | |
177 if (!nd) return FALSE; | |
178 | |
179 old_path = g_strdup(nd->fd->path); | |
180 | |
181 base = remove_level_from_path(old_path); | |
182 new_path = concat_dir_and_file(base, new); | |
183 g_free(base); | |
184 | |
382 | 185 if (file_util_rename_dir(nd->fd, new_path, vd->view)) |
9 | 186 { |
382 | 187 vdtree_populate_path(vd, new_path, TRUE, TRUE); |
9 | 188 |
382 | 189 if (vd->layout && strcmp(vd->path, old_path) == 0) |
9 | 190 { |
382 | 191 layout_set_path(vd->layout, new_path); |
9 | 192 } |
193 } | |
194 | |
195 g_free(old_path); | |
196 g_free(new_path); | |
197 | |
198 return FALSE; | |
199 } | |
200 | |
382 | 201 static void vdtree_rename_by_data(ViewDir *vd, FileData *fd) |
9 | 202 { |
203 GtkTreeModel *store; | |
204 GtkTreePath *tpath; | |
205 GtkTreeIter iter; | |
206 | |
207 if (!fd || | |
382 | 208 !vdtree_find_row(vd, fd, &iter, NULL)) return; |
9 | 209 |
382 | 210 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vd->view)); |
9 | 211 tpath = gtk_tree_model_get_path(store, &iter); |
212 | |
382 | 213 tree_edit_by_path(GTK_TREE_VIEW(vd->view), tpath, 0, fd->name, |
214 vdtree_rename_row_cb, vd); | |
9 | 215 gtk_tree_path_free(tpath); |
216 } | |
217 | |
218 static void vdtree_node_free(NodeData *nd) | |
219 { | |
220 if (!nd) return; | |
221 | |
138 | 222 file_data_unref(nd->fd); |
9 | 223 g_free(nd); |
224 } | |
225 | |
226 /* | |
227 *----------------------------------------------------------------------------- | |
228 * pop-up menu | |
229 *----------------------------------------------------------------------------- | |
230 */ | |
231 | |
232 static void vdtree_pop_menu_up_cb(GtkWidget *widget, gpointer data) | |
233 { | |
382 | 234 ViewDir *vd = data; |
9 | 235 gchar *path; |
236 | |
382 | 237 if (!vd->path || strcmp(vd->path, "/") == 0) return; |
238 path = remove_level_from_path(vd->path); | |
9 | 239 |
382 | 240 if (vd->select_func) |
9 | 241 { |
382 | 242 vd->select_func(vd, path, vd->select_data); |
9 | 243 } |
244 | |
245 g_free(path); | |
246 } | |
247 | |
248 static void vdtree_pop_menu_slide_cb(GtkWidget *widget, gpointer data) | |
249 { | |
382 | 250 ViewDir *vd = data; |
9 | 251 gchar *path; |
252 | |
382 | 253 if (!vd->layout) return; |
9 | 254 |
382 | 255 if (!vd->click_fd) return; |
256 path = vd->click_fd->path; | |
9 | 257 |
382 | 258 layout_set_path(vd->layout, path); |
259 layout_select_none(vd->layout); | |
260 layout_image_slideshow_stop(vd->layout); | |
261 layout_image_slideshow_start(vd->layout); | |
9 | 262 } |
263 | |
264 static void vdtree_pop_menu_slide_rec_cb(GtkWidget *widget, gpointer data) | |
265 { | |
382 | 266 ViewDir *vd = data; |
9 | 267 gchar *path; |
268 GList *list; | |
269 | |
382 | 270 if (!vd->layout) return; |
9 | 271 |
382 | 272 if (!vd->click_fd) return; |
273 path = vd->click_fd->path; | |
9 | 274 |
138 | 275 list = filelist_recursive(path); |
9 | 276 |
382 | 277 layout_image_slideshow_stop(vd->layout); |
278 layout_image_slideshow_start_from_list(vd->layout, list); | |
9 | 279 } |
280 | |
382 | 281 static void vdtree_pop_menu_dupe(ViewDir *vd, gint recursive) |
9 | 282 { |
283 DupeWindow *dw; | |
284 GList *list = NULL; | |
285 | |
382 | 286 if (!vd->click_fd) return; |
9 | 287 |
288 if (recursive) | |
289 { | |
382 | 290 list = g_list_append(list, file_data_ref(vd->click_fd)); |
9 | 291 } |
292 else | |
293 { | |
382 | 294 filelist_read(vd->click_fd->path, &list, NULL); |
138 | 295 list = filelist_filter(list, FALSE); |
9 | 296 } |
297 | |
298 dw = dupe_window_new(DUPE_MATCH_NAME); | |
299 dupe_window_add_files(dw, list, recursive); | |
300 | |
138 | 301 filelist_free(list); |
9 | 302 } |
303 | |
304 static void vdtree_pop_menu_dupe_cb(GtkWidget *widget, gpointer data) | |
305 { | |
382 | 306 ViewDir *vd = data; |
307 vdtree_pop_menu_dupe(vd, FALSE); | |
9 | 308 } |
309 | |
310 static void vdtree_pop_menu_dupe_rec_cb(GtkWidget *widget, gpointer data) | |
311 { | |
382 | 312 ViewDir *vd = data; |
313 vdtree_pop_menu_dupe(vd, TRUE); | |
9 | 314 } |
315 | |
316 static void vdtree_pop_menu_new_cb(GtkWidget *widget, gpointer data) | |
317 { | |
382 | 318 ViewDir *vd = data; |
9 | 319 const gchar *path; |
320 gchar *new_path; | |
321 gchar *buf; | |
322 | |
382 | 323 if (!vd->click_fd) return; |
324 path = vd->click_fd->path; | |
9 | 325 |
326 buf = concat_dir_and_file(path, _("new_folder")); | |
327 new_path = unique_filename(buf, NULL, NULL, FALSE); | |
328 g_free(buf); | |
329 if (!new_path) return; | |
330 | |
331 if (!mkdir_utf8(new_path, 0755)) | |
332 { | |
333 gchar *text; | |
334 | |
335 text = g_strdup_printf(_("Unable to create folder:\n%s"), new_path); | |
382 | 336 file_util_warning_dialog(_("Error creating folder"), text, GTK_STOCK_DIALOG_ERROR, vd->view); |
9 | 337 g_free(text); |
338 } | |
339 else | |
340 { | |
341 FileData *fd; | |
342 | |
382 | 343 fd = vdtree_populate_path(vd, new_path, TRUE, TRUE); |
9 | 344 |
382 | 345 vdtree_rename_by_data(vd, fd); |
9 | 346 } |
347 | |
348 g_free(new_path); | |
349 } | |
350 | |
351 static void vdtree_pop_menu_rename_cb(GtkWidget *widget, gpointer data) | |
352 { | |
382 | 353 ViewDir *vd = data; |
9 | 354 |
382 | 355 vdtree_rename_by_data(vd, vd->click_fd); |
9 | 356 } |
357 | |
112
b15d4c18168f
Fri Nov 17 19:06:19 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
358 static void vdtree_pop_menu_delete_cb(GtkWidget *widget, gpointer data) |
b15d4c18168f
Fri Nov 17 19:06:19 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
359 { |
382 | 360 ViewDir *vd = data; |
112
b15d4c18168f
Fri Nov 17 19:06:19 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
361 |
382 | 362 if (!vd->click_fd) return; |
363 file_util_delete_dir(vd->click_fd, vd->widget); | |
112
b15d4c18168f
Fri Nov 17 19:06:19 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
364 } |
b15d4c18168f
Fri Nov 17 19:06:19 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
365 |
380
5afe77bb563a
Introduce a new struct ViewDir to handle directory views common
zas_
parents:
356
diff
changeset
|
366 static void vdtree_pop_menu_dir_view_as_cb(GtkWidget *widget, gpointer data) |
9 | 367 { |
382 | 368 ViewDir *vd = data; |
9 | 369 |
382 | 370 if (vd->layout) layout_views_set(vd->layout, DIRVIEW_LIST, vd->layout->icon_view); |
9 | 371 } |
372 | |
373 static void vdtree_pop_menu_refresh_cb(GtkWidget *widget, gpointer data) | |
374 { | |
382 | 375 ViewDir *vd = data; |
9 | 376 |
382 | 377 if (vd->layout) layout_refresh(vd->layout); |
9 | 378 } |
379 | |
356 | 380 static void vdtree_toggle_show_hidden_files_cb(GtkWidget *widget, gpointer data) |
355
0b82646e977f
Let toggle the visibility of hidden files from directories list
zas_
parents:
332
diff
changeset
|
381 { |
382 | 382 ViewDir *vd = data; |
355
0b82646e977f
Let toggle the visibility of hidden files from directories list
zas_
parents:
332
diff
changeset
|
383 |
356 | 384 options->file_filter.show_hidden_files = !options->file_filter.show_hidden_files; |
382 | 385 if (vd->layout) layout_refresh(vd->layout); |
355
0b82646e977f
Let toggle the visibility of hidden files from directories list
zas_
parents:
332
diff
changeset
|
386 } |
0b82646e977f
Let toggle the visibility of hidden files from directories list
zas_
parents:
332
diff
changeset
|
387 |
382 | 388 static GtkWidget *vdtree_pop_menu(ViewDir *vd, FileData *fd) |
9 | 389 { |
390 GtkWidget *menu; | |
391 gint active; | |
112
b15d4c18168f
Fri Nov 17 19:06:19 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
392 gint parent_active = FALSE; |
9 | 393 |
394 active = (fd != NULL); | |
112
b15d4c18168f
Fri Nov 17 19:06:19 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
395 if (fd) |
b15d4c18168f
Fri Nov 17 19:06:19 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
396 { |
b15d4c18168f
Fri Nov 17 19:06:19 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
397 gchar *parent; |
b15d4c18168f
Fri Nov 17 19:06:19 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
398 |
b15d4c18168f
Fri Nov 17 19:06:19 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
399 parent = remove_level_from_path(fd->path); |
b15d4c18168f
Fri Nov 17 19:06:19 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
400 parent_active = access_file(parent, W_OK | X_OK); |
b15d4c18168f
Fri Nov 17 19:06:19 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
401 g_free(parent); |
b15d4c18168f
Fri Nov 17 19:06:19 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
402 } |
9 | 403 |
404 menu = popup_menu_short_lived(); | |
405 g_signal_connect(G_OBJECT(menu), "destroy", | |
383
499d7ba62261
Move some dnd common code from view_dir_list.c and view_dir_tree.c
zas_
parents:
382
diff
changeset
|
406 G_CALLBACK(vd_popup_destroy_cb), vd); |
9 | 407 |
408 menu_item_add_stock_sensitive(menu, _("_Up to parent"), GTK_STOCK_GO_UP, | |
382 | 409 (vd->path && strcmp(vd->path, "/") != 0), |
410 G_CALLBACK(vdtree_pop_menu_up_cb), vd); | |
9 | 411 |
412 menu_item_add_divider(menu); | |
413 menu_item_add_sensitive(menu, _("_Slideshow"), active, | |
382 | 414 G_CALLBACK(vdtree_pop_menu_slide_cb), vd); |
9 | 415 menu_item_add_sensitive(menu, _("Slideshow recursive"), active, |
382 | 416 G_CALLBACK(vdtree_pop_menu_slide_rec_cb), vd); |
9 | 417 |
418 menu_item_add_divider(menu); | |
419 menu_item_add_stock_sensitive(menu, _("Find _duplicates..."), GTK_STOCK_FIND, active, | |
382 | 420 G_CALLBACK(vdtree_pop_menu_dupe_cb), vd); |
9 | 421 menu_item_add_stock_sensitive(menu, _("Find duplicates recursive..."), GTK_STOCK_FIND, active, |
382 | 422 G_CALLBACK(vdtree_pop_menu_dupe_rec_cb), vd); |
9 | 423 |
424 menu_item_add_divider(menu); | |
425 | |
426 active = (fd && | |
427 access_file(fd->path, W_OK | X_OK)); | |
428 menu_item_add_sensitive(menu, _("_New folder..."), active, | |
382 | 429 G_CALLBACK(vdtree_pop_menu_new_cb), vd); |
9 | 430 |
112
b15d4c18168f
Fri Nov 17 19:06:19 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
431 menu_item_add_sensitive(menu, _("_Rename..."), parent_active, |
382 | 432 G_CALLBACK(vdtree_pop_menu_rename_cb), vd); |
112
b15d4c18168f
Fri Nov 17 19:06:19 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
433 menu_item_add_stock_sensitive(menu, _("_Delete..."), GTK_STOCK_DELETE, parent_active, |
382 | 434 G_CALLBACK(vdtree_pop_menu_delete_cb), vd); |
9 | 435 |
436 menu_item_add_divider(menu); | |
437 menu_item_add_check(menu, _("View as _tree"), TRUE, | |
382 | 438 G_CALLBACK(vdtree_pop_menu_dir_view_as_cb), vd); |
356 | 439 menu_item_add_check(menu, _("Show _hidden files"), options->file_filter.show_hidden_files, |
382 | 440 G_CALLBACK(vdtree_toggle_show_hidden_files_cb), vd); |
355
0b82646e977f
Let toggle the visibility of hidden files from directories list
zas_
parents:
332
diff
changeset
|
441 |
9 | 442 menu_item_add_stock(menu, _("Re_fresh"), GTK_STOCK_REFRESH, |
382 | 443 G_CALLBACK(vdtree_pop_menu_refresh_cb), vd); |
9 | 444 |
445 return menu; | |
446 } | |
447 | |
448 /* | |
449 *---------------------------------------------------------------------------- | |
450 * dnd | |
451 *---------------------------------------------------------------------------- | |
452 */ | |
453 | |
454 static GtkTargetEntry vdtree_dnd_drop_types[] = { | |
455 { "text/uri-list", 0, TARGET_URI_LIST } | |
456 }; | |
457 static gint vdtree_dnd_drop_types_count = 1; | |
458 | |
459 | |
382 | 460 static void vdtree_dest_set(ViewDir *vd, gint enable) |
9 | 461 { |
462 if (enable) | |
463 { | |
382 | 464 gtk_drag_dest_set(vd->view, |
9 | 465 GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP, |
466 vdtree_dnd_drop_types, vdtree_dnd_drop_types_count, | |
467 GDK_ACTION_MOVE | GDK_ACTION_COPY); | |
468 } | |
469 else | |
470 { | |
382 | 471 gtk_drag_dest_unset(vd->view); |
9 | 472 } |
473 } | |
474 | |
475 static void vdtree_dnd_get(GtkWidget *widget, GdkDragContext *context, | |
476 GtkSelectionData *selection_data, guint info, | |
477 guint time, gpointer data) | |
478 { | |
382 | 479 ViewDir *vd = data; |
9 | 480 GList *list; |
481 gchar *uri_text = NULL; | |
482 gint length = 0; | |
483 | |
382 | 484 if (!vd->click_fd) return; |
9 | 485 |
486 switch (info) | |
487 { | |
488 case TARGET_URI_LIST: | |
489 case TARGET_TEXT_PLAIN: | |
382 | 490 list = g_list_prepend(NULL, vd->click_fd); |
138 | 491 uri_text = uri_text_from_filelist(list, &length, (info == TARGET_TEXT_PLAIN)); |
9 | 492 g_list_free(list); |
493 break; | |
494 } | |
495 | |
496 if (uri_text) | |
497 { | |
498 gtk_selection_data_set(selection_data, selection_data->target, | |
64
04ff0df3ad2f
Mon Aug 15 17:13:57 2005 John Ellis <johne@verizon.net>
gqview
parents:
63
diff
changeset
|
499 8, (guchar *)uri_text, length); |
9 | 500 g_free(uri_text); |
501 } | |
502 } | |
503 | |
504 static void vdtree_dnd_begin(GtkWidget *widget, GdkDragContext *context, gpointer data) | |
505 { | |
382 | 506 ViewDir *vd = data; |
9 | 507 |
383
499d7ba62261
Move some dnd common code from view_dir_list.c and view_dir_tree.c
zas_
parents:
382
diff
changeset
|
508 vd_color_set(vd, vd->click_fd, TRUE); |
382 | 509 vdtree_dest_set(vd, FALSE); |
9 | 510 } |
511 | |
512 static void vdtree_dnd_end(GtkWidget *widget, GdkDragContext *context, gpointer data) | |
513 { | |
382 | 514 ViewDir *vd = data; |
9 | 515 |
383
499d7ba62261
Move some dnd common code from view_dir_list.c and view_dir_tree.c
zas_
parents:
382
diff
changeset
|
516 vd_color_set(vd, vd->click_fd, FALSE); |
382 | 517 vdtree_dest_set(vd, TRUE); |
9 | 518 } |
519 | |
520 static void vdtree_dnd_drop_receive(GtkWidget *widget, | |
521 GdkDragContext *context, gint x, gint y, | |
522 GtkSelectionData *selection_data, guint info, | |
523 guint time, gpointer data) | |
524 { | |
382 | 525 ViewDir *vd = data; |
9 | 526 GtkTreePath *tpath; |
527 GtkTreeIter iter; | |
528 FileData *fd = NULL; | |
529 | |
382 | 530 vd->click_fd = NULL; |
9 | 531 |
532 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), x, y, | |
533 &tpath, NULL, NULL, NULL)) | |
534 { | |
535 GtkTreeModel *store; | |
536 NodeData *nd; | |
537 | |
538 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget)); | |
539 gtk_tree_model_get_iter(store, &iter, tpath); | |
540 gtk_tree_model_get(store, &iter, DIR_COLUMN_POINTER, &nd, -1); | |
541 gtk_tree_path_free(tpath); | |
542 | |
543 fd = (nd) ? nd->fd : NULL; | |
544 } | |
545 | |
546 if (!fd) return; | |
547 | |
548 if (info == TARGET_URI_LIST) | |
549 { | |
550 GList *list; | |
551 gint active; | |
552 | |
138 | 553 list = uri_filelist_from_text((gchar *)selection_data->data, TRUE); |
9 | 554 if (!list) return; |
555 | |
556 active = access_file(fd->path, W_OK | X_OK); | |
557 | |
383
499d7ba62261
Move some dnd common code from view_dir_list.c and view_dir_tree.c
zas_
parents:
382
diff
changeset
|
558 vd_color_set(vd, fd, TRUE); |
499d7ba62261
Move some dnd common code from view_dir_list.c and view_dir_tree.c
zas_
parents:
382
diff
changeset
|
559 vd->popup = vd_drop_menu(vd, active); |
382 | 560 gtk_menu_popup(GTK_MENU(vd->popup), NULL, NULL, NULL, NULL, 0, time); |
9 | 561 |
382 | 562 vd->drop_fd = fd; |
563 vd->drop_list = list; | |
9 | 564 } |
565 } | |
566 | |
567 static gint vdtree_dnd_drop_expand_cb(gpointer data) | |
568 { | |
382 | 569 ViewDir *vd = data; |
9 | 570 GtkTreeIter iter; |
571 | |
382 | 572 if (vd->drop_fd && |
573 vdtree_find_row(vd, vd->drop_fd, &iter, NULL)) | |
9 | 574 { |
382 | 575 vdtree_populate_path_by_iter(vd, &iter, FALSE, vd->path); |
576 vdtree_expand_by_data(vd, vd->drop_fd, TRUE); | |
9 | 577 } |
578 | |
382 | 579 VDTREE_INFO(vd, drop_expand_id) = -1; |
9 | 580 return FALSE; |
581 } | |
582 | |
382 | 583 static void vdtree_dnd_drop_expand_cancel(ViewDir *vd) |
9 | 584 { |
382 | 585 if (VDTREE_INFO(vd, drop_expand_id) != -1) g_source_remove(VDTREE_INFO(vd, drop_expand_id)); |
586 VDTREE_INFO(vd, drop_expand_id) = -1; | |
9 | 587 } |
588 | |
382 | 589 static void vdtree_dnd_drop_expand(ViewDir *vd) |
9 | 590 { |
382 | 591 vdtree_dnd_drop_expand_cancel(vd); |
592 VDTREE_INFO(vd, drop_expand_id) = g_timeout_add(1000, vdtree_dnd_drop_expand_cb, vd); | |
9 | 593 } |
594 | |
382 | 595 static void vdtree_drop_update(ViewDir *vd, gint x, gint y) |
9 | 596 { |
597 GtkTreePath *tpath; | |
598 GtkTreeIter iter; | |
599 FileData *fd = NULL; | |
600 | |
382 | 601 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(vd->view), x, y, |
9 | 602 &tpath, NULL, NULL, NULL)) |
603 { | |
604 GtkTreeModel *store; | |
605 NodeData *nd; | |
606 | |
382 | 607 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vd->view)); |
9 | 608 gtk_tree_model_get_iter(store, &iter, tpath); |
609 gtk_tree_model_get(store, &iter, DIR_COLUMN_POINTER, &nd, -1); | |
610 gtk_tree_path_free(tpath); | |
611 | |
612 fd = (nd) ? nd->fd : NULL; | |
613 } | |
614 | |
382 | 615 if (fd != vd->drop_fd) |
9 | 616 { |
383
499d7ba62261
Move some dnd common code from view_dir_list.c and view_dir_tree.c
zas_
parents:
382
diff
changeset
|
617 vd_color_set(vd, vd->drop_fd, FALSE); |
499d7ba62261
Move some dnd common code from view_dir_list.c and view_dir_tree.c
zas_
parents:
382
diff
changeset
|
618 vd_color_set(vd, fd, TRUE); |
382 | 619 if (fd) vdtree_dnd_drop_expand(vd); |
9 | 620 } |
621 | |
382 | 622 vd->drop_fd = fd; |
9 | 623 } |
624 | |
382 | 625 static void vdtree_dnd_drop_scroll_cancel(ViewDir *vd) |
9 | 626 { |
382 | 627 if (vd->drop_scroll_id != -1) g_source_remove(vd->drop_scroll_id); |
628 vd->drop_scroll_id = -1; | |
9 | 629 } |
630 | |
631 static gint vdtree_auto_scroll_idle_cb(gpointer data) | |
632 { | |
382 | 633 ViewDir *vd = data; |
9 | 634 |
382 | 635 if (vd->drop_fd) |
9 | 636 { |
637 GdkWindow *window; | |
638 gint x, y; | |
639 gint w, h; | |
640 | |
382 | 641 window = vd->view->window; |
9 | 642 gdk_window_get_pointer(window, &x, &y, NULL); |
643 gdk_drawable_get_size(window, &w, &h); | |
644 if (x >= 0 && x < w && y >= 0 && y < h) | |
645 { | |
382 | 646 vdtree_drop_update(vd, x, y); |
9 | 647 } |
648 } | |
649 | |
382 | 650 vd->drop_scroll_id = -1; |
9 | 651 return FALSE; |
652 } | |
653 | |
654 static gint vdtree_auto_scroll_notify_cb(GtkWidget *widget, gint x, gint y, gpointer data) | |
655 { | |
382 | 656 ViewDir *vd = data; |
9 | 657 |
382 | 658 if (!vd->drop_fd || vd->drop_list) return FALSE; |
9 | 659 |
382 | 660 if (vd->drop_scroll_id == -1) vd->drop_scroll_id = g_idle_add(vdtree_auto_scroll_idle_cb, vd); |
9 | 661 |
662 return TRUE; | |
663 } | |
664 | |
665 static gint vdtree_dnd_drop_motion(GtkWidget *widget, GdkDragContext *context, | |
666 gint x, gint y, guint time, gpointer data) | |
667 { | |
382 | 668 ViewDir *vd = data; |
9 | 669 |
382 | 670 vd->click_fd = NULL; |
9 | 671 |
382 | 672 if (gtk_drag_get_source_widget(context) == vd->view) |
9 | 673 { |
674 gdk_drag_status(context, 0, time); | |
675 return TRUE; | |
676 } | |
677 else | |
678 { | |
679 gdk_drag_status(context, context->suggested_action, time); | |
680 } | |
681 | |
382 | 682 vdtree_drop_update(vd, x, y); |
9 | 683 |
382 | 684 if (vd->drop_fd) |
9 | 685 { |
382 | 686 GtkAdjustment *adj = gtk_tree_view_get_vadjustment(GTK_TREE_VIEW(vd->view)); |
687 widget_auto_scroll_start(vd->view, adj, -1, -1, vdtree_auto_scroll_notify_cb, vd); | |
9 | 688 } |
689 | |
690 return FALSE; | |
691 } | |
692 | |
693 static void vdtree_dnd_drop_leave(GtkWidget *widget, GdkDragContext *context, guint time, gpointer data) | |
694 { | |
382 | 695 ViewDir *vd = data; |
9 | 696 |
383
499d7ba62261
Move some dnd common code from view_dir_list.c and view_dir_tree.c
zas_
parents:
382
diff
changeset
|
697 if (vd->drop_fd != vd->click_fd) vd_color_set(vd, vd->drop_fd, FALSE); |
9 | 698 |
382 | 699 vd->drop_fd = NULL; |
9 | 700 |
382 | 701 vdtree_dnd_drop_expand_cancel(vd); |
9 | 702 } |
703 | |
382 | 704 static void vdtree_dnd_init(ViewDir *vd) |
9 | 705 { |
382 | 706 gtk_drag_source_set(vd->view, GDK_BUTTON1_MASK | GDK_BUTTON2_MASK, |
9 | 707 dnd_file_drag_types, dnd_file_drag_types_count, |
708 GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_ASK); | |
382 | 709 g_signal_connect(G_OBJECT(vd->view), "drag_data_get", |
710 G_CALLBACK(vdtree_dnd_get), vd); | |
711 g_signal_connect(G_OBJECT(vd->view), "drag_begin", | |
712 G_CALLBACK(vdtree_dnd_begin), vd); | |
713 g_signal_connect(G_OBJECT(vd->view), "drag_end", | |
714 G_CALLBACK(vdtree_dnd_end), vd); | |
9 | 715 |
382 | 716 vdtree_dest_set(vd, TRUE); |
717 g_signal_connect(G_OBJECT(vd->view), "drag_data_received", | |
718 G_CALLBACK(vdtree_dnd_drop_receive), vd); | |
719 g_signal_connect(G_OBJECT(vd->view), "drag_motion", | |
720 G_CALLBACK(vdtree_dnd_drop_motion), vd); | |
721 g_signal_connect(G_OBJECT(vd->view), "drag_leave", | |
722 G_CALLBACK(vdtree_dnd_drop_leave), vd); | |
9 | 723 } |
724 | |
725 /* | |
726 *---------------------------------------------------------------------------- | |
727 * parts lists | |
728 *---------------------------------------------------------------------------- | |
729 */ | |
730 | |
731 static GList *parts_list(const gchar *path) | |
732 { | |
733 GList *list = NULL; | |
734 const gchar *strb, *strp; | |
735 gint l; | |
736 | |
737 strp = path; | |
738 | |
739 if (*strp != '/') return NULL; | |
740 | |
741 strp++; | |
742 strb = strp; | |
743 l = 0; | |
744 | |
745 while (*strp != '\0') | |
746 { | |
747 if (*strp == '/') | |
748 { | |
749 if (l > 0) list = g_list_prepend(list, g_strndup(strb, l)); | |
750 strp++; | |
751 strb = strp; | |
752 l = 0; | |
753 } | |
754 else | |
755 { | |
756 strp++; | |
757 l++; | |
758 } | |
759 } | |
760 if (l > 0) list = g_list_prepend(list, g_strndup(strb, l)); | |
761 | |
762 list = g_list_reverse(list); | |
763 | |
764 list = g_list_prepend(list, g_strdup("/")); | |
765 | |
766 return list; | |
767 } | |
768 | |
769 static void parts_list_free(GList *list) | |
770 { | |
771 GList *work = list; | |
772 while (work) | |
773 { | |
774 PathData *pd = work->data; | |
775 g_free(pd->name); | |
776 g_free(pd); | |
777 work = work->next; | |
778 } | |
779 | |
780 g_list_free(list); | |
781 } | |
782 | |
382 | 783 static GList *parts_list_add_node_points(ViewDir *vd, GList *list) |
9 | 784 { |
785 GList *work; | |
786 GtkTreeModel *store; | |
787 GtkTreeIter iter; | |
788 gint valid; | |
789 | |
382 | 790 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vd->view)); |
9 | 791 valid = gtk_tree_model_get_iter_first(store, &iter); |
792 | |
793 work = list; | |
794 while (work) | |
795 { | |
796 PathData *pd; | |
797 FileData *fd = NULL; | |
798 | |
799 pd = g_new0(PathData, 1); | |
800 pd->name = work->data; | |
801 | |
802 while (valid && !fd) | |
803 { | |
804 NodeData *nd; | |
805 | |
806 gtk_tree_model_get(store, &iter, DIR_COLUMN_POINTER, &nd, -1); | |
807 if (strcmp(nd->fd->name, pd->name) == 0) | |
808 { | |
809 fd = nd->fd; | |
810 } | |
811 else | |
812 { | |
813 valid = gtk_tree_model_iter_next(store, &iter); | |
814 } | |
815 } | |
816 | |
817 pd->node = fd; | |
818 work->data = pd; | |
819 | |
820 if (fd) | |
821 { | |
822 GtkTreeIter parent; | |
823 memcpy(&parent, &iter, sizeof(parent)); | |
824 valid = gtk_tree_model_iter_children(store, &iter, &parent); | |
825 } | |
826 | |
827 work = work->next; | |
828 } | |
829 | |
830 return list; | |
831 } | |
832 | |
833 /* | |
834 *---------------------------------------------------------------------------- | |
835 * misc | |
836 *---------------------------------------------------------------------------- | |
837 */ | |
838 | |
839 #if 0 | |
840 static void vdtree_row_deleted_cb(GtkTreeModel *tree_model, GtkTreePath *tpath, gpointer data) | |
841 { | |
842 GtkTreeIter iter; | |
843 NodeData *nd; | |
844 | |
845 gtk_tree_model_get_iter(tree_model, &iter, tpath); | |
846 gtk_tree_model_get(tree_model, &iter, DIR_COLUMN_POINTER, &nd, -1); | |
847 | |
848 if (!nd) return; | |
849 | |
138 | 850 file_data_unref(nd->fd); |
9 | 851 g_free(nd); |
852 } | |
853 #endif | |
854 | |
855 /* | |
856 *---------------------------------------------------------------------------- | |
857 * node traversal, management | |
858 *---------------------------------------------------------------------------- | |
859 */ | |
860 | |
382 | 861 static gint vdtree_find_iter_by_data(ViewDir *vd, GtkTreeIter *parent, NodeData *nd, GtkTreeIter *iter) |
9 | 862 { |
863 GtkTreeModel *store; | |
864 | |
382 | 865 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vd->view)); |
9 | 866 if (!nd || !gtk_tree_model_iter_children(store, iter, parent)) return -1; |
867 do { | |
868 NodeData *cnd; | |
869 | |
870 gtk_tree_model_get(store, iter, DIR_COLUMN_POINTER, &cnd, -1); | |
871 if (cnd == nd) return TRUE; | |
872 } while (gtk_tree_model_iter_next(store, iter)); | |
873 | |
874 return FALSE; | |
875 } | |
876 | |
382 | 877 static NodeData *vdtree_find_iter_by_name(ViewDir *vd, GtkTreeIter *parent, const gchar *name, GtkTreeIter *iter) |
9 | 878 { |
879 GtkTreeModel *store; | |
880 | |
382 | 881 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vd->view)); |
9 | 882 if (!name || !gtk_tree_model_iter_children(store, iter, parent)) return NULL; |
883 do { | |
884 NodeData *nd; | |
885 | |
886 gtk_tree_model_get(store, iter, DIR_COLUMN_POINTER, &nd, -1); | |
887 if (nd && strcmp(nd->fd->name, name) == 0) return nd; | |
888 } while (gtk_tree_model_iter_next(store, iter)); | |
889 | |
890 return NULL; | |
891 } | |
892 | |
382 | 893 static void vdtree_add_by_data(ViewDir *vd, FileData *fd, GtkTreeIter *parent) |
9 | 894 { |
895 GtkTreeStore *store; | |
896 GtkTreeIter child; | |
897 NodeData *nd; | |
898 GdkPixbuf *pixbuf; | |
899 NodeData *end; | |
900 GtkTreeIter empty; | |
901 | |
902 if (!fd) return; | |
903 | |
904 if (access_file(fd->path, R_OK | X_OK)) | |
905 { | |
382 | 906 pixbuf = vd->pf->close; |
9 | 907 } |
908 else | |
909 { | |
382 | 910 pixbuf = vd->pf->deny; |
9 | 911 } |
912 | |
913 nd = g_new0(NodeData, 1); | |
914 nd->fd = fd; | |
915 nd->expanded = FALSE; | |
916 nd->last_update = time(NULL); | |
917 | |
382 | 918 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vd->view))); |
9 | 919 gtk_tree_store_append(store, &child, parent); |
920 gtk_tree_store_set(store, &child, DIR_COLUMN_POINTER, nd, | |
921 DIR_COLUMN_ICON, pixbuf, | |
922 DIR_COLUMN_NAME, nd->fd->name, | |
923 DIR_COLUMN_COLOR, FALSE, -1); | |
924 | |
925 /* all nodes are created with an "empty" node, so that the expander is shown | |
926 * this is removed when the child is populated */ | |
927 end = g_new0(NodeData, 1); | |
138 | 928 end->fd = file_data_new_simple(""); |
9 | 929 end->expanded = TRUE; |
930 | |
931 gtk_tree_store_append(store, &empty, &child); | |
932 gtk_tree_store_set(store, &empty, DIR_COLUMN_POINTER, end, | |
933 DIR_COLUMN_NAME, "empty", -1); | |
934 | |
935 if (parent) | |
936 { | |
937 NodeData *pnd; | |
938 GtkTreePath *tpath; | |
939 | |
940 gtk_tree_model_get(GTK_TREE_MODEL(store), parent, DIR_COLUMN_POINTER, &pnd, -1); | |
941 tpath = gtk_tree_model_get_path(GTK_TREE_MODEL(store), parent); | |
320 | 942 if (options->tree_descend_subdirs && |
382 | 943 gtk_tree_view_row_expanded(GTK_TREE_VIEW(vd->view), tpath) && |
9 | 944 !nd->expanded) |
945 { | |
382 | 946 vdtree_populate_path_by_iter(vd, &child, FALSE, vd->path); |
9 | 947 } |
948 gtk_tree_path_free(tpath); | |
949 } | |
950 } | |
951 | |
382 | 952 static gint vdtree_populate_path_by_iter(ViewDir *vd, GtkTreeIter *iter, gint force, const gchar *target_path) |
9 | 953 { |
954 GtkTreeModel *store; | |
955 GList *list; | |
956 GList *work; | |
957 GList *old; | |
958 time_t current_time; | |
959 GtkTreeIter child; | |
960 NodeData *nd; | |
961 | |
382 | 962 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vd->view)); |
9 | 963 gtk_tree_model_get(store, iter, DIR_COLUMN_POINTER, &nd, -1); |
964 | |
965 if (!nd) return FALSE; | |
966 | |
967 current_time = time(NULL); | |
968 | |
969 if (nd->expanded) | |
970 { | |
971 if (!force && current_time - nd->last_update < 10) return TRUE; | |
972 if (!isdir(nd->fd->path)) | |
973 { | |
382 | 974 if (vd->click_fd == nd->fd) vd->click_fd = NULL; |
975 if (vd->drop_fd == nd->fd) vd->drop_fd = NULL; | |
9 | 976 gtk_tree_store_remove(GTK_TREE_STORE(store), iter); |
977 vdtree_node_free(nd); | |
978 return FALSE; | |
979 } | |
980 if (!force && filetime(nd->fd->path) == nd->fd->date) return TRUE; | |
981 } | |
982 | |
382 | 983 vdtree_busy_push(vd); |
9 | 984 |
985 list = NULL; | |
986 filelist_read(nd->fd->path, NULL, &list); | |
987 | |
988 /* when hidden files are not enabled, and the user enters a hidden path, | |
989 * allow the tree to display that path by specifically inserting the hidden entries | |
990 */ | |
356 | 991 if (!options->file_filter.show_hidden_files && |
9 | 992 target_path && |
993 strncmp(nd->fd->path, target_path, strlen(nd->fd->path)) == 0) | |
994 { | |
995 gint n; | |
996 | |
997 n = strlen(nd->fd->path); | |
998 if (target_path[n] == '/' && target_path[n+1] == '.') | |
999 { | |
1000 gchar *name8; | |
1001 struct stat sbuf; | |
1002 | |
1003 n++; | |
1004 | |
1005 while (target_path[n] != '\0' && target_path[n] != '/') n++; | |
1006 name8 = g_strndup(target_path, n); | |
1007 | |
1008 if (stat_utf8(name8, &sbuf)) | |
1009 { | |
145
8be2cc687304
fixed grouping sidecar files and made it configurable via config file
nadvornik
parents:
138
diff
changeset
|
1010 list = g_list_prepend(list, file_data_new_simple(name8)); |
9 | 1011 } |
1012 | |
1013 g_free(name8); | |
1014 } | |
1015 } | |
1016 | |
1017 old = NULL; | |
1018 if (gtk_tree_model_iter_children(store, &child, iter)) | |
1019 { | |
1020 do { | |
1021 NodeData *cnd; | |
1022 | |
1023 gtk_tree_model_get(store, &child, DIR_COLUMN_POINTER, &cnd, -1); | |
1024 old = g_list_prepend(old, cnd); | |
1025 } while (gtk_tree_model_iter_next(store, &child)); | |
1026 } | |
1027 | |
1028 work = list; | |
1029 while (work) | |
1030 { | |
1031 FileData *fd; | |
1032 | |
1033 fd = work->data; | |
1034 work = work->next; | |
1035 | |
1036 if (strcmp(fd->name, ".") == 0 || strcmp(fd->name, "..") == 0) | |
1037 { | |
138 | 1038 file_data_unref(fd); |
9 | 1039 } |
1040 else | |
1041 { | |
1042 NodeData *cnd; | |
1043 | |
382 | 1044 cnd = vdtree_find_iter_by_name(vd, iter, fd->name, &child); |
9 | 1045 if (cnd) |
1046 { | |
1047 old = g_list_remove(old, cnd); | |
1048 if (cnd->expanded && cnd->fd->date != fd->date && | |
382 | 1049 vdtree_populate_path_by_iter(vd, &child, FALSE, target_path)) |
9 | 1050 { |
1051 cnd->fd->size = fd->size; | |
1052 cnd->fd->date = fd->date; | |
1053 } | |
1054 | |
138 | 1055 file_data_unref(fd); |
9 | 1056 } |
1057 else | |
1058 { | |
382 | 1059 vdtree_add_by_data(vd, fd, iter); |
9 | 1060 } |
1061 } | |
1062 } | |
1063 | |
1064 work = old; | |
1065 while (work) | |
1066 { | |
1067 NodeData *cnd = work->data; | |
1068 work = work->next; | |
1069 | |
382 | 1070 if (vd->click_fd == cnd->fd) vd->click_fd = NULL; |
1071 if (vd->drop_fd == cnd->fd) vd->drop_fd = NULL; | |
9 | 1072 |
382 | 1073 if (vdtree_find_iter_by_data(vd, iter, cnd, &child)) |
9 | 1074 { |
1075 gtk_tree_store_remove(GTK_TREE_STORE(store), &child); | |
1076 vdtree_node_free(cnd); | |
1077 } | |
1078 } | |
1079 | |
1080 g_list_free(old); | |
1081 g_list_free(list); | |
1082 | |
382 | 1083 vdtree_busy_pop(vd); |
9 | 1084 |
1085 nd->expanded = TRUE; | |
1086 nd->last_update = current_time; | |
1087 | |
1088 return TRUE; | |
1089 } | |
1090 | |
382 | 1091 static FileData *vdtree_populate_path(ViewDir *vd, const gchar *path, gint expand, gint force) |
9 | 1092 { |
1093 GList *list; | |
1094 GList *work; | |
1095 FileData *fd = NULL; | |
1096 | |
1097 if (!path) return NULL; | |
1098 | |
382 | 1099 vdtree_busy_push(vd); |
9 | 1100 |
1101 list = parts_list(path); | |
382 | 1102 list = parts_list_add_node_points(vd, list); |
9 | 1103 |
1104 work = list; | |
1105 while (work) | |
1106 { | |
1107 PathData *pd = work->data; | |
1108 if (pd->node == NULL) | |
1109 { | |
1110 PathData *parent_pd; | |
1111 GtkTreeIter parent_iter; | |
1112 GtkTreeIter iter; | |
1113 NodeData *nd; | |
1114 | |
1115 if (work == list) | |
1116 { | |
1117 /* should not happen */ | |
1118 printf("vdtree warning, root node not found\n"); | |
1119 parts_list_free(list); | |
382 | 1120 vdtree_busy_pop(vd); |
9 | 1121 return NULL; |
1122 } | |
1123 | |
1124 parent_pd = work->prev->data; | |
1125 | |
382 | 1126 if (!vdtree_find_row(vd, parent_pd->node, &parent_iter, NULL) || |
1127 !vdtree_populate_path_by_iter(vd, &parent_iter, force, path) || | |
1128 (nd = vdtree_find_iter_by_name(vd, &parent_iter, pd->name, &iter)) == NULL) | |
9 | 1129 { |
1130 printf("vdtree warning, aborted at %s\n", parent_pd->name); | |
1131 parts_list_free(list); | |
382 | 1132 vdtree_busy_pop(vd); |
9 | 1133 return NULL; |
1134 } | |
1135 | |
1136 pd->node = nd->fd; | |
1137 | |
1138 if (pd->node) | |
1139 { | |
1140 if (expand) | |
1141 { | |
382 | 1142 vdtree_expand_by_iter(vd, &parent_iter, TRUE); |
1143 vdtree_expand_by_iter(vd, &iter, TRUE); | |
9 | 1144 } |
382 | 1145 vdtree_populate_path_by_iter(vd, &iter, force, path); |
9 | 1146 } |
1147 } | |
1148 else | |
1149 { | |
1150 GtkTreeIter iter; | |
1151 | |
382 | 1152 if (vdtree_find_row(vd, pd->node, &iter, NULL)) |
9 | 1153 { |
382 | 1154 if (expand) vdtree_expand_by_iter(vd, &iter, TRUE); |
1155 vdtree_populate_path_by_iter(vd, &iter, force, path); | |
9 | 1156 } |
1157 } | |
1158 | |
1159 work = work->next; | |
1160 } | |
1161 | |
1162 work = g_list_last(list); | |
1163 if (work) | |
1164 { | |
1165 PathData *pd = work->data; | |
1166 fd = pd->node; | |
1167 } | |
1168 parts_list_free(list); | |
1169 | |
382 | 1170 vdtree_busy_pop(vd); |
9 | 1171 |
1172 return fd; | |
1173 } | |
1174 | |
1175 /* | |
1176 *---------------------------------------------------------------------------- | |
1177 * access | |
1178 *---------------------------------------------------------------------------- | |
1179 */ | |
1180 | |
1181 static gint selection_is_ok = FALSE; | |
1182 | |
1183 static gboolean vdtree_select_cb(GtkTreeSelection *selection, GtkTreeModel *store, GtkTreePath *tpath, | |
1184 gboolean path_currently_selected, gpointer data) | |
1185 { | |
1186 return selection_is_ok; | |
1187 } | |
1188 | |
382 | 1189 static void vdtree_select_row(ViewDir *vd, FileData *fd) |
9 | 1190 { |
1191 GtkTreeSelection *selection; | |
1192 GtkTreeIter iter; | |
1193 | |
382 | 1194 if (!vdtree_find_row(vd, fd, &iter, NULL)) return; |
1195 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vd->view)); | |
9 | 1196 |
1197 /* hack, such that selection is only allowed to be changed from here */ | |
1198 selection_is_ok = TRUE; | |
1199 gtk_tree_selection_select_iter(selection, &iter); | |
1200 selection_is_ok = FALSE; | |
1201 | |
382 | 1202 if (!vdtree_populate_path_by_iter(vd, &iter, FALSE, vd->path)) return; |
9 | 1203 |
382 | 1204 vdtree_expand_by_iter(vd, &iter, TRUE); |
9 | 1205 |
382 | 1206 if (fd && vd->select_func) |
9 | 1207 { |
382 | 1208 vd->select_func(vd, fd->path, vd->select_data); |
9 | 1209 } |
1210 } | |
1211 | |
382 | 1212 gint vdtree_set_path(ViewDir *vd, const gchar *path) |
9 | 1213 { |
1214 FileData *fd; | |
1215 GtkTreeIter iter; | |
1216 | |
1217 if (!path) return FALSE; | |
382 | 1218 if (vd->path && strcmp(path, vd->path) == 0) return TRUE; |
9 | 1219 |
382 | 1220 g_free(vd->path); |
1221 vd->path = g_strdup(path); | |
9 | 1222 |
382 | 1223 fd = vdtree_populate_path(vd, vd->path, TRUE, FALSE); |
9 | 1224 |
1225 if (!fd) return FALSE; | |
1226 | |
382 | 1227 if (vdtree_find_row(vd, fd, &iter, NULL)) |
9 | 1228 { |
1229 GtkTreeModel *store; | |
1230 GtkTreePath *tpath; | |
1231 | |
382 | 1232 tree_view_row_make_visible(GTK_TREE_VIEW(vd->view), &iter, TRUE); |
9 | 1233 |
382 | 1234 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vd->view)); |
9 | 1235 tpath = gtk_tree_model_get_path(store, &iter); |
382 | 1236 gtk_tree_view_set_cursor(GTK_TREE_VIEW(vd->view), tpath, NULL, FALSE); |
9 | 1237 gtk_tree_path_free(tpath); |
1238 | |
382 | 1239 vdtree_select_row(vd, fd); |
9 | 1240 } |
1241 | |
1242 return TRUE; | |
1243 } | |
1244 | |
1245 #if 0 | |
382 | 1246 const gchar *vdtree_get_path(ViewDir *vd) |
9 | 1247 { |
382 | 1248 return vd->path; |
9 | 1249 } |
1250 #endif | |
1251 | |
382 | 1252 void vdtree_refresh(ViewDir *vd) |
9 | 1253 { |
382 | 1254 vdtree_populate_path(vd, vd->path, FALSE, TRUE); |
9 | 1255 } |
1256 | |
382 | 1257 const gchar *vdtree_row_get_path(ViewDir *vd, gint row) |
9 | 1258 { |
1259 printf("FIXME: no get row path\n"); | |
1260 return NULL; | |
1261 } | |
1262 | |
1263 /* | |
1264 *---------------------------------------------------------------------------- | |
1265 * callbacks | |
1266 *---------------------------------------------------------------------------- | |
1267 */ | |
1268 | |
1269 static void vdtree_menu_position_cb(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer data) | |
1270 { | |
382 | 1271 ViewDir *vd = data; |
9 | 1272 GtkTreeModel *store; |
1273 GtkTreeIter iter; | |
1274 GtkTreePath *tpath; | |
1275 gint cw, ch; | |
1276 | |
382 | 1277 if (vdtree_find_row(vd, vd->click_fd, &iter, NULL) < 0) return; |
1278 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vd->view)); | |
9 | 1279 tpath = gtk_tree_model_get_path(store, &iter); |
382 | 1280 tree_view_get_cell_clamped(GTK_TREE_VIEW(vd->view), tpath, 0, TRUE, x, y, &cw, &ch); |
9 | 1281 gtk_tree_path_free(tpath); |
1282 *y += ch; | |
1283 popup_menu_position_clamp(menu, x, y, 0); | |
1284 } | |
1285 | |
1286 static gint vdtree_press_key_cb(GtkWidget *widget, GdkEventKey *event, gpointer data) | |
1287 { | |
382 | 1288 ViewDir *vd = data; |
9 | 1289 GtkTreePath *tpath; |
1290 GtkTreeIter iter; | |
1291 FileData *fd = NULL; | |
1292 | |
382 | 1293 gtk_tree_view_get_cursor(GTK_TREE_VIEW(vd->view), &tpath, NULL); |
9 | 1294 if (tpath) |
1295 { | |
1296 GtkTreeModel *store; | |
1297 NodeData *nd; | |
1298 | |
1299 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget)); | |
1300 gtk_tree_model_get_iter(store, &iter, tpath); | |
1301 gtk_tree_model_get(store, &iter, DIR_COLUMN_POINTER, &nd, -1); | |
1302 | |
1303 gtk_tree_path_free(tpath); | |
1304 | |
1305 fd = (nd) ? nd->fd : NULL; | |
1306 } | |
1307 | |
1308 switch (event->keyval) | |
1309 { | |
1310 case GDK_Menu: | |
382 | 1311 vd->click_fd = fd; |
383
499d7ba62261
Move some dnd common code from view_dir_list.c and view_dir_tree.c
zas_
parents:
382
diff
changeset
|
1312 vd_color_set(vd, vd->click_fd, TRUE); |
9 | 1313 |
382 | 1314 vd->popup = vdtree_pop_menu(vd, vd->click_fd); |
1315 gtk_menu_popup(GTK_MENU(vd->popup), NULL, NULL, vdtree_menu_position_cb, vd, 0, GDK_CURRENT_TIME); | |
9 | 1316 |
1317 return TRUE; | |
1318 break; | |
1319 case GDK_plus: | |
1320 case GDK_Right: | |
1321 case GDK_KP_Add: | |
1322 if (fd) | |
1323 { | |
382 | 1324 vdtree_populate_path_by_iter(vd, &iter, FALSE, vd->path); |
1325 vdtree_icon_set_by_iter(vd, &iter, vd->pf->open); | |
9 | 1326 } |
1327 break; | |
1328 } | |
1329 | |
1330 return FALSE; | |
1331 } | |
1332 | |
1333 static gint vdtree_clicked_on_expander(GtkTreeView *treeview, GtkTreePath *tpath, | |
1334 GtkTreeViewColumn *column, gint x, gint y, gint *left_of_expander) | |
1335 { | |
1336 gint depth; | |
1337 gint size; | |
1338 gint sep; | |
1339 gint exp_width; | |
1340 | |
1341 if (column != gtk_tree_view_get_expander_column(treeview)) return FALSE; | |
1342 | |
1343 gtk_widget_style_get(GTK_WIDGET(treeview), "expander-size", &size, "horizontal-separator", &sep, NULL); | |
1344 depth = gtk_tree_path_get_depth(tpath); | |
1345 | |
1346 exp_width = sep + size + sep; | |
1347 | |
1348 if (x <= depth * exp_width) | |
1349 { | |
1350 if (left_of_expander) *left_of_expander = !(x >= (depth - 1) * exp_width); | |
1351 return TRUE; | |
1352 } | |
1353 | |
1354 return FALSE; | |
1355 } | |
1356 | |
1357 static gint vdtree_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data) | |
1358 { | |
382 | 1359 ViewDir *vd = data; |
9 | 1360 GtkTreePath *tpath; |
1361 GtkTreeViewColumn *column; | |
1362 GtkTreeIter iter; | |
1363 NodeData *nd = NULL; | |
1364 | |
1365 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), bevent->x, bevent->y, | |
1366 &tpath, &column, NULL, NULL)) | |
1367 { | |
1368 GtkTreeModel *store; | |
1369 gint left_of_expander; | |
1370 | |
1371 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget)); | |
1372 gtk_tree_model_get_iter(store, &iter, tpath); | |
1373 gtk_tree_model_get(store, &iter, DIR_COLUMN_POINTER, &nd, -1); | |
1374 gtk_tree_view_set_cursor(GTK_TREE_VIEW(widget), tpath, NULL, FALSE); | |
1375 | |
1376 if (vdtree_clicked_on_expander(GTK_TREE_VIEW(widget), tpath, column, bevent->x, bevent->y, &left_of_expander)) | |
1377 { | |
382 | 1378 vd->click_fd = NULL; |
9 | 1379 |
1380 /* clicking this region should automatically reveal an expander, if necessary | |
1381 * treeview bug: the expander will not expand until a button_motion_event highlights it. | |
1382 */ | |
1383 if (bevent->button == 1 && | |
1384 !left_of_expander && | |
382 | 1385 !gtk_tree_view_row_expanded(GTK_TREE_VIEW(vd->view), tpath)) |
9 | 1386 { |
382 | 1387 vdtree_populate_path_by_iter(vd, &iter, FALSE, vd->path); |
1388 vdtree_icon_set_by_iter(vd, &iter, vd->pf->open); | |
9 | 1389 } |
1390 | |
1391 gtk_tree_path_free(tpath); | |
1392 return FALSE; | |
1393 } | |
1394 | |
1395 gtk_tree_path_free(tpath); | |
1396 } | |
1397 | |
382 | 1398 vd->click_fd = (nd) ? nd->fd : NULL; |
383
499d7ba62261
Move some dnd common code from view_dir_list.c and view_dir_tree.c
zas_
parents:
382
diff
changeset
|
1399 vd_color_set(vd, vd->click_fd, TRUE); |
9 | 1400 |
1401 if (bevent->button == 3) | |
1402 { | |
382 | 1403 vd->popup = vdtree_pop_menu(vd, vd->click_fd); |
1404 gtk_menu_popup(GTK_MENU(vd->popup), NULL, NULL, NULL, NULL, | |
9 | 1405 bevent->button, bevent->time); |
1406 } | |
1407 | |
1408 return (bevent->button != 1); | |
1409 } | |
1410 | |
1411 static gint vdtree_release_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data) | |
1412 { | |
382 | 1413 ViewDir *vd = data; |
9 | 1414 GtkTreePath *tpath; |
1415 GtkTreeIter iter; | |
1416 NodeData *nd = NULL; | |
1417 | |
382 | 1418 if (!vd->click_fd) return FALSE; |
383
499d7ba62261
Move some dnd common code from view_dir_list.c and view_dir_tree.c
zas_
parents:
382
diff
changeset
|
1419 vd_color_set(vd, vd->click_fd, FALSE); |
9 | 1420 |
1421 if (bevent->button != 1) return TRUE; | |
1422 | |
1423 if ((bevent->x != 0 || bevent->y != 0) && | |
1424 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), bevent->x, bevent->y, | |
1425 &tpath, NULL, NULL, NULL)) | |
1426 { | |
1427 GtkTreeModel *store; | |
1428 | |
1429 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget)); | |
1430 gtk_tree_model_get_iter(store, &iter, tpath); | |
1431 gtk_tree_model_get(store, &iter, DIR_COLUMN_POINTER, &nd, -1); | |
1432 gtk_tree_path_free(tpath); | |
1433 } | |
1434 | |
382 | 1435 if (nd && vd->click_fd == nd->fd) |
9 | 1436 { |
382 | 1437 vdtree_select_row(vd, vd->click_fd); |
9 | 1438 } |
1439 | |
1440 return FALSE; | |
1441 } | |
1442 | |
1443 static void vdtree_row_expanded(GtkTreeView *treeview, GtkTreeIter *iter, GtkTreePath *tpath, gpointer data) | |
1444 { | |
382 | 1445 ViewDir *vd = data; |
9 | 1446 |
382 | 1447 vdtree_populate_path_by_iter(vd, iter, FALSE, NULL); |
1448 vdtree_icon_set_by_iter(vd, iter, vd->pf->open); | |
9 | 1449 } |
1450 | |
1451 static void vdtree_row_collapsed(GtkTreeView *treeview, GtkTreeIter *iter, GtkTreePath *tpath, gpointer data) | |
1452 { | |
382 | 1453 ViewDir *vd = data; |
9 | 1454 |
382 | 1455 vdtree_icon_set_by_iter(vd, iter, vd->pf->close); |
9 | 1456 } |
1457 | |
1458 static gint vdtree_sort_cb(GtkTreeModel *store, GtkTreeIter *a, GtkTreeIter *b, gpointer data) | |
1459 { | |
1460 NodeData *nda; | |
1461 NodeData *ndb; | |
1462 | |
1463 gtk_tree_model_get(store, a, DIR_COLUMN_POINTER, &nda, -1); | |
1464 gtk_tree_model_get(store, b, DIR_COLUMN_POINTER, &ndb, -1); | |
1465 | |
1466 return CASE_SORT(nda->fd->name, ndb->fd->name); | |
1467 } | |
1468 | |
1469 /* | |
1470 *---------------------------------------------------------------------------- | |
1471 * core | |
1472 *---------------------------------------------------------------------------- | |
1473 */ | |
1474 | |
382 | 1475 static void vdtree_setup_root(ViewDir *vd) |
9 | 1476 { |
1477 const gchar *path = "/"; | |
1478 FileData *fd; | |
1479 | |
138 | 1480 |
1481 fd = file_data_new_simple(path); | |
382 | 1482 vdtree_add_by_data(vd, fd, NULL); |
9 | 1483 |
382 | 1484 vdtree_expand_by_data(vd, fd, TRUE); |
1485 vdtree_populate_path(vd, path, FALSE, FALSE); | |
9 | 1486 } |
1487 | |
1488 static void vdtree_activate_cb(GtkTreeView *tview, GtkTreePath *tpath, GtkTreeViewColumn *column, gpointer data) | |
1489 { | |
382 | 1490 ViewDir *vd = data; |
9 | 1491 GtkTreeModel *store; |
1492 GtkTreeIter iter; | |
1493 NodeData *nd; | |
1494 | |
1495 store = gtk_tree_view_get_model(tview); | |
1496 gtk_tree_model_get_iter(store, &iter, tpath); | |
1497 gtk_tree_model_get(store, &iter, DIR_COLUMN_POINTER, &nd, -1); | |
1498 | |
382 | 1499 vdtree_select_row(vd, nd->fd); |
9 | 1500 } |
1501 | |
1502 static GdkColor *vdtree_color_shifted(GtkWidget *widget) | |
1503 { | |
1504 static GdkColor color; | |
1505 static GtkWidget *done = NULL; | |
1506 | |
1507 if (done != widget) | |
1508 { | |
1509 GtkStyle *style; | |
1510 | |
1511 style = gtk_widget_get_style(widget); | |
1512 memcpy(&color, &style->base[GTK_STATE_NORMAL], sizeof(color)); | |
1513 shift_color(&color, -1, 0); | |
1514 done = widget; | |
1515 } | |
1516 | |
1517 return &color; | |
1518 } | |
1519 | |
1520 static void vdtree_color_cb(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, | |
1521 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data) | |
1522 { | |
382 | 1523 ViewDir *vd = data; |
9 | 1524 gboolean set; |
1525 | |
1526 gtk_tree_model_get(tree_model, iter, DIR_COLUMN_COLOR, &set, -1); | |
1527 g_object_set(G_OBJECT(cell), | |
382 | 1528 "cell-background-gdk", vdtree_color_shifted(vd->view), |
9 | 1529 "cell-background-set", set, NULL); |
1530 } | |
1531 | |
1532 static gboolean vdtree_destroy_node_cb(GtkTreeModel *store, GtkTreePath *tpath, GtkTreeIter *iter, gpointer data) | |
1533 { | |
1534 NodeData *nd; | |
1535 | |
1536 gtk_tree_model_get(store, iter, DIR_COLUMN_POINTER, &nd, -1); | |
1537 vdtree_node_free(nd); | |
1538 | |
1539 return FALSE; | |
1540 } | |
1541 | |
1542 static void vdtree_destroy_cb(GtkWidget *widget, gpointer data) | |
1543 { | |
382 | 1544 ViewDir *vd = data; |
9 | 1545 GtkTreeModel *store; |
1546 | |
382 | 1547 vdtree_dnd_drop_expand_cancel(vd); |
1548 vdtree_dnd_drop_scroll_cancel(vd); | |
1549 widget_auto_scroll_stop(vd->view); | |
9 | 1550 |
382 | 1551 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vd->view)); |
1552 gtk_tree_model_foreach(store, vdtree_destroy_node_cb, vd); | |
9 | 1553 } |
1554 | |
384
392dd6541d51
Merge parts of view_dir_list/tree constructors/destructors to
zas_
parents:
383
diff
changeset
|
1555 ViewDir *vdtree_new(ViewDir *vd, const gchar *path) |
9 | 1556 { |
1557 GtkTreeStore *store; | |
1558 GtkTreeSelection *selection; | |
1559 GtkTreeViewColumn *column; | |
1560 GtkCellRenderer *renderer; | |
1561 | |
382 | 1562 vd->info = g_new0(ViewDirInfoTree, 1); |
1563 vd->type = DIRVIEW_TREE; | |
384
392dd6541d51
Merge parts of view_dir_list/tree constructors/destructors to
zas_
parents:
383
diff
changeset
|
1564 vd->widget_destroy_cb = vdtree_destroy_cb; |
9 | 1565 |
382 | 1566 VDTREE_INFO(vd, drop_expand_id) = -1; |
9 | 1567 |
382 | 1568 VDTREE_INFO(vd, busy_ref) = 0; |
9 | 1569 |
1570 store = gtk_tree_store_new(4, G_TYPE_POINTER, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_INT); | |
382 | 1571 vd->view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); |
9 | 1572 g_object_unref(store); |
1573 | |
382 | 1574 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(vd->view), FALSE); |
1575 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(vd->view), FALSE); | |
1576 gtk_tree_sortable_set_default_sort_func(GTK_TREE_SORTABLE(store), vdtree_sort_cb, vd, NULL); | |
9 | 1577 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), |
1578 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, GTK_SORT_ASCENDING); | |
1579 | |
382 | 1580 g_signal_connect(G_OBJECT(vd->view), "row_activated", |
1581 G_CALLBACK(vdtree_activate_cb), vd); | |
1582 g_signal_connect(G_OBJECT(vd->view), "row_expanded", | |
1583 G_CALLBACK(vdtree_row_expanded), vd); | |
1584 g_signal_connect(G_OBJECT(vd->view), "row_collapsed", | |
1585 G_CALLBACK(vdtree_row_collapsed), vd); | |
9 | 1586 #if 0 |
1587 g_signal_connect(G_OBJECT(store), "row_deleted", | |
382 | 1588 G_CALLBACK(vdtree_row_deleted_cb), vd); |
9 | 1589 #endif |
1590 | |
382 | 1591 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vd->view)); |
9 | 1592 gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); |
382 | 1593 gtk_tree_selection_set_select_function(selection, vdtree_select_cb, vd, NULL); |
9 | 1594 |
1595 column = gtk_tree_view_column_new(); | |
1596 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_GROW_ONLY); | |
1597 | |
1598 renderer = gtk_cell_renderer_pixbuf_new(); | |
1599 gtk_tree_view_column_pack_start(column, renderer, FALSE); | |
1600 gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", DIR_COLUMN_ICON); | |
382 | 1601 gtk_tree_view_column_set_cell_data_func(column, renderer, vdtree_color_cb, vd, NULL); |
9 | 1602 |
1603 renderer = gtk_cell_renderer_text_new(); | |
1604 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
1605 gtk_tree_view_column_add_attribute(column, renderer, "text", DIR_COLUMN_NAME); | |
382 | 1606 gtk_tree_view_column_set_cell_data_func(column, renderer, vdtree_color_cb, vd, NULL); |
9 | 1607 |
382 | 1608 gtk_tree_view_append_column(GTK_TREE_VIEW(vd->view), column); |
9 | 1609 |
382 | 1610 g_signal_connect(G_OBJECT(vd->view), "key_press_event", |
1611 G_CALLBACK(vdtree_press_key_cb), vd); | |
9 | 1612 |
382 | 1613 gtk_container_add(GTK_CONTAINER(vd->widget), vd->view); |
1614 gtk_widget_show(vd->view); | |
9 | 1615 |
382 | 1616 vd->pf = folder_icons_new(); |
9 | 1617 |
382 | 1618 vdtree_setup_root(vd); |
9 | 1619 |
382 | 1620 vdtree_dnd_init(vd); |
9 | 1621 |
382 | 1622 g_signal_connect(G_OBJECT(vd->view), "button_press_event", |
1623 G_CALLBACK(vdtree_press_cb), vd); | |
1624 g_signal_connect(G_OBJECT(vd->view), "button_release_event", | |
1625 G_CALLBACK(vdtree_release_cb), vd); | |
9 | 1626 |
382 | 1627 vdtree_set_path(vd, path); |
9 | 1628 |
382 | 1629 return vd; |
9 | 1630 } |
1631 | |
1632 #if 0 | |
382 | 1633 void vdtree_set_click_func(ViewDir *vd, |
1634 void (*func)(ViewDir *vd, GdkEventButton *event, FileData *fd, gpointer), gpointer data) | |
9 | 1635 { |
1636 if (!td) return; | |
382 | 1637 vd->click_func = func; |
1638 vd->click_data = data; | |
9 | 1639 } |
1640 #endif | |
1641 | |
1642 |