Mercurial > geeqie
annotate src/view_dir_tree.c @ 389:b78077f65eff
Merge few more vdlist/vdtree functions.
author | zas_ |
---|---|
date | Wed, 16 Apr 2008 21:58:05 +0000 |
parents | 5186f8e38cb8 |
children | 4a5e1377f3d7 |
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 | |
46 | |
382 | 47 static gint vdtree_populate_path_by_iter(ViewDir *vd, GtkTreeIter *iter, gint force, const gchar *target_path); |
9 | 48 |
49 | |
50 /* | |
51 *---------------------------------------------------------------------------- | |
52 * utils | |
53 *---------------------------------------------------------------------------- | |
54 */ | |
55 | |
56 static void set_cursor(GtkWidget *widget, GdkCursorType cursor_type) | |
57 { | |
58 GdkCursor *cursor = NULL; | |
59 | |
60 if (!widget || !widget->window) return; | |
61 | |
62 if (cursor_type > -1) cursor = gdk_cursor_new (cursor_type); | |
63 gdk_window_set_cursor (widget->window, cursor); | |
64 if (cursor) gdk_cursor_unref(cursor); | |
65 gdk_flush(); | |
66 } | |
67 | |
382 | 68 static void vdtree_busy_push(ViewDir *vd) |
9 | 69 { |
382 | 70 if (VDTREE_INFO(vd, busy_ref) == 0) set_cursor(vd->view, GDK_WATCH); |
71 VDTREE_INFO(vd, busy_ref)++; | |
9 | 72 } |
73 | |
382 | 74 static void vdtree_busy_pop(ViewDir *vd) |
9 | 75 { |
382 | 76 if (VDTREE_INFO(vd, busy_ref) == 1) set_cursor(vd->view, -1); |
77 if (VDTREE_INFO(vd, busy_ref) > 0) VDTREE_INFO(vd, busy_ref)--; | |
9 | 78 } |
79 | |
383
499d7ba62261
Move some dnd common code from view_dir_list.c and view_dir_tree.c
zas_
parents:
382
diff
changeset
|
80 gint vdtree_find_row(ViewDir *vd, FileData *fd, GtkTreeIter *iter, GtkTreeIter *parent) |
9 | 81 { |
82 GtkTreeModel *store; | |
83 gint valid; | |
84 | |
382 | 85 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vd->view)); |
9 | 86 if (parent) |
87 { | |
88 valid = gtk_tree_model_iter_children(store, iter, parent); | |
89 } | |
90 else | |
91 { | |
92 valid = gtk_tree_model_get_iter_first(store, iter); | |
93 } | |
94 while (valid) | |
95 { | |
96 NodeData *nd; | |
97 GtkTreeIter found; | |
98 | |
99 gtk_tree_model_get(GTK_TREE_MODEL(store), iter, DIR_COLUMN_POINTER, &nd, -1); | |
100 if (nd->fd == fd) return TRUE; | |
101 | |
382 | 102 if (vdtree_find_row(vd, fd, &found, iter)) |
9 | 103 { |
104 memcpy(iter, &found, sizeof(found)); | |
105 return TRUE; | |
106 } | |
107 | |
108 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), iter); | |
109 } | |
110 | |
111 return FALSE; | |
112 } | |
113 | |
382 | 114 static void vdtree_icon_set_by_iter(ViewDir *vd, GtkTreeIter *iter, GdkPixbuf *pixbuf) |
9 | 115 { |
116 GtkTreeModel *store; | |
117 GdkPixbuf *old; | |
118 | |
382 | 119 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vd->view)); |
9 | 120 gtk_tree_model_get(store, iter, DIR_COLUMN_ICON, &old, -1); |
382 | 121 if (old != vd->pf->deny) |
9 | 122 { |
123 gtk_tree_store_set(GTK_TREE_STORE(store), iter, DIR_COLUMN_ICON, pixbuf, -1); | |
124 } | |
125 } | |
126 | |
382 | 127 static void vdtree_expand_by_iter(ViewDir *vd, GtkTreeIter *iter, gint expand) |
9 | 128 { |
129 GtkTreeModel *store; | |
130 GtkTreePath *tpath; | |
131 | |
382 | 132 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vd->view)); |
9 | 133 tpath = gtk_tree_model_get_path(store, iter); |
134 if (expand) | |
135 { | |
382 | 136 gtk_tree_view_expand_row(GTK_TREE_VIEW(vd->view), tpath, FALSE); |
137 vdtree_icon_set_by_iter(vd, iter, vd->pf->open); | |
9 | 138 } |
139 else | |
140 { | |
382 | 141 gtk_tree_view_collapse_row(GTK_TREE_VIEW(vd->view), tpath); |
9 | 142 } |
143 gtk_tree_path_free(tpath); | |
144 } | |
145 | |
382 | 146 static void vdtree_expand_by_data(ViewDir *vd, FileData *fd, gint expand) |
9 | 147 { |
148 GtkTreeIter iter; | |
149 | |
389 | 150 if (vd_find_row(vd, fd, &iter)) |
9 | 151 { |
382 | 152 vdtree_expand_by_iter(vd, &iter, expand); |
9 | 153 } |
154 } | |
155 | |
156 static void vdtree_node_free(NodeData *nd) | |
157 { | |
158 if (!nd) return; | |
159 | |
138 | 160 file_data_unref(nd->fd); |
9 | 161 g_free(nd); |
162 } | |
163 | |
164 /* | |
165 *---------------------------------------------------------------------------- | |
166 * dnd | |
167 *---------------------------------------------------------------------------- | |
168 */ | |
169 | |
170 static GtkTargetEntry vdtree_dnd_drop_types[] = { | |
171 { "text/uri-list", 0, TARGET_URI_LIST } | |
172 }; | |
173 static gint vdtree_dnd_drop_types_count = 1; | |
174 | |
175 | |
382 | 176 static void vdtree_dest_set(ViewDir *vd, gint enable) |
9 | 177 { |
178 if (enable) | |
179 { | |
382 | 180 gtk_drag_dest_set(vd->view, |
9 | 181 GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP, |
182 vdtree_dnd_drop_types, vdtree_dnd_drop_types_count, | |
183 GDK_ACTION_MOVE | GDK_ACTION_COPY); | |
184 } | |
185 else | |
186 { | |
382 | 187 gtk_drag_dest_unset(vd->view); |
9 | 188 } |
189 } | |
190 | |
191 static void vdtree_dnd_get(GtkWidget *widget, GdkDragContext *context, | |
192 GtkSelectionData *selection_data, guint info, | |
193 guint time, gpointer data) | |
194 { | |
382 | 195 ViewDir *vd = data; |
9 | 196 GList *list; |
197 gchar *uri_text = NULL; | |
198 gint length = 0; | |
199 | |
382 | 200 if (!vd->click_fd) return; |
9 | 201 |
202 switch (info) | |
203 { | |
204 case TARGET_URI_LIST: | |
205 case TARGET_TEXT_PLAIN: | |
382 | 206 list = g_list_prepend(NULL, vd->click_fd); |
138 | 207 uri_text = uri_text_from_filelist(list, &length, (info == TARGET_TEXT_PLAIN)); |
9 | 208 g_list_free(list); |
209 break; | |
210 } | |
211 | |
212 if (uri_text) | |
213 { | |
214 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
|
215 8, (guchar *)uri_text, length); |
9 | 216 g_free(uri_text); |
217 } | |
218 } | |
219 | |
220 static void vdtree_dnd_begin(GtkWidget *widget, GdkDragContext *context, gpointer data) | |
221 { | |
382 | 222 ViewDir *vd = data; |
9 | 223 |
383
499d7ba62261
Move some dnd common code from view_dir_list.c and view_dir_tree.c
zas_
parents:
382
diff
changeset
|
224 vd_color_set(vd, vd->click_fd, TRUE); |
382 | 225 vdtree_dest_set(vd, FALSE); |
9 | 226 } |
227 | |
228 static void vdtree_dnd_end(GtkWidget *widget, GdkDragContext *context, gpointer data) | |
229 { | |
382 | 230 ViewDir *vd = data; |
9 | 231 |
383
499d7ba62261
Move some dnd common code from view_dir_list.c and view_dir_tree.c
zas_
parents:
382
diff
changeset
|
232 vd_color_set(vd, vd->click_fd, FALSE); |
382 | 233 vdtree_dest_set(vd, TRUE); |
9 | 234 } |
235 | |
236 static void vdtree_dnd_drop_receive(GtkWidget *widget, | |
237 GdkDragContext *context, gint x, gint y, | |
238 GtkSelectionData *selection_data, guint info, | |
239 guint time, gpointer data) | |
240 { | |
382 | 241 ViewDir *vd = data; |
9 | 242 GtkTreePath *tpath; |
243 GtkTreeIter iter; | |
244 FileData *fd = NULL; | |
245 | |
382 | 246 vd->click_fd = NULL; |
9 | 247 |
248 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), x, y, | |
249 &tpath, NULL, NULL, NULL)) | |
250 { | |
251 GtkTreeModel *store; | |
252 NodeData *nd; | |
253 | |
254 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget)); | |
255 gtk_tree_model_get_iter(store, &iter, tpath); | |
256 gtk_tree_model_get(store, &iter, DIR_COLUMN_POINTER, &nd, -1); | |
257 gtk_tree_path_free(tpath); | |
258 | |
259 fd = (nd) ? nd->fd : NULL; | |
260 } | |
261 | |
262 if (!fd) return; | |
263 | |
264 if (info == TARGET_URI_LIST) | |
265 { | |
266 GList *list; | |
267 gint active; | |
268 | |
138 | 269 list = uri_filelist_from_text((gchar *)selection_data->data, TRUE); |
9 | 270 if (!list) return; |
271 | |
272 active = access_file(fd->path, W_OK | X_OK); | |
273 | |
383
499d7ba62261
Move some dnd common code from view_dir_list.c and view_dir_tree.c
zas_
parents:
382
diff
changeset
|
274 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
|
275 vd->popup = vd_drop_menu(vd, active); |
382 | 276 gtk_menu_popup(GTK_MENU(vd->popup), NULL, NULL, NULL, NULL, 0, time); |
9 | 277 |
382 | 278 vd->drop_fd = fd; |
279 vd->drop_list = list; | |
9 | 280 } |
281 } | |
282 | |
283 static gint vdtree_dnd_drop_expand_cb(gpointer data) | |
284 { | |
382 | 285 ViewDir *vd = data; |
9 | 286 GtkTreeIter iter; |
287 | |
382 | 288 if (vd->drop_fd && |
389 | 289 vd_find_row(vd, vd->drop_fd, &iter)) |
9 | 290 { |
382 | 291 vdtree_populate_path_by_iter(vd, &iter, FALSE, vd->path); |
292 vdtree_expand_by_data(vd, vd->drop_fd, TRUE); | |
9 | 293 } |
294 | |
382 | 295 VDTREE_INFO(vd, drop_expand_id) = -1; |
9 | 296 return FALSE; |
297 } | |
298 | |
382 | 299 static void vdtree_dnd_drop_expand_cancel(ViewDir *vd) |
9 | 300 { |
382 | 301 if (VDTREE_INFO(vd, drop_expand_id) != -1) g_source_remove(VDTREE_INFO(vd, drop_expand_id)); |
302 VDTREE_INFO(vd, drop_expand_id) = -1; | |
9 | 303 } |
304 | |
382 | 305 static void vdtree_dnd_drop_expand(ViewDir *vd) |
9 | 306 { |
382 | 307 vdtree_dnd_drop_expand_cancel(vd); |
308 VDTREE_INFO(vd, drop_expand_id) = g_timeout_add(1000, vdtree_dnd_drop_expand_cb, vd); | |
9 | 309 } |
310 | |
382 | 311 static void vdtree_drop_update(ViewDir *vd, gint x, gint y) |
9 | 312 { |
313 GtkTreePath *tpath; | |
314 GtkTreeIter iter; | |
315 FileData *fd = NULL; | |
316 | |
382 | 317 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(vd->view), x, y, |
9 | 318 &tpath, NULL, NULL, NULL)) |
319 { | |
320 GtkTreeModel *store; | |
321 NodeData *nd; | |
322 | |
382 | 323 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vd->view)); |
9 | 324 gtk_tree_model_get_iter(store, &iter, tpath); |
325 gtk_tree_model_get(store, &iter, DIR_COLUMN_POINTER, &nd, -1); | |
326 gtk_tree_path_free(tpath); | |
327 | |
328 fd = (nd) ? nd->fd : NULL; | |
329 } | |
330 | |
382 | 331 if (fd != vd->drop_fd) |
9 | 332 { |
383
499d7ba62261
Move some dnd common code from view_dir_list.c and view_dir_tree.c
zas_
parents:
382
diff
changeset
|
333 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
|
334 vd_color_set(vd, fd, TRUE); |
382 | 335 if (fd) vdtree_dnd_drop_expand(vd); |
9 | 336 } |
337 | |
382 | 338 vd->drop_fd = fd; |
9 | 339 } |
340 | |
382 | 341 static void vdtree_dnd_drop_scroll_cancel(ViewDir *vd) |
9 | 342 { |
382 | 343 if (vd->drop_scroll_id != -1) g_source_remove(vd->drop_scroll_id); |
344 vd->drop_scroll_id = -1; | |
9 | 345 } |
346 | |
347 static gint vdtree_auto_scroll_idle_cb(gpointer data) | |
348 { | |
382 | 349 ViewDir *vd = data; |
9 | 350 |
382 | 351 if (vd->drop_fd) |
9 | 352 { |
353 GdkWindow *window; | |
354 gint x, y; | |
355 gint w, h; | |
356 | |
382 | 357 window = vd->view->window; |
9 | 358 gdk_window_get_pointer(window, &x, &y, NULL); |
359 gdk_drawable_get_size(window, &w, &h); | |
360 if (x >= 0 && x < w && y >= 0 && y < h) | |
361 { | |
382 | 362 vdtree_drop_update(vd, x, y); |
9 | 363 } |
364 } | |
365 | |
382 | 366 vd->drop_scroll_id = -1; |
9 | 367 return FALSE; |
368 } | |
369 | |
370 static gint vdtree_auto_scroll_notify_cb(GtkWidget *widget, gint x, gint y, gpointer data) | |
371 { | |
382 | 372 ViewDir *vd = data; |
9 | 373 |
382 | 374 if (!vd->drop_fd || vd->drop_list) return FALSE; |
9 | 375 |
382 | 376 if (vd->drop_scroll_id == -1) vd->drop_scroll_id = g_idle_add(vdtree_auto_scroll_idle_cb, vd); |
9 | 377 |
378 return TRUE; | |
379 } | |
380 | |
381 static gint vdtree_dnd_drop_motion(GtkWidget *widget, GdkDragContext *context, | |
382 gint x, gint y, guint time, gpointer data) | |
383 { | |
382 | 384 ViewDir *vd = data; |
9 | 385 |
382 | 386 vd->click_fd = NULL; |
9 | 387 |
382 | 388 if (gtk_drag_get_source_widget(context) == vd->view) |
9 | 389 { |
390 gdk_drag_status(context, 0, time); | |
391 return TRUE; | |
392 } | |
393 else | |
394 { | |
395 gdk_drag_status(context, context->suggested_action, time); | |
396 } | |
397 | |
382 | 398 vdtree_drop_update(vd, x, y); |
9 | 399 |
382 | 400 if (vd->drop_fd) |
9 | 401 { |
382 | 402 GtkAdjustment *adj = gtk_tree_view_get_vadjustment(GTK_TREE_VIEW(vd->view)); |
403 widget_auto_scroll_start(vd->view, adj, -1, -1, vdtree_auto_scroll_notify_cb, vd); | |
9 | 404 } |
405 | |
406 return FALSE; | |
407 } | |
408 | |
409 static void vdtree_dnd_drop_leave(GtkWidget *widget, GdkDragContext *context, guint time, gpointer data) | |
410 { | |
382 | 411 ViewDir *vd = data; |
9 | 412 |
383
499d7ba62261
Move some dnd common code from view_dir_list.c and view_dir_tree.c
zas_
parents:
382
diff
changeset
|
413 if (vd->drop_fd != vd->click_fd) vd_color_set(vd, vd->drop_fd, FALSE); |
9 | 414 |
382 | 415 vd->drop_fd = NULL; |
9 | 416 |
382 | 417 vdtree_dnd_drop_expand_cancel(vd); |
9 | 418 } |
419 | |
382 | 420 static void vdtree_dnd_init(ViewDir *vd) |
9 | 421 { |
382 | 422 gtk_drag_source_set(vd->view, GDK_BUTTON1_MASK | GDK_BUTTON2_MASK, |
9 | 423 dnd_file_drag_types, dnd_file_drag_types_count, |
424 GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_ASK); | |
382 | 425 g_signal_connect(G_OBJECT(vd->view), "drag_data_get", |
426 G_CALLBACK(vdtree_dnd_get), vd); | |
427 g_signal_connect(G_OBJECT(vd->view), "drag_begin", | |
428 G_CALLBACK(vdtree_dnd_begin), vd); | |
429 g_signal_connect(G_OBJECT(vd->view), "drag_end", | |
430 G_CALLBACK(vdtree_dnd_end), vd); | |
9 | 431 |
382 | 432 vdtree_dest_set(vd, TRUE); |
433 g_signal_connect(G_OBJECT(vd->view), "drag_data_received", | |
434 G_CALLBACK(vdtree_dnd_drop_receive), vd); | |
435 g_signal_connect(G_OBJECT(vd->view), "drag_motion", | |
436 G_CALLBACK(vdtree_dnd_drop_motion), vd); | |
437 g_signal_connect(G_OBJECT(vd->view), "drag_leave", | |
438 G_CALLBACK(vdtree_dnd_drop_leave), vd); | |
9 | 439 } |
440 | |
441 /* | |
442 *---------------------------------------------------------------------------- | |
443 * parts lists | |
444 *---------------------------------------------------------------------------- | |
445 */ | |
446 | |
447 static GList *parts_list(const gchar *path) | |
448 { | |
449 GList *list = NULL; | |
450 const gchar *strb, *strp; | |
451 gint l; | |
452 | |
453 strp = path; | |
454 | |
455 if (*strp != '/') return NULL; | |
456 | |
457 strp++; | |
458 strb = strp; | |
459 l = 0; | |
460 | |
461 while (*strp != '\0') | |
462 { | |
463 if (*strp == '/') | |
464 { | |
465 if (l > 0) list = g_list_prepend(list, g_strndup(strb, l)); | |
466 strp++; | |
467 strb = strp; | |
468 l = 0; | |
469 } | |
470 else | |
471 { | |
472 strp++; | |
473 l++; | |
474 } | |
475 } | |
476 if (l > 0) list = g_list_prepend(list, g_strndup(strb, l)); | |
477 | |
478 list = g_list_reverse(list); | |
479 | |
480 list = g_list_prepend(list, g_strdup("/")); | |
481 | |
482 return list; | |
483 } | |
484 | |
485 static void parts_list_free(GList *list) | |
486 { | |
487 GList *work = list; | |
488 while (work) | |
489 { | |
490 PathData *pd = work->data; | |
491 g_free(pd->name); | |
492 g_free(pd); | |
493 work = work->next; | |
494 } | |
495 | |
496 g_list_free(list); | |
497 } | |
498 | |
382 | 499 static GList *parts_list_add_node_points(ViewDir *vd, GList *list) |
9 | 500 { |
501 GList *work; | |
502 GtkTreeModel *store; | |
503 GtkTreeIter iter; | |
504 gint valid; | |
505 | |
382 | 506 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vd->view)); |
9 | 507 valid = gtk_tree_model_get_iter_first(store, &iter); |
508 | |
509 work = list; | |
510 while (work) | |
511 { | |
512 PathData *pd; | |
513 FileData *fd = NULL; | |
514 | |
515 pd = g_new0(PathData, 1); | |
516 pd->name = work->data; | |
517 | |
518 while (valid && !fd) | |
519 { | |
520 NodeData *nd; | |
521 | |
522 gtk_tree_model_get(store, &iter, DIR_COLUMN_POINTER, &nd, -1); | |
523 if (strcmp(nd->fd->name, pd->name) == 0) | |
524 { | |
525 fd = nd->fd; | |
526 } | |
527 else | |
528 { | |
529 valid = gtk_tree_model_iter_next(store, &iter); | |
530 } | |
531 } | |
532 | |
533 pd->node = fd; | |
534 work->data = pd; | |
535 | |
536 if (fd) | |
537 { | |
538 GtkTreeIter parent; | |
539 memcpy(&parent, &iter, sizeof(parent)); | |
540 valid = gtk_tree_model_iter_children(store, &iter, &parent); | |
541 } | |
542 | |
543 work = work->next; | |
544 } | |
545 | |
546 return list; | |
547 } | |
548 | |
549 /* | |
550 *---------------------------------------------------------------------------- | |
551 * misc | |
552 *---------------------------------------------------------------------------- | |
553 */ | |
554 | |
555 #if 0 | |
556 static void vdtree_row_deleted_cb(GtkTreeModel *tree_model, GtkTreePath *tpath, gpointer data) | |
557 { | |
558 GtkTreeIter iter; | |
559 NodeData *nd; | |
560 | |
561 gtk_tree_model_get_iter(tree_model, &iter, tpath); | |
562 gtk_tree_model_get(tree_model, &iter, DIR_COLUMN_POINTER, &nd, -1); | |
563 | |
564 if (!nd) return; | |
565 | |
138 | 566 file_data_unref(nd->fd); |
9 | 567 g_free(nd); |
568 } | |
569 #endif | |
570 | |
571 /* | |
572 *---------------------------------------------------------------------------- | |
573 * node traversal, management | |
574 *---------------------------------------------------------------------------- | |
575 */ | |
576 | |
382 | 577 static gint vdtree_find_iter_by_data(ViewDir *vd, GtkTreeIter *parent, NodeData *nd, GtkTreeIter *iter) |
9 | 578 { |
579 GtkTreeModel *store; | |
580 | |
382 | 581 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vd->view)); |
9 | 582 if (!nd || !gtk_tree_model_iter_children(store, iter, parent)) return -1; |
583 do { | |
584 NodeData *cnd; | |
585 | |
586 gtk_tree_model_get(store, iter, DIR_COLUMN_POINTER, &cnd, -1); | |
587 if (cnd == nd) return TRUE; | |
588 } while (gtk_tree_model_iter_next(store, iter)); | |
589 | |
590 return FALSE; | |
591 } | |
592 | |
382 | 593 static NodeData *vdtree_find_iter_by_name(ViewDir *vd, GtkTreeIter *parent, const gchar *name, GtkTreeIter *iter) |
9 | 594 { |
595 GtkTreeModel *store; | |
596 | |
382 | 597 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vd->view)); |
9 | 598 if (!name || !gtk_tree_model_iter_children(store, iter, parent)) return NULL; |
599 do { | |
600 NodeData *nd; | |
601 | |
602 gtk_tree_model_get(store, iter, DIR_COLUMN_POINTER, &nd, -1); | |
603 if (nd && strcmp(nd->fd->name, name) == 0) return nd; | |
604 } while (gtk_tree_model_iter_next(store, iter)); | |
605 | |
606 return NULL; | |
607 } | |
608 | |
382 | 609 static void vdtree_add_by_data(ViewDir *vd, FileData *fd, GtkTreeIter *parent) |
9 | 610 { |
611 GtkTreeStore *store; | |
612 GtkTreeIter child; | |
613 NodeData *nd; | |
614 GdkPixbuf *pixbuf; | |
615 NodeData *end; | |
616 GtkTreeIter empty; | |
617 | |
618 if (!fd) return; | |
619 | |
620 if (access_file(fd->path, R_OK | X_OK)) | |
621 { | |
382 | 622 pixbuf = vd->pf->close; |
9 | 623 } |
624 else | |
625 { | |
382 | 626 pixbuf = vd->pf->deny; |
9 | 627 } |
628 | |
629 nd = g_new0(NodeData, 1); | |
630 nd->fd = fd; | |
631 nd->expanded = FALSE; | |
632 nd->last_update = time(NULL); | |
633 | |
382 | 634 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vd->view))); |
9 | 635 gtk_tree_store_append(store, &child, parent); |
636 gtk_tree_store_set(store, &child, DIR_COLUMN_POINTER, nd, | |
637 DIR_COLUMN_ICON, pixbuf, | |
638 DIR_COLUMN_NAME, nd->fd->name, | |
639 DIR_COLUMN_COLOR, FALSE, -1); | |
640 | |
641 /* all nodes are created with an "empty" node, so that the expander is shown | |
642 * this is removed when the child is populated */ | |
643 end = g_new0(NodeData, 1); | |
138 | 644 end->fd = file_data_new_simple(""); |
9 | 645 end->expanded = TRUE; |
646 | |
647 gtk_tree_store_append(store, &empty, &child); | |
648 gtk_tree_store_set(store, &empty, DIR_COLUMN_POINTER, end, | |
649 DIR_COLUMN_NAME, "empty", -1); | |
650 | |
651 if (parent) | |
652 { | |
653 NodeData *pnd; | |
654 GtkTreePath *tpath; | |
655 | |
656 gtk_tree_model_get(GTK_TREE_MODEL(store), parent, DIR_COLUMN_POINTER, &pnd, -1); | |
657 tpath = gtk_tree_model_get_path(GTK_TREE_MODEL(store), parent); | |
320 | 658 if (options->tree_descend_subdirs && |
382 | 659 gtk_tree_view_row_expanded(GTK_TREE_VIEW(vd->view), tpath) && |
9 | 660 !nd->expanded) |
661 { | |
382 | 662 vdtree_populate_path_by_iter(vd, &child, FALSE, vd->path); |
9 | 663 } |
664 gtk_tree_path_free(tpath); | |
665 } | |
666 } | |
667 | |
382 | 668 static gint vdtree_populate_path_by_iter(ViewDir *vd, GtkTreeIter *iter, gint force, const gchar *target_path) |
9 | 669 { |
670 GtkTreeModel *store; | |
671 GList *list; | |
672 GList *work; | |
673 GList *old; | |
674 time_t current_time; | |
675 GtkTreeIter child; | |
676 NodeData *nd; | |
677 | |
382 | 678 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vd->view)); |
9 | 679 gtk_tree_model_get(store, iter, DIR_COLUMN_POINTER, &nd, -1); |
680 | |
681 if (!nd) return FALSE; | |
682 | |
683 current_time = time(NULL); | |
684 | |
685 if (nd->expanded) | |
686 { | |
687 if (!force && current_time - nd->last_update < 10) return TRUE; | |
688 if (!isdir(nd->fd->path)) | |
689 { | |
382 | 690 if (vd->click_fd == nd->fd) vd->click_fd = NULL; |
691 if (vd->drop_fd == nd->fd) vd->drop_fd = NULL; | |
9 | 692 gtk_tree_store_remove(GTK_TREE_STORE(store), iter); |
693 vdtree_node_free(nd); | |
694 return FALSE; | |
695 } | |
696 if (!force && filetime(nd->fd->path) == nd->fd->date) return TRUE; | |
697 } | |
698 | |
382 | 699 vdtree_busy_push(vd); |
9 | 700 |
701 list = NULL; | |
702 filelist_read(nd->fd->path, NULL, &list); | |
703 | |
704 /* when hidden files are not enabled, and the user enters a hidden path, | |
705 * allow the tree to display that path by specifically inserting the hidden entries | |
706 */ | |
356 | 707 if (!options->file_filter.show_hidden_files && |
9 | 708 target_path && |
709 strncmp(nd->fd->path, target_path, strlen(nd->fd->path)) == 0) | |
710 { | |
711 gint n; | |
712 | |
713 n = strlen(nd->fd->path); | |
714 if (target_path[n] == '/' && target_path[n+1] == '.') | |
715 { | |
716 gchar *name8; | |
717 struct stat sbuf; | |
718 | |
719 n++; | |
720 | |
721 while (target_path[n] != '\0' && target_path[n] != '/') n++; | |
722 name8 = g_strndup(target_path, n); | |
723 | |
724 if (stat_utf8(name8, &sbuf)) | |
725 { | |
145
8be2cc687304
fixed grouping sidecar files and made it configurable via config file
nadvornik
parents:
138
diff
changeset
|
726 list = g_list_prepend(list, file_data_new_simple(name8)); |
9 | 727 } |
728 | |
729 g_free(name8); | |
730 } | |
731 } | |
732 | |
733 old = NULL; | |
734 if (gtk_tree_model_iter_children(store, &child, iter)) | |
735 { | |
736 do { | |
737 NodeData *cnd; | |
738 | |
739 gtk_tree_model_get(store, &child, DIR_COLUMN_POINTER, &cnd, -1); | |
740 old = g_list_prepend(old, cnd); | |
741 } while (gtk_tree_model_iter_next(store, &child)); | |
742 } | |
743 | |
744 work = list; | |
745 while (work) | |
746 { | |
747 FileData *fd; | |
748 | |
749 fd = work->data; | |
750 work = work->next; | |
751 | |
752 if (strcmp(fd->name, ".") == 0 || strcmp(fd->name, "..") == 0) | |
753 { | |
138 | 754 file_data_unref(fd); |
9 | 755 } |
756 else | |
757 { | |
758 NodeData *cnd; | |
759 | |
382 | 760 cnd = vdtree_find_iter_by_name(vd, iter, fd->name, &child); |
9 | 761 if (cnd) |
762 { | |
763 old = g_list_remove(old, cnd); | |
764 if (cnd->expanded && cnd->fd->date != fd->date && | |
382 | 765 vdtree_populate_path_by_iter(vd, &child, FALSE, target_path)) |
9 | 766 { |
767 cnd->fd->size = fd->size; | |
768 cnd->fd->date = fd->date; | |
769 } | |
770 | |
138 | 771 file_data_unref(fd); |
9 | 772 } |
773 else | |
774 { | |
382 | 775 vdtree_add_by_data(vd, fd, iter); |
9 | 776 } |
777 } | |
778 } | |
779 | |
780 work = old; | |
781 while (work) | |
782 { | |
783 NodeData *cnd = work->data; | |
784 work = work->next; | |
785 | |
382 | 786 if (vd->click_fd == cnd->fd) vd->click_fd = NULL; |
787 if (vd->drop_fd == cnd->fd) vd->drop_fd = NULL; | |
9 | 788 |
382 | 789 if (vdtree_find_iter_by_data(vd, iter, cnd, &child)) |
9 | 790 { |
791 gtk_tree_store_remove(GTK_TREE_STORE(store), &child); | |
792 vdtree_node_free(cnd); | |
793 } | |
794 } | |
795 | |
796 g_list_free(old); | |
797 g_list_free(list); | |
798 | |
382 | 799 vdtree_busy_pop(vd); |
9 | 800 |
801 nd->expanded = TRUE; | |
802 nd->last_update = current_time; | |
803 | |
804 return TRUE; | |
805 } | |
806 | |
388
5186f8e38cb8
Make directory view popup menu common and move it to view_dir.{c,h}.
zas_
parents:
384
diff
changeset
|
807 FileData *vdtree_populate_path(ViewDir *vd, const gchar *path, gint expand, gint force) |
9 | 808 { |
809 GList *list; | |
810 GList *work; | |
811 FileData *fd = NULL; | |
812 | |
813 if (!path) return NULL; | |
814 | |
382 | 815 vdtree_busy_push(vd); |
9 | 816 |
817 list = parts_list(path); | |
382 | 818 list = parts_list_add_node_points(vd, list); |
9 | 819 |
820 work = list; | |
821 while (work) | |
822 { | |
823 PathData *pd = work->data; | |
824 if (pd->node == NULL) | |
825 { | |
826 PathData *parent_pd; | |
827 GtkTreeIter parent_iter; | |
828 GtkTreeIter iter; | |
829 NodeData *nd; | |
830 | |
831 if (work == list) | |
832 { | |
833 /* should not happen */ | |
834 printf("vdtree warning, root node not found\n"); | |
835 parts_list_free(list); | |
382 | 836 vdtree_busy_pop(vd); |
9 | 837 return NULL; |
838 } | |
839 | |
840 parent_pd = work->prev->data; | |
841 | |
389 | 842 if (!vd_find_row(vd, parent_pd->node, &parent_iter) || |
382 | 843 !vdtree_populate_path_by_iter(vd, &parent_iter, force, path) || |
844 (nd = vdtree_find_iter_by_name(vd, &parent_iter, pd->name, &iter)) == NULL) | |
9 | 845 { |
846 printf("vdtree warning, aborted at %s\n", parent_pd->name); | |
847 parts_list_free(list); | |
382 | 848 vdtree_busy_pop(vd); |
9 | 849 return NULL; |
850 } | |
851 | |
852 pd->node = nd->fd; | |
853 | |
854 if (pd->node) | |
855 { | |
856 if (expand) | |
857 { | |
382 | 858 vdtree_expand_by_iter(vd, &parent_iter, TRUE); |
859 vdtree_expand_by_iter(vd, &iter, TRUE); | |
9 | 860 } |
382 | 861 vdtree_populate_path_by_iter(vd, &iter, force, path); |
9 | 862 } |
863 } | |
864 else | |
865 { | |
866 GtkTreeIter iter; | |
867 | |
389 | 868 if (vd_find_row(vd, pd->node, &iter)) |
9 | 869 { |
382 | 870 if (expand) vdtree_expand_by_iter(vd, &iter, TRUE); |
871 vdtree_populate_path_by_iter(vd, &iter, force, path); | |
9 | 872 } |
873 } | |
874 | |
875 work = work->next; | |
876 } | |
877 | |
878 work = g_list_last(list); | |
879 if (work) | |
880 { | |
881 PathData *pd = work->data; | |
882 fd = pd->node; | |
883 } | |
884 parts_list_free(list); | |
885 | |
382 | 886 vdtree_busy_pop(vd); |
9 | 887 |
888 return fd; | |
889 } | |
890 | |
891 /* | |
892 *---------------------------------------------------------------------------- | |
893 * access | |
894 *---------------------------------------------------------------------------- | |
895 */ | |
896 | |
897 static gint selection_is_ok = FALSE; | |
898 | |
899 static gboolean vdtree_select_cb(GtkTreeSelection *selection, GtkTreeModel *store, GtkTreePath *tpath, | |
900 gboolean path_currently_selected, gpointer data) | |
901 { | |
902 return selection_is_ok; | |
903 } | |
904 | |
382 | 905 static void vdtree_select_row(ViewDir *vd, FileData *fd) |
9 | 906 { |
907 GtkTreeSelection *selection; | |
908 GtkTreeIter iter; | |
909 | |
389 | 910 if (!vd_find_row(vd, fd, &iter)) return; |
382 | 911 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vd->view)); |
9 | 912 |
913 /* hack, such that selection is only allowed to be changed from here */ | |
914 selection_is_ok = TRUE; | |
915 gtk_tree_selection_select_iter(selection, &iter); | |
916 selection_is_ok = FALSE; | |
917 | |
382 | 918 if (!vdtree_populate_path_by_iter(vd, &iter, FALSE, vd->path)) return; |
9 | 919 |
382 | 920 vdtree_expand_by_iter(vd, &iter, TRUE); |
9 | 921 |
382 | 922 if (fd && vd->select_func) |
9 | 923 { |
382 | 924 vd->select_func(vd, fd->path, vd->select_data); |
9 | 925 } |
926 } | |
927 | |
382 | 928 gint vdtree_set_path(ViewDir *vd, const gchar *path) |
9 | 929 { |
930 FileData *fd; | |
931 GtkTreeIter iter; | |
932 | |
933 if (!path) return FALSE; | |
382 | 934 if (vd->path && strcmp(path, vd->path) == 0) return TRUE; |
9 | 935 |
382 | 936 g_free(vd->path); |
937 vd->path = g_strdup(path); | |
9 | 938 |
382 | 939 fd = vdtree_populate_path(vd, vd->path, TRUE, FALSE); |
9 | 940 |
941 if (!fd) return FALSE; | |
942 | |
389 | 943 if (vd_find_row(vd, fd, &iter)) |
9 | 944 { |
945 GtkTreeModel *store; | |
946 GtkTreePath *tpath; | |
947 | |
382 | 948 tree_view_row_make_visible(GTK_TREE_VIEW(vd->view), &iter, TRUE); |
9 | 949 |
382 | 950 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vd->view)); |
9 | 951 tpath = gtk_tree_model_get_path(store, &iter); |
382 | 952 gtk_tree_view_set_cursor(GTK_TREE_VIEW(vd->view), tpath, NULL, FALSE); |
9 | 953 gtk_tree_path_free(tpath); |
954 | |
382 | 955 vdtree_select_row(vd, fd); |
9 | 956 } |
957 | |
958 return TRUE; | |
959 } | |
960 | |
961 #if 0 | |
382 | 962 const gchar *vdtree_get_path(ViewDir *vd) |
9 | 963 { |
382 | 964 return vd->path; |
9 | 965 } |
966 #endif | |
967 | |
382 | 968 void vdtree_refresh(ViewDir *vd) |
9 | 969 { |
382 | 970 vdtree_populate_path(vd, vd->path, FALSE, TRUE); |
9 | 971 } |
972 | |
382 | 973 const gchar *vdtree_row_get_path(ViewDir *vd, gint row) |
9 | 974 { |
975 printf("FIXME: no get row path\n"); | |
976 return NULL; | |
977 } | |
978 | |
979 /* | |
980 *---------------------------------------------------------------------------- | |
981 * callbacks | |
982 *---------------------------------------------------------------------------- | |
983 */ | |
984 | |
985 static void vdtree_menu_position_cb(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer data) | |
986 { | |
382 | 987 ViewDir *vd = data; |
9 | 988 GtkTreeModel *store; |
989 GtkTreeIter iter; | |
990 GtkTreePath *tpath; | |
991 gint cw, ch; | |
992 | |
389 | 993 if (vd_find_row(vd, vd->click_fd, &iter) < 0) return; |
382 | 994 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vd->view)); |
9 | 995 tpath = gtk_tree_model_get_path(store, &iter); |
382 | 996 tree_view_get_cell_clamped(GTK_TREE_VIEW(vd->view), tpath, 0, TRUE, x, y, &cw, &ch); |
9 | 997 gtk_tree_path_free(tpath); |
998 *y += ch; | |
999 popup_menu_position_clamp(menu, x, y, 0); | |
1000 } | |
1001 | |
1002 static gint vdtree_press_key_cb(GtkWidget *widget, GdkEventKey *event, gpointer data) | |
1003 { | |
382 | 1004 ViewDir *vd = data; |
9 | 1005 GtkTreePath *tpath; |
1006 GtkTreeIter iter; | |
1007 FileData *fd = NULL; | |
1008 | |
382 | 1009 gtk_tree_view_get_cursor(GTK_TREE_VIEW(vd->view), &tpath, NULL); |
9 | 1010 if (tpath) |
1011 { | |
1012 GtkTreeModel *store; | |
1013 NodeData *nd; | |
1014 | |
1015 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget)); | |
1016 gtk_tree_model_get_iter(store, &iter, tpath); | |
1017 gtk_tree_model_get(store, &iter, DIR_COLUMN_POINTER, &nd, -1); | |
1018 | |
1019 gtk_tree_path_free(tpath); | |
1020 | |
1021 fd = (nd) ? nd->fd : NULL; | |
1022 } | |
1023 | |
1024 switch (event->keyval) | |
1025 { | |
1026 case GDK_Menu: | |
382 | 1027 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
|
1028 vd_color_set(vd, vd->click_fd, TRUE); |
9 | 1029 |
388
5186f8e38cb8
Make directory view popup menu common and move it to view_dir.{c,h}.
zas_
parents:
384
diff
changeset
|
1030 vd->popup = vd_pop_menu(vd, vd->click_fd); |
382 | 1031 gtk_menu_popup(GTK_MENU(vd->popup), NULL, NULL, vdtree_menu_position_cb, vd, 0, GDK_CURRENT_TIME); |
9 | 1032 |
1033 return TRUE; | |
1034 break; | |
1035 case GDK_plus: | |
1036 case GDK_Right: | |
1037 case GDK_KP_Add: | |
1038 if (fd) | |
1039 { | |
382 | 1040 vdtree_populate_path_by_iter(vd, &iter, FALSE, vd->path); |
1041 vdtree_icon_set_by_iter(vd, &iter, vd->pf->open); | |
9 | 1042 } |
1043 break; | |
1044 } | |
1045 | |
1046 return FALSE; | |
1047 } | |
1048 | |
1049 static gint vdtree_clicked_on_expander(GtkTreeView *treeview, GtkTreePath *tpath, | |
1050 GtkTreeViewColumn *column, gint x, gint y, gint *left_of_expander) | |
1051 { | |
1052 gint depth; | |
1053 gint size; | |
1054 gint sep; | |
1055 gint exp_width; | |
1056 | |
1057 if (column != gtk_tree_view_get_expander_column(treeview)) return FALSE; | |
1058 | |
1059 gtk_widget_style_get(GTK_WIDGET(treeview), "expander-size", &size, "horizontal-separator", &sep, NULL); | |
1060 depth = gtk_tree_path_get_depth(tpath); | |
1061 | |
1062 exp_width = sep + size + sep; | |
1063 | |
1064 if (x <= depth * exp_width) | |
1065 { | |
1066 if (left_of_expander) *left_of_expander = !(x >= (depth - 1) * exp_width); | |
1067 return TRUE; | |
1068 } | |
1069 | |
1070 return FALSE; | |
1071 } | |
1072 | |
1073 static gint vdtree_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data) | |
1074 { | |
382 | 1075 ViewDir *vd = data; |
9 | 1076 GtkTreePath *tpath; |
1077 GtkTreeViewColumn *column; | |
1078 GtkTreeIter iter; | |
1079 NodeData *nd = NULL; | |
1080 | |
1081 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), bevent->x, bevent->y, | |
1082 &tpath, &column, NULL, NULL)) | |
1083 { | |
1084 GtkTreeModel *store; | |
1085 gint left_of_expander; | |
1086 | |
1087 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget)); | |
1088 gtk_tree_model_get_iter(store, &iter, tpath); | |
1089 gtk_tree_model_get(store, &iter, DIR_COLUMN_POINTER, &nd, -1); | |
1090 gtk_tree_view_set_cursor(GTK_TREE_VIEW(widget), tpath, NULL, FALSE); | |
1091 | |
1092 if (vdtree_clicked_on_expander(GTK_TREE_VIEW(widget), tpath, column, bevent->x, bevent->y, &left_of_expander)) | |
1093 { | |
382 | 1094 vd->click_fd = NULL; |
9 | 1095 |
1096 /* clicking this region should automatically reveal an expander, if necessary | |
1097 * treeview bug: the expander will not expand until a button_motion_event highlights it. | |
1098 */ | |
1099 if (bevent->button == 1 && | |
1100 !left_of_expander && | |
382 | 1101 !gtk_tree_view_row_expanded(GTK_TREE_VIEW(vd->view), tpath)) |
9 | 1102 { |
382 | 1103 vdtree_populate_path_by_iter(vd, &iter, FALSE, vd->path); |
1104 vdtree_icon_set_by_iter(vd, &iter, vd->pf->open); | |
9 | 1105 } |
1106 | |
1107 gtk_tree_path_free(tpath); | |
1108 return FALSE; | |
1109 } | |
1110 | |
1111 gtk_tree_path_free(tpath); | |
1112 } | |
1113 | |
382 | 1114 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
|
1115 vd_color_set(vd, vd->click_fd, TRUE); |
9 | 1116 |
1117 if (bevent->button == 3) | |
1118 { | |
388
5186f8e38cb8
Make directory view popup menu common and move it to view_dir.{c,h}.
zas_
parents:
384
diff
changeset
|
1119 vd->popup = vd_pop_menu(vd, vd->click_fd); |
382 | 1120 gtk_menu_popup(GTK_MENU(vd->popup), NULL, NULL, NULL, NULL, |
9 | 1121 bevent->button, bevent->time); |
1122 } | |
1123 | |
1124 return (bevent->button != 1); | |
1125 } | |
1126 | |
1127 static gint vdtree_release_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data) | |
1128 { | |
382 | 1129 ViewDir *vd = data; |
9 | 1130 GtkTreePath *tpath; |
1131 GtkTreeIter iter; | |
1132 NodeData *nd = NULL; | |
1133 | |
382 | 1134 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
|
1135 vd_color_set(vd, vd->click_fd, FALSE); |
9 | 1136 |
1137 if (bevent->button != 1) return TRUE; | |
1138 | |
1139 if ((bevent->x != 0 || bevent->y != 0) && | |
1140 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), bevent->x, bevent->y, | |
1141 &tpath, NULL, NULL, NULL)) | |
1142 { | |
1143 GtkTreeModel *store; | |
1144 | |
1145 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget)); | |
1146 gtk_tree_model_get_iter(store, &iter, tpath); | |
1147 gtk_tree_model_get(store, &iter, DIR_COLUMN_POINTER, &nd, -1); | |
1148 gtk_tree_path_free(tpath); | |
1149 } | |
1150 | |
382 | 1151 if (nd && vd->click_fd == nd->fd) |
9 | 1152 { |
382 | 1153 vdtree_select_row(vd, vd->click_fd); |
9 | 1154 } |
1155 | |
1156 return FALSE; | |
1157 } | |
1158 | |
1159 static void vdtree_row_expanded(GtkTreeView *treeview, GtkTreeIter *iter, GtkTreePath *tpath, gpointer data) | |
1160 { | |
382 | 1161 ViewDir *vd = data; |
9 | 1162 |
382 | 1163 vdtree_populate_path_by_iter(vd, iter, FALSE, NULL); |
1164 vdtree_icon_set_by_iter(vd, iter, vd->pf->open); | |
9 | 1165 } |
1166 | |
1167 static void vdtree_row_collapsed(GtkTreeView *treeview, GtkTreeIter *iter, GtkTreePath *tpath, gpointer data) | |
1168 { | |
382 | 1169 ViewDir *vd = data; |
9 | 1170 |
382 | 1171 vdtree_icon_set_by_iter(vd, iter, vd->pf->close); |
9 | 1172 } |
1173 | |
1174 static gint vdtree_sort_cb(GtkTreeModel *store, GtkTreeIter *a, GtkTreeIter *b, gpointer data) | |
1175 { | |
1176 NodeData *nda; | |
1177 NodeData *ndb; | |
1178 | |
1179 gtk_tree_model_get(store, a, DIR_COLUMN_POINTER, &nda, -1); | |
1180 gtk_tree_model_get(store, b, DIR_COLUMN_POINTER, &ndb, -1); | |
1181 | |
1182 return CASE_SORT(nda->fd->name, ndb->fd->name); | |
1183 } | |
1184 | |
1185 /* | |
1186 *---------------------------------------------------------------------------- | |
1187 * core | |
1188 *---------------------------------------------------------------------------- | |
1189 */ | |
1190 | |
382 | 1191 static void vdtree_setup_root(ViewDir *vd) |
9 | 1192 { |
1193 const gchar *path = "/"; | |
1194 FileData *fd; | |
1195 | |
138 | 1196 |
1197 fd = file_data_new_simple(path); | |
382 | 1198 vdtree_add_by_data(vd, fd, NULL); |
9 | 1199 |
382 | 1200 vdtree_expand_by_data(vd, fd, TRUE); |
1201 vdtree_populate_path(vd, path, FALSE, FALSE); | |
9 | 1202 } |
1203 | |
1204 static void vdtree_activate_cb(GtkTreeView *tview, GtkTreePath *tpath, GtkTreeViewColumn *column, gpointer data) | |
1205 { | |
382 | 1206 ViewDir *vd = data; |
9 | 1207 GtkTreeModel *store; |
1208 GtkTreeIter iter; | |
1209 NodeData *nd; | |
1210 | |
1211 store = gtk_tree_view_get_model(tview); | |
1212 gtk_tree_model_get_iter(store, &iter, tpath); | |
1213 gtk_tree_model_get(store, &iter, DIR_COLUMN_POINTER, &nd, -1); | |
1214 | |
382 | 1215 vdtree_select_row(vd, nd->fd); |
9 | 1216 } |
1217 | |
1218 static GdkColor *vdtree_color_shifted(GtkWidget *widget) | |
1219 { | |
1220 static GdkColor color; | |
1221 static GtkWidget *done = NULL; | |
1222 | |
1223 if (done != widget) | |
1224 { | |
1225 GtkStyle *style; | |
1226 | |
1227 style = gtk_widget_get_style(widget); | |
1228 memcpy(&color, &style->base[GTK_STATE_NORMAL], sizeof(color)); | |
1229 shift_color(&color, -1, 0); | |
1230 done = widget; | |
1231 } | |
1232 | |
1233 return &color; | |
1234 } | |
1235 | |
1236 static void vdtree_color_cb(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, | |
1237 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data) | |
1238 { | |
382 | 1239 ViewDir *vd = data; |
9 | 1240 gboolean set; |
1241 | |
1242 gtk_tree_model_get(tree_model, iter, DIR_COLUMN_COLOR, &set, -1); | |
1243 g_object_set(G_OBJECT(cell), | |
382 | 1244 "cell-background-gdk", vdtree_color_shifted(vd->view), |
9 | 1245 "cell-background-set", set, NULL); |
1246 } | |
1247 | |
1248 static gboolean vdtree_destroy_node_cb(GtkTreeModel *store, GtkTreePath *tpath, GtkTreeIter *iter, gpointer data) | |
1249 { | |
1250 NodeData *nd; | |
1251 | |
1252 gtk_tree_model_get(store, iter, DIR_COLUMN_POINTER, &nd, -1); | |
1253 vdtree_node_free(nd); | |
1254 | |
1255 return FALSE; | |
1256 } | |
1257 | |
1258 static void vdtree_destroy_cb(GtkWidget *widget, gpointer data) | |
1259 { | |
382 | 1260 ViewDir *vd = data; |
9 | 1261 GtkTreeModel *store; |
1262 | |
382 | 1263 vdtree_dnd_drop_expand_cancel(vd); |
1264 vdtree_dnd_drop_scroll_cancel(vd); | |
1265 widget_auto_scroll_stop(vd->view); | |
9 | 1266 |
382 | 1267 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vd->view)); |
1268 gtk_tree_model_foreach(store, vdtree_destroy_node_cb, vd); | |
9 | 1269 } |
1270 | |
384
392dd6541d51
Merge parts of view_dir_list/tree constructors/destructors to
zas_
parents:
383
diff
changeset
|
1271 ViewDir *vdtree_new(ViewDir *vd, const gchar *path) |
9 | 1272 { |
1273 GtkTreeStore *store; | |
1274 GtkTreeSelection *selection; | |
1275 GtkTreeViewColumn *column; | |
1276 GtkCellRenderer *renderer; | |
1277 | |
382 | 1278 vd->info = g_new0(ViewDirInfoTree, 1); |
1279 vd->type = DIRVIEW_TREE; | |
384
392dd6541d51
Merge parts of view_dir_list/tree constructors/destructors to
zas_
parents:
383
diff
changeset
|
1280 vd->widget_destroy_cb = vdtree_destroy_cb; |
9 | 1281 |
382 | 1282 VDTREE_INFO(vd, drop_expand_id) = -1; |
9 | 1283 |
382 | 1284 VDTREE_INFO(vd, busy_ref) = 0; |
9 | 1285 |
1286 store = gtk_tree_store_new(4, G_TYPE_POINTER, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_INT); | |
382 | 1287 vd->view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); |
9 | 1288 g_object_unref(store); |
1289 | |
382 | 1290 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(vd->view), FALSE); |
1291 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(vd->view), FALSE); | |
1292 gtk_tree_sortable_set_default_sort_func(GTK_TREE_SORTABLE(store), vdtree_sort_cb, vd, NULL); | |
9 | 1293 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), |
1294 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, GTK_SORT_ASCENDING); | |
1295 | |
382 | 1296 g_signal_connect(G_OBJECT(vd->view), "row_activated", |
1297 G_CALLBACK(vdtree_activate_cb), vd); | |
1298 g_signal_connect(G_OBJECT(vd->view), "row_expanded", | |
1299 G_CALLBACK(vdtree_row_expanded), vd); | |
1300 g_signal_connect(G_OBJECT(vd->view), "row_collapsed", | |
1301 G_CALLBACK(vdtree_row_collapsed), vd); | |
9 | 1302 #if 0 |
1303 g_signal_connect(G_OBJECT(store), "row_deleted", | |
382 | 1304 G_CALLBACK(vdtree_row_deleted_cb), vd); |
9 | 1305 #endif |
1306 | |
382 | 1307 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vd->view)); |
9 | 1308 gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); |
382 | 1309 gtk_tree_selection_set_select_function(selection, vdtree_select_cb, vd, NULL); |
9 | 1310 |
1311 column = gtk_tree_view_column_new(); | |
1312 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_GROW_ONLY); | |
1313 | |
1314 renderer = gtk_cell_renderer_pixbuf_new(); | |
1315 gtk_tree_view_column_pack_start(column, renderer, FALSE); | |
1316 gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", DIR_COLUMN_ICON); | |
382 | 1317 gtk_tree_view_column_set_cell_data_func(column, renderer, vdtree_color_cb, vd, NULL); |
9 | 1318 |
1319 renderer = gtk_cell_renderer_text_new(); | |
1320 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
1321 gtk_tree_view_column_add_attribute(column, renderer, "text", DIR_COLUMN_NAME); | |
382 | 1322 gtk_tree_view_column_set_cell_data_func(column, renderer, vdtree_color_cb, vd, NULL); |
9 | 1323 |
382 | 1324 gtk_tree_view_append_column(GTK_TREE_VIEW(vd->view), column); |
9 | 1325 |
382 | 1326 g_signal_connect(G_OBJECT(vd->view), "key_press_event", |
1327 G_CALLBACK(vdtree_press_key_cb), vd); | |
9 | 1328 |
382 | 1329 gtk_container_add(GTK_CONTAINER(vd->widget), vd->view); |
1330 gtk_widget_show(vd->view); | |
9 | 1331 |
382 | 1332 vd->pf = folder_icons_new(); |
9 | 1333 |
382 | 1334 vdtree_setup_root(vd); |
9 | 1335 |
382 | 1336 vdtree_dnd_init(vd); |
9 | 1337 |
382 | 1338 g_signal_connect(G_OBJECT(vd->view), "button_press_event", |
1339 G_CALLBACK(vdtree_press_cb), vd); | |
1340 g_signal_connect(G_OBJECT(vd->view), "button_release_event", | |
1341 G_CALLBACK(vdtree_release_cb), vd); | |
9 | 1342 |
382 | 1343 vdtree_set_path(vd, path); |
9 | 1344 |
382 | 1345 return vd; |
9 | 1346 } |
1347 | |
1348 #if 0 | |
382 | 1349 void vdtree_set_click_func(ViewDir *vd, |
1350 void (*func)(ViewDir *vd, GdkEventButton *event, FileData *fd, gpointer), gpointer data) | |
9 | 1351 { |
1352 if (!td) return; | |
382 | 1353 vd->click_func = func; |
1354 vd->click_data = data; | |
9 | 1355 } |
1356 #endif | |
1357 | |
1358 |