Mercurial > geeqie.yaz
annotate src/view_dir_list.c @ 276:4f526d436873
Implement secure rc file saving.
First data is written to a temporary file, then if nothing
was wrong, this file is renamed to the final name.
This way the risk of corrupted rc file is greatly reduced.
The code is borrowed from ELinks (http://elinks.cz).
author | zas_ |
---|---|
date | Tue, 08 Apr 2008 21:55:58 +0000 |
parents | 22ed43d4c849 |
children | 9995c5fb202a |
rev | line source |
---|---|
9 | 1 /* |
196 | 2 * Geeqie |
9 | 3 * (C) 2004 John Ellis |
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 | |
12 #include "gqview.h" | |
13 #include "view_dir_list.h" | |
14 | |
15 #include "dnd.h" | |
16 #include "dupe.h" | |
17 #include "filelist.h" | |
18 #include "layout.h" | |
19 #include "layout_image.h" | |
20 #include "layout_util.h" | |
21 #include "utilops.h" | |
22 #include "ui_bookmark.h" | |
23 #include "ui_fileops.h" | |
24 #include "ui_menu.h" | |
25 #include "ui_tree_edit.h" | |
26 | |
27 #include <gdk/gdkkeysyms.h> /* for keyboard values */ | |
28 | |
29 | |
30 #define VDLIST_PAD 4 | |
31 | |
32 | |
33 enum { | |
34 DIR_COLUMN_POINTER = 0, | |
35 DIR_COLUMN_ICON, | |
36 DIR_COLUMN_NAME, | |
37 DIR_COLUMN_COLOR, | |
38 DIR_COLUMN_COUNT | |
39 }; | |
40 | |
41 | |
42 static void vdlist_popup_destroy_cb(GtkWidget *widget, gpointer data); | |
43 static gint vdlist_auto_scroll_notify_cb(GtkWidget *widget, gint x, gint y, gpointer data); | |
44 | |
45 /* | |
46 *----------------------------------------------------------------------------- | |
47 * misc | |
48 *----------------------------------------------------------------------------- | |
49 */ | |
50 | |
51 static gint vdlist_find_row(ViewDirList *vdl, FileData *fd, GtkTreeIter *iter) | |
52 { | |
53 GtkTreeModel *store; | |
54 gint valid; | |
55 gint row = 0; | |
56 | |
57 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vdl->listview)); | |
58 valid = gtk_tree_model_get_iter_first(store, iter); | |
59 while (valid) | |
60 { | |
61 FileData *fd_n; | |
62 gtk_tree_model_get(GTK_TREE_MODEL(store), iter, DIR_COLUMN_POINTER, &fd_n, -1); | |
63 if (fd_n == fd) return row; | |
64 | |
65 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), iter); | |
66 row++; | |
67 } | |
68 | |
69 return -1; | |
70 } | |
71 | |
72 static gint vdlist_rename_row_cb(TreeEditData *td, const gchar *old, const gchar *new, gpointer data) | |
73 { | |
74 ViewDirList *vdl = data; | |
75 GtkTreeModel *store; | |
76 GtkTreeIter iter; | |
77 FileData *fd; | |
78 gchar *old_path; | |
79 gchar *new_path; | |
80 gchar *base; | |
81 | |
82 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vdl->listview)); | |
83 if (!gtk_tree_model_get_iter(store, &iter, td->path)) return FALSE; | |
84 gtk_tree_model_get(store, &iter, DIR_COLUMN_POINTER, &fd, -1); | |
85 if (!fd) return FALSE; | |
86 | |
87 old_path = g_strdup(fd->path); | |
88 | |
89 base = remove_level_from_path(old_path); | |
90 new_path = concat_dir_and_file(base, new); | |
91 g_free(base); | |
92 | |
138 | 93 if (file_util_rename_dir(fd, new_path, vdl->listview)) |
9 | 94 { |
95 if (vdl->layout && strcmp(vdl->path, old_path) == 0) | |
96 { | |
97 layout_set_path(vdl->layout, new_path); | |
98 } | |
99 else | |
100 { | |
101 vdlist_refresh(vdl); | |
102 } | |
103 } | |
104 | |
105 g_free(old_path); | |
106 g_free(new_path); | |
107 return FALSE; | |
108 } | |
109 | |
110 static void vdlist_rename_by_row(ViewDirList *vdl, FileData *fd) | |
111 { | |
112 GtkTreeModel *store; | |
113 GtkTreePath *tpath; | |
114 GtkTreeIter iter; | |
115 | |
116 if (vdlist_find_row(vdl, fd, &iter) < 0) return; | |
117 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vdl->listview)); | |
118 tpath = gtk_tree_model_get_path(store, &iter); | |
119 | |
120 tree_edit_by_path(GTK_TREE_VIEW(vdl->listview), tpath, 0, fd->name, | |
121 vdlist_rename_row_cb, vdl); | |
122 gtk_tree_path_free(tpath); | |
123 } | |
124 | |
125 static FileData *vdlist_row_by_path(ViewDirList *vdl, const gchar *path, gint *row) | |
126 { | |
127 GList *work; | |
128 gint n; | |
129 | |
130 if (!path) | |
131 { | |
132 if (row) *row = -1; | |
133 return NULL; | |
134 } | |
135 | |
136 n = 0; | |
137 work = vdl->list; | |
138 while (work) | |
139 { | |
140 FileData *fd = work->data; | |
141 if (strcmp(fd->path, path) == 0) | |
142 { | |
143 if (row) *row = n; | |
144 return fd; | |
145 } | |
146 work = work->next; | |
147 n++; | |
148 } | |
149 | |
150 if (row) *row = -1; | |
151 return NULL; | |
152 } | |
153 | |
154 static void vdlist_color_set(ViewDirList *vdl, FileData *fd, gint color_set) | |
155 { | |
156 GtkTreeModel *store; | |
157 GtkTreeIter iter; | |
158 | |
159 if (vdlist_find_row(vdl, fd, &iter) < 0) return; | |
160 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vdl->listview)); | |
161 gtk_list_store_set(GTK_LIST_STORE(store), &iter, DIR_COLUMN_COLOR, color_set, -1); | |
162 } | |
163 | |
164 /* | |
165 *----------------------------------------------------------------------------- | |
166 * drop menu (from dnd) | |
167 *----------------------------------------------------------------------------- | |
168 */ | |
169 | |
170 static void vdlist_drop_menu_copy_cb(GtkWidget *widget, gpointer data) | |
171 { | |
172 ViewDirList *vdl = data; | |
173 const gchar *path; | |
174 GList *list; | |
175 | |
176 if (!vdl->drop_fd) return; | |
177 | |
178 path = vdl->drop_fd->path; | |
179 list = vdl->drop_list; | |
180 vdl->drop_list = NULL; | |
181 | |
182 file_util_copy_simple(list, path); | |
183 } | |
184 | |
185 static void vdlist_drop_menu_move_cb(GtkWidget *widget, gpointer data) | |
186 { | |
187 ViewDirList *vdl = data; | |
188 const gchar *path; | |
189 GList *list; | |
190 | |
191 if (!vdl->drop_fd) return; | |
192 | |
193 path = vdl->drop_fd->path; | |
194 list = vdl->drop_list; | |
195 | |
196 vdl->drop_list = NULL; | |
197 | |
198 file_util_move_simple(list, path); | |
199 } | |
200 | |
201 static GtkWidget *vdlist_drop_menu(ViewDirList *vdl, gint active) | |
202 { | |
203 GtkWidget *menu; | |
204 | |
205 menu = popup_menu_short_lived(); | |
206 g_signal_connect(G_OBJECT(menu), "destroy", | |
207 G_CALLBACK(vdlist_popup_destroy_cb), vdl); | |
208 | |
209 menu_item_add_stock_sensitive(menu, _("_Copy"), GTK_STOCK_COPY, active, | |
210 G_CALLBACK(vdlist_drop_menu_copy_cb), vdl); | |
211 menu_item_add_sensitive(menu, _("_Move"), active, G_CALLBACK(vdlist_drop_menu_move_cb), vdl); | |
212 | |
213 menu_item_add_divider(menu); | |
214 menu_item_add_stock(menu, _("Cancel"), GTK_STOCK_CANCEL, NULL, vdl); | |
215 | |
216 return menu; | |
217 } | |
218 | |
219 /* | |
220 *----------------------------------------------------------------------------- | |
221 * pop-up menu | |
222 *----------------------------------------------------------------------------- | |
223 */ | |
224 | |
225 static void vdlist_pop_menu_up_cb(GtkWidget *widget, gpointer data) | |
226 { | |
227 ViewDirList *vdl = data; | |
228 gchar *path; | |
229 | |
230 if (!vdl->path || strcmp(vdl->path, "/") == 0) return; | |
231 path = remove_level_from_path(vdl->path); | |
232 | |
233 if (vdl->select_func) | |
234 { | |
235 vdl->select_func(vdl, path, vdl->select_data); | |
236 } | |
237 | |
238 g_free(path); | |
239 } | |
240 | |
241 static void vdlist_pop_menu_slide_cb(GtkWidget *widget, gpointer data) | |
242 { | |
243 ViewDirList *vdl = data; | |
244 gchar *path; | |
245 | |
246 if (!vdl->layout || !vdl->click_fd) return; | |
247 | |
248 path = g_strdup(vdl->click_fd->path); | |
249 | |
250 layout_set_path(vdl->layout, path); | |
251 layout_select_none(vdl->layout); | |
252 layout_image_slideshow_stop(vdl->layout); | |
253 layout_image_slideshow_start(vdl->layout); | |
254 | |
255 g_free(path); | |
256 } | |
257 | |
258 static void vdlist_pop_menu_slide_rec_cb(GtkWidget *widget, gpointer data) | |
259 { | |
260 ViewDirList *vdl = data; | |
261 gchar *path; | |
262 GList *list; | |
263 | |
264 if (!vdl->layout || !vdl->click_fd) return; | |
265 | |
266 path = g_strdup(vdl->click_fd->path); | |
267 | |
138 | 268 list = filelist_recursive(path); |
9 | 269 |
270 layout_image_slideshow_stop(vdl->layout); | |
271 layout_image_slideshow_start_from_list(vdl->layout, list); | |
272 | |
273 g_free(path); | |
274 } | |
275 | |
276 static void vdlist_pop_menu_dupe(ViewDirList *vdl, gint recursive) | |
277 { | |
278 DupeWindow *dw; | |
279 GList *list = NULL; | |
280 | |
281 if (!vdl->click_fd) return; | |
282 | |
283 if (recursive) | |
284 { | |
138 | 285 list = g_list_append(list, file_data_ref(vdl->click_fd)); |
9 | 286 } |
287 else | |
288 { | |
138 | 289 filelist_read(vdl->click_fd->path, &list, NULL); |
290 list = filelist_filter(list, FALSE); | |
9 | 291 } |
292 | |
293 dw = dupe_window_new(DUPE_MATCH_NAME); | |
294 dupe_window_add_files(dw, list, recursive); | |
295 | |
138 | 296 filelist_free(list); |
9 | 297 } |
298 | |
299 static void vdlist_pop_menu_dupe_cb(GtkWidget *widget, gpointer data) | |
300 { | |
301 ViewDirList *vdl = data; | |
302 vdlist_pop_menu_dupe(vdl, FALSE); | |
303 } | |
304 | |
305 static void vdlist_pop_menu_dupe_rec_cb(GtkWidget *widget, gpointer data) | |
306 { | |
307 ViewDirList *vdl = data; | |
308 vdlist_pop_menu_dupe(vdl, TRUE); | |
309 } | |
310 | |
311 static void vdlist_pop_menu_new_cb(GtkWidget *widget, gpointer data) | |
312 { | |
313 ViewDirList *vdl = data; | |
314 gchar *new_path; | |
315 gchar *buf; | |
316 | |
317 if (!vdl->path) return; | |
318 | |
319 buf = concat_dir_and_file(vdl->path, _("new_folder")); | |
320 new_path = unique_filename(buf, NULL, NULL, FALSE); | |
321 g_free(buf); | |
322 if (!new_path) return; | |
323 | |
324 if (!mkdir_utf8(new_path, 0755)) | |
325 { | |
326 gchar *text; | |
327 | |
328 text = g_strdup_printf(_("Unable to create folder:\n%s"), new_path); | |
329 file_util_warning_dialog(_("Error creating folder"), text, GTK_STOCK_DIALOG_ERROR, vdl->listview); | |
330 g_free(text); | |
331 } | |
332 else | |
333 { | |
334 FileData *fd; | |
335 | |
336 vdlist_refresh(vdl); | |
337 fd = vdlist_row_by_path(vdl, new_path, NULL); | |
338 | |
339 vdlist_rename_by_row(vdl, fd); | |
340 } | |
341 | |
342 g_free(new_path); | |
343 } | |
344 | |
345 static void vdlist_pop_menu_rename_cb(GtkWidget *widget, gpointer data) | |
346 { | |
347 ViewDirList *vdl = data; | |
348 | |
349 vdlist_rename_by_row(vdl, vdl->click_fd); | |
350 } | |
351 | |
112
b15d4c18168f
Fri Nov 17 19:06:19 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
352 static void vdlist_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
|
353 { |
b15d4c18168f
Fri Nov 17 19:06:19 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
354 ViewDirList *vdl = data; |
b15d4c18168f
Fri Nov 17 19:06:19 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
355 |
b15d4c18168f
Fri Nov 17 19:06:19 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
356 if (!vdl->click_fd) return; |
138 | 357 file_util_delete_dir(vdl->click_fd, vdl->widget); |
112
b15d4c18168f
Fri Nov 17 19:06:19 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
358 } |
b15d4c18168f
Fri Nov 17 19:06:19 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
359 |
9 | 360 static void vdlist_pop_menu_tree_cb(GtkWidget *widget, gpointer data) |
361 { | |
362 ViewDirList *vdl = data; | |
363 | |
364 if (vdl->layout) layout_views_set(vdl->layout, TRUE, vdl->layout->icon_view); | |
365 } | |
366 | |
367 static void vdlist_pop_menu_refresh_cb(GtkWidget *widget, gpointer data) | |
368 { | |
369 ViewDirList *vdl = data; | |
370 | |
371 if (vdl->layout) layout_refresh(vdl->layout); | |
372 } | |
373 | |
374 static GtkWidget *vdlist_pop_menu(ViewDirList *vdl, FileData *fd) | |
375 { | |
376 GtkWidget *menu; | |
377 gint active; | |
378 | |
379 active = (fd != NULL); | |
380 | |
381 menu = popup_menu_short_lived(); | |
382 g_signal_connect(G_OBJECT(menu), "destroy", | |
383 G_CALLBACK(vdlist_popup_destroy_cb), vdl); | |
384 | |
385 menu_item_add_stock_sensitive(menu, _("_Up to parent"), GTK_STOCK_GO_UP, | |
386 (vdl->path && strcmp(vdl->path, "/") != 0), | |
387 G_CALLBACK(vdlist_pop_menu_up_cb), vdl); | |
388 | |
389 menu_item_add_divider(menu); | |
390 menu_item_add_sensitive(menu, _("_Slideshow"), active, | |
391 G_CALLBACK(vdlist_pop_menu_slide_cb), vdl); | |
392 menu_item_add_sensitive(menu, _("Slideshow recursive"), active, | |
393 G_CALLBACK(vdlist_pop_menu_slide_rec_cb), vdl); | |
394 | |
395 menu_item_add_divider(menu); | |
396 menu_item_add_stock_sensitive(menu, _("Find _duplicates..."), GTK_STOCK_FIND, active, | |
397 G_CALLBACK(vdlist_pop_menu_dupe_cb), vdl); | |
398 menu_item_add_stock_sensitive(menu, _("Find duplicates recursive..."), GTK_STOCK_FIND, active, | |
399 G_CALLBACK(vdlist_pop_menu_dupe_rec_cb), vdl); | |
400 | |
401 menu_item_add_divider(menu); | |
402 | |
403 /* check using . (always row 0) */ | |
404 active = (vdl->path && access_file(vdl->path , W_OK | X_OK)); | |
405 menu_item_add_sensitive(menu, _("_New folder..."), active, | |
406 G_CALLBACK(vdlist_pop_menu_new_cb), vdl); | |
407 | |
408 /* ignore .. and . */ | |
409 active = (active && fd && | |
410 strcmp(fd->name, ".") != 0 && | |
411 strcmp(fd->name, "..") != 0 && | |
412 access_file(fd->path, W_OK | X_OK)); | |
413 menu_item_add_sensitive(menu, _("_Rename..."), active, | |
414 G_CALLBACK(vdlist_pop_menu_rename_cb), vdl); | |
112
b15d4c18168f
Fri Nov 17 19:06:19 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
415 menu_item_add_stock_sensitive(menu, _("_Delete..."), GTK_STOCK_DELETE, active, |
b15d4c18168f
Fri Nov 17 19:06:19 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
416 G_CALLBACK(vdlist_pop_menu_delete_cb), vdl); |
9 | 417 |
418 menu_item_add_divider(menu); | |
419 menu_item_add_check(menu, _("View as _tree"), FALSE, | |
420 G_CALLBACK(vdlist_pop_menu_tree_cb), vdl); | |
421 menu_item_add_stock(menu, _("Re_fresh"), GTK_STOCK_REFRESH, | |
422 G_CALLBACK(vdlist_pop_menu_refresh_cb), vdl); | |
423 | |
424 return menu; | |
425 } | |
426 | |
427 static void vdlist_popup_destroy_cb(GtkWidget *widget, gpointer data) | |
428 { | |
429 ViewDirList *vdl = data; | |
430 | |
431 vdlist_color_set(vdl, vdl->click_fd, FALSE); | |
432 vdl->click_fd = NULL; | |
433 vdl->popup = NULL; | |
434 | |
435 vdlist_color_set(vdl, vdl->drop_fd, FALSE); | |
138 | 436 filelist_free(vdl->drop_list); |
9 | 437 vdl->drop_list = NULL; |
438 vdl->drop_fd = NULL; | |
439 } | |
440 | |
441 /* | |
442 *----------------------------------------------------------------------------- | |
443 * dnd | |
444 *----------------------------------------------------------------------------- | |
445 */ | |
446 | |
447 static GtkTargetEntry vdlist_dnd_drop_types[] = { | |
448 { "text/uri-list", 0, TARGET_URI_LIST } | |
449 }; | |
450 static gint vdlist_dnd_drop_types_count = 1; | |
451 | |
452 static void vdlist_dest_set(ViewDirList *vdl, gint enable) | |
453 { | |
454 if (enable) | |
455 { | |
456 gtk_drag_dest_set(vdl->listview, | |
457 GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP, | |
458 vdlist_dnd_drop_types, vdlist_dnd_drop_types_count, | |
459 GDK_ACTION_MOVE | GDK_ACTION_COPY); | |
460 } | |
461 else | |
462 { | |
463 gtk_drag_dest_unset(vdl->listview); | |
464 } | |
465 } | |
466 | |
467 static void vdlist_dnd_get(GtkWidget *widget, GdkDragContext *context, | |
468 GtkSelectionData *selection_data, guint info, | |
469 guint time, gpointer data) | |
470 { | |
471 ViewDirList *vdl = data; | |
472 GList *list; | |
473 gchar *text = NULL; | |
474 gint length = 0; | |
475 | |
476 if (!vdl->click_fd) return; | |
477 | |
478 switch (info) | |
479 { | |
480 case TARGET_URI_LIST: | |
481 case TARGET_TEXT_PLAIN: | |
138 | 482 list = g_list_prepend(NULL, vdl->click_fd); |
483 text = uri_text_from_filelist(list, &length, (info == TARGET_TEXT_PLAIN)); | |
9 | 484 g_list_free(list); |
485 break; | |
486 } | |
487 if (text) | |
488 { | |
489 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:
44
diff
changeset
|
490 8, (guchar *)text, length); |
9 | 491 g_free(text); |
492 } | |
493 } | |
494 | |
495 static void vdlist_dnd_begin(GtkWidget *widget, GdkDragContext *context, gpointer data) | |
496 { | |
497 ViewDirList *vdl = data; | |
498 | |
499 vdlist_color_set(vdl, vdl->click_fd, TRUE); | |
500 vdlist_dest_set(vdl, FALSE); | |
501 } | |
502 | |
503 static void vdlist_dnd_end(GtkWidget *widget, GdkDragContext *context, gpointer data) | |
504 { | |
505 ViewDirList *vdl = data; | |
506 | |
507 vdlist_color_set(vdl, vdl->click_fd, FALSE); | |
508 | |
509 if (context->action == GDK_ACTION_MOVE) | |
510 { | |
511 vdlist_refresh(vdl); | |
512 } | |
513 vdlist_dest_set(vdl, TRUE); | |
514 } | |
515 | |
516 static void vdlist_dnd_drop_receive(GtkWidget *widget, | |
517 GdkDragContext *context, gint x, gint y, | |
518 GtkSelectionData *selection_data, guint info, | |
519 guint time, gpointer data) | |
520 { | |
521 ViewDirList *vdl = data; | |
522 GtkTreePath *tpath; | |
523 GtkTreeIter iter; | |
524 FileData *fd = NULL; | |
525 | |
526 vdl->click_fd = NULL; | |
527 | |
528 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), x, y, | |
529 &tpath, NULL, NULL, NULL)) | |
530 { | |
531 GtkTreeModel *store; | |
532 | |
533 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget)); | |
534 gtk_tree_model_get_iter(store, &iter, tpath); | |
535 gtk_tree_model_get(store, &iter, DIR_COLUMN_POINTER, &fd, -1); | |
536 gtk_tree_path_free(tpath); | |
537 } | |
538 | |
539 if (!fd) return; | |
540 | |
541 if (info == TARGET_URI_LIST) | |
542 { | |
543 GList *list; | |
544 gint active; | |
545 | |
138 | 546 list = uri_filelist_from_text((gchar *)selection_data->data, TRUE); |
9 | 547 if (!list) return; |
548 | |
549 active = access_file(fd->path, W_OK | X_OK); | |
550 | |
551 vdlist_color_set(vdl, fd, TRUE); | |
552 vdl->popup = vdlist_drop_menu(vdl, active); | |
553 gtk_menu_popup(GTK_MENU(vdl->popup), NULL, NULL, NULL, NULL, 0, time); | |
554 | |
555 vdl->drop_fd = fd; | |
556 vdl->drop_list = list; | |
557 } | |
558 } | |
559 | |
560 #if 0 | |
561 static gint vdlist_get_row_visibility(ViewDirList *vdl, FileData *fd) | |
562 { | |
563 GtkTreeModel *store; | |
564 GtkTreeViewColumn *column; | |
565 GtkTreePath *tpath; | |
566 GtkTreeIter iter; | |
567 | |
568 GdkRectangle vrect; | |
569 GdkRectangle crect; | |
570 | |
571 if (!fd || vdlist_find_row(vdl, fd, &iter) < 0) return 0; | |
572 | |
573 column = gtk_tree_view_get_column(GTK_TREE_VIEW(vdl->listview), 0); | |
574 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vdl->listview)); | |
575 tpath = gtk_tree_model_get_path(store, &iter); | |
576 | |
577 gtk_tree_view_get_visible_rect(GTK_TREE_VIEW(vdl->listview), &vrect); | |
578 gtk_tree_view_get_cell_area(GTK_TREE_VIEW(vdl->listview), tpath, column, &crect); | |
579 printf("window: %d + %d; cell: %d + %d\n", vrect.y, vrect.height, crect.y, crect.height); | |
580 gtk_tree_path_free(tpath); | |
581 | |
582 if (crect.y + crect.height < vrect.y) return -1; | |
583 if (crect.y > vrect.y + vrect.height) return 1; | |
584 return 0; | |
585 } | |
586 #endif | |
587 | |
588 static void vdlist_scroll_to_row(ViewDirList *vdl, FileData *fd, gfloat y_align) | |
589 { | |
590 GtkTreeIter iter; | |
591 | |
592 if (GTK_WIDGET_REALIZED(vdl->listview) && | |
593 vdlist_find_row(vdl, fd, &iter) >= 0) | |
594 { | |
595 GtkTreeModel *store; | |
596 GtkTreePath *tpath; | |
597 | |
598 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vdl->listview)); | |
599 tpath = gtk_tree_model_get_path(store, &iter); | |
600 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(vdl->listview), tpath, NULL, TRUE, y_align, 0.0); | |
601 gtk_tree_view_set_cursor(GTK_TREE_VIEW(vdl->listview), tpath, NULL, FALSE); | |
602 gtk_tree_path_free(tpath); | |
603 | |
604 if (!GTK_WIDGET_HAS_FOCUS(vdl->listview)) gtk_widget_grab_focus(vdl->listview); | |
605 } | |
606 } | |
607 | |
608 static void vdlist_drop_update(ViewDirList *vdl, gint x, gint y) | |
609 { | |
610 GtkTreePath *tpath; | |
611 GtkTreeIter iter; | |
612 FileData *fd = NULL; | |
613 | |
614 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(vdl->listview), x, y, | |
615 &tpath, NULL, NULL, NULL)) | |
616 { | |
617 GtkTreeModel *store; | |
618 | |
619 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vdl->listview)); | |
620 gtk_tree_model_get_iter(store, &iter, tpath); | |
621 gtk_tree_model_get(store, &iter, DIR_COLUMN_POINTER, &fd, -1); | |
622 gtk_tree_path_free(tpath); | |
623 } | |
624 | |
625 if (fd != vdl->drop_fd) | |
626 { | |
627 vdlist_color_set(vdl, vdl->drop_fd, FALSE); | |
628 vdlist_color_set(vdl, fd, TRUE); | |
629 } | |
630 | |
631 vdl->drop_fd = fd; | |
632 } | |
633 | |
634 static void vdlist_dnd_drop_scroll_cancel(ViewDirList *vdl) | |
635 { | |
636 if (vdl->drop_scroll_id != -1) g_source_remove(vdl->drop_scroll_id); | |
637 vdl->drop_scroll_id = -1; | |
638 } | |
639 | |
640 static gint vdlist_auto_scroll_idle_cb(gpointer data) | |
641 { | |
642 ViewDirList *vdl = data; | |
643 | |
644 if (vdl->drop_fd) | |
645 { | |
646 GdkWindow *window; | |
647 gint x, y; | |
648 gint w, h; | |
649 | |
650 window = vdl->listview->window; | |
651 gdk_window_get_pointer(window, &x, &y, NULL); | |
652 gdk_drawable_get_size(window, &w, &h); | |
653 if (x >= 0 && x < w && y >= 0 && y < h) | |
654 { | |
655 vdlist_drop_update(vdl, x, y); | |
656 } | |
657 } | |
658 | |
659 vdl->drop_scroll_id = -1; | |
660 return FALSE; | |
661 } | |
662 | |
663 static gint vdlist_auto_scroll_notify_cb(GtkWidget *widget, gint x, gint y, gpointer data) | |
664 { | |
665 ViewDirList *vdl = data; | |
666 | |
667 if (!vdl->drop_fd || vdl->drop_list) return FALSE; | |
668 | |
669 if (vdl->drop_scroll_id == -1) vdl->drop_scroll_id = g_idle_add(vdlist_auto_scroll_idle_cb, vdl); | |
670 | |
671 return TRUE; | |
672 } | |
673 | |
674 static gint vdlist_dnd_drop_motion(GtkWidget *widget, GdkDragContext *context, | |
675 gint x, gint y, guint time, gpointer data) | |
676 { | |
677 ViewDirList *vdl = data; | |
678 | |
679 vdl->click_fd = NULL; | |
680 | |
681 if (gtk_drag_get_source_widget(context) == vdl->listview) | |
682 { | |
683 /* from same window */ | |
684 gdk_drag_status(context, 0, time); | |
685 return TRUE; | |
686 } | |
687 else | |
688 { | |
689 gdk_drag_status(context, context->suggested_action, time); | |
690 } | |
691 | |
692 vdlist_drop_update(vdl, x, y); | |
693 | |
694 if (vdl->drop_fd) | |
695 { | |
696 GtkAdjustment *adj = gtk_tree_view_get_vadjustment(GTK_TREE_VIEW(vdl->listview)); | |
697 widget_auto_scroll_start(vdl->listview, adj, -1, -1, vdlist_auto_scroll_notify_cb, vdl); | |
698 } | |
699 | |
700 return FALSE; | |
701 } | |
702 | |
703 static void vdlist_dnd_drop_leave(GtkWidget *widget, GdkDragContext *context, guint time, gpointer data) | |
704 { | |
705 ViewDirList *vdl = data; | |
706 | |
707 if (vdl->drop_fd != vdl->click_fd) vdlist_color_set(vdl, vdl->drop_fd, FALSE); | |
708 | |
709 vdl->drop_fd = NULL; | |
710 } | |
711 | |
712 static void vdlist_dnd_init(ViewDirList *vdl) | |
713 { | |
714 gtk_drag_source_set(vdl->listview, GDK_BUTTON1_MASK | GDK_BUTTON2_MASK, | |
715 dnd_file_drag_types, dnd_file_drag_types_count, | |
716 GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK); | |
717 g_signal_connect(G_OBJECT(vdl->listview), "drag_data_get", | |
718 G_CALLBACK(vdlist_dnd_get), vdl); | |
719 g_signal_connect(G_OBJECT(vdl->listview), "drag_begin", | |
720 G_CALLBACK(vdlist_dnd_begin), vdl); | |
721 g_signal_connect(G_OBJECT(vdl->listview), "drag_end", | |
722 G_CALLBACK(vdlist_dnd_end), vdl); | |
723 | |
724 vdlist_dest_set(vdl, TRUE); | |
725 g_signal_connect(G_OBJECT(vdl->listview), "drag_data_received", | |
726 G_CALLBACK(vdlist_dnd_drop_receive), vdl); | |
727 g_signal_connect(G_OBJECT(vdl->listview), "drag_motion", | |
728 G_CALLBACK(vdlist_dnd_drop_motion), vdl); | |
729 g_signal_connect(G_OBJECT(vdl->listview), "drag_leave", | |
730 G_CALLBACK(vdlist_dnd_drop_leave), vdl); | |
731 } | |
732 | |
733 /* | |
734 *----------------------------------------------------------------------------- | |
735 * main | |
736 *----------------------------------------------------------------------------- | |
737 */ | |
738 | |
739 static void vdlist_select_row(ViewDirList *vdl, FileData *fd) | |
740 { | |
741 if (fd && vdl->select_func) | |
742 { | |
743 gchar *path; | |
744 | |
745 path = g_strdup(fd->path); | |
746 vdl->select_func(vdl, path, vdl->select_data); | |
747 g_free(path); | |
748 } | |
749 } | |
750 | |
751 const gchar *vdlist_row_get_path(ViewDirList *vdl, gint row) | |
752 { | |
753 FileData *fd; | |
754 | |
755 fd = g_list_nth_data(vdl->list, row); | |
756 | |
757 if (fd) return fd->path; | |
758 | |
759 return NULL; | |
760 } | |
761 | |
762 static void vdlist_populate(ViewDirList *vdl) | |
763 { | |
764 GtkListStore *store; | |
765 GList *work; | |
766 | |
767 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vdl->listview))); | |
768 gtk_list_store_clear(store); | |
769 | |
770 work = vdl->list; | |
771 while (work) | |
772 { | |
773 FileData *fd; | |
774 GtkTreeIter iter; | |
775 GdkPixbuf *pixbuf; | |
776 | |
777 fd = work->data; | |
778 | |
779 if (access_file(fd->path, R_OK | X_OK) && fd->name) | |
780 { | |
781 if (fd->name[0] == '.' && fd->name[1] == '\0') | |
782 { | |
783 pixbuf = vdl->pf->open; | |
784 } | |
785 else if (fd->name[0] == '.' && fd->name[1] == '.' && fd->name[2] == '\0') | |
786 { | |
787 pixbuf = vdl->pf->parent; | |
788 } | |
789 else | |
790 { | |
791 pixbuf = vdl->pf->close; | |
792 } | |
793 } | |
794 else | |
795 { | |
796 pixbuf = vdl->pf->deny; | |
797 } | |
798 | |
799 gtk_list_store_append(store, &iter); | |
800 gtk_list_store_set(store, &iter, | |
801 DIR_COLUMN_POINTER, fd, | |
802 DIR_COLUMN_ICON, pixbuf, | |
803 DIR_COLUMN_NAME, fd->name, -1); | |
804 | |
805 work = work->next; | |
806 } | |
807 | |
808 vdl->click_fd = NULL; | |
809 vdl->drop_fd = NULL; | |
810 } | |
811 | |
812 gint vdlist_set_path(ViewDirList *vdl, const gchar *path) | |
813 { | |
814 gint ret; | |
815 FileData *fd; | |
816 gchar *old_path = NULL; | |
138 | 817 gchar *filepath; |
9 | 818 |
819 if (!path) return FALSE; | |
820 if (vdl->path && strcmp(path, vdl->path) == 0) return TRUE; | |
821 | |
822 if (vdl->path) | |
823 { | |
824 gchar *base; | |
825 | |
826 base = remove_level_from_path(vdl->path); | |
827 if (strcmp(base, path) == 0) | |
828 { | |
829 old_path = g_strdup(filename_from_path(vdl->path)); | |
830 } | |
831 g_free(base); | |
832 } | |
833 | |
834 g_free(vdl->path); | |
835 vdl->path = g_strdup(path); | |
836 | |
837 filelist_free(vdl->list); | |
838 vdl->list = NULL; | |
839 | |
840 ret = filelist_read(vdl->path, NULL, &vdl->list); | |
841 | |
842 vdl->list = filelist_sort(vdl->list, SORT_NAME, TRUE); | |
843 | |
844 /* add . and .. */ | |
845 | |
846 if (strcmp(vdl->path, "/") != 0) | |
847 { | |
138 | 848 filepath = g_strconcat(vdl->path, "/", "..", NULL); |
849 fd = file_data_new_simple(filepath); | |
9 | 850 vdl->list = g_list_prepend(vdl->list, fd); |
138 | 851 g_free(filepath); |
9 | 852 } |
138 | 853 filepath = g_strconcat(vdl->path, "/", ".", NULL); |
854 fd = file_data_new_simple(filepath); | |
9 | 855 vdl->list = g_list_prepend(vdl->list, fd); |
138 | 856 g_free(filepath); |
9 | 857 |
858 vdlist_populate(vdl); | |
859 | |
860 if (old_path) | |
861 { | |
862 /* scroll to make last path visible */ | |
863 FileData *found = NULL; | |
864 GList *work; | |
865 | |
866 work = vdl->list; | |
867 while (work && !found) | |
868 { | |
869 FileData *fd = work->data; | |
870 if (strcmp(old_path, fd->name) == 0) found = fd; | |
871 work = work->next; | |
872 } | |
873 | |
874 if (found) vdlist_scroll_to_row(vdl, found, 0.5); | |
875 | |
876 g_free(old_path); | |
877 return ret; | |
878 } | |
879 | |
880 if (GTK_WIDGET_REALIZED(vdl->listview)) | |
881 { | |
882 gtk_tree_view_scroll_to_point(GTK_TREE_VIEW(vdl->listview), 0, 0); | |
883 } | |
884 | |
885 return ret; | |
886 } | |
887 | |
888 void vdlist_refresh(ViewDirList *vdl) | |
889 { | |
890 gchar *path; | |
891 | |
892 path = g_strdup(vdl->path); | |
893 vdl->path = NULL; | |
894 vdlist_set_path(vdl, path); | |
895 g_free(path); | |
896 } | |
897 | |
898 static void vdlist_menu_position_cb(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer data) | |
899 { | |
900 ViewDirList *vdl = data; | |
901 GtkTreeModel *store; | |
902 GtkTreeIter iter; | |
903 GtkTreePath *tpath; | |
904 gint cw, ch; | |
905 | |
906 if (vdlist_find_row(vdl, vdl->click_fd, &iter) < 0) return; | |
907 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vdl->listview)); | |
908 tpath = gtk_tree_model_get_path(store, &iter); | |
909 tree_view_get_cell_clamped(GTK_TREE_VIEW(vdl->listview), tpath, 0, TRUE, x, y, &cw, &ch); | |
910 gtk_tree_path_free(tpath); | |
911 *y += ch; | |
912 popup_menu_position_clamp(menu, x, y, 0); | |
913 } | |
914 | |
915 static gint vdlist_press_key_cb(GtkWidget *widget, GdkEventKey *event, gpointer data) | |
916 { | |
917 ViewDirList *vdl = data; | |
918 GtkTreePath *tpath; | |
919 | |
920 if (event->keyval != GDK_Menu) return FALSE; | |
921 | |
922 gtk_tree_view_get_cursor(GTK_TREE_VIEW(vdl->listview), &tpath, NULL); | |
923 if (tpath) | |
924 { | |
925 GtkTreeModel *store; | |
926 GtkTreeIter iter; | |
927 | |
928 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget)); | |
929 gtk_tree_model_get_iter(store, &iter, tpath); | |
930 gtk_tree_model_get(store, &iter, DIR_COLUMN_POINTER, &vdl->click_fd, -1); | |
931 | |
932 gtk_tree_path_free(tpath); | |
933 } | |
934 else | |
935 { | |
936 vdl->click_fd = NULL; | |
937 } | |
938 | |
939 vdlist_color_set(vdl, vdl->click_fd, TRUE); | |
940 | |
941 vdl->popup = vdlist_pop_menu(vdl, vdl->click_fd); | |
942 | |
943 gtk_menu_popup(GTK_MENU(vdl->popup), NULL, NULL, vdlist_menu_position_cb, vdl, 0, GDK_CURRENT_TIME); | |
944 | |
945 return TRUE; | |
946 } | |
947 | |
948 static gint vdlist_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data) | |
949 { | |
950 ViewDirList *vdl = data; | |
951 GtkTreePath *tpath; | |
952 GtkTreeIter iter; | |
953 FileData *fd = NULL; | |
954 | |
955 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), bevent->x, bevent->y, | |
956 &tpath, NULL, NULL, NULL)) | |
957 { | |
958 GtkTreeModel *store; | |
959 | |
960 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget)); | |
961 gtk_tree_model_get_iter(store, &iter, tpath); | |
962 gtk_tree_model_get(store, &iter, DIR_COLUMN_POINTER, &fd, -1); | |
963 gtk_tree_view_set_cursor(GTK_TREE_VIEW(widget), tpath, NULL, FALSE); | |
964 gtk_tree_path_free(tpath); | |
965 } | |
966 | |
967 vdl->click_fd = fd; | |
968 vdlist_color_set(vdl, vdl->click_fd, TRUE); | |
969 | |
970 if (bevent->button == 3) | |
971 { | |
972 vdl->popup = vdlist_pop_menu(vdl, vdl->click_fd); | |
973 gtk_menu_popup(GTK_MENU(vdl->popup), NULL, NULL, NULL, NULL, | |
974 bevent->button, bevent->time); | |
975 } | |
976 | |
977 return TRUE; | |
978 } | |
979 | |
980 static gint vdlist_release_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data) | |
981 { | |
982 ViewDirList *vdl = data; | |
983 GtkTreePath *tpath; | |
984 GtkTreeIter iter; | |
985 FileData *fd = NULL; | |
986 | |
987 vdlist_color_set(vdl, vdl->click_fd, FALSE); | |
988 | |
989 if (bevent->button != 1) return TRUE; | |
990 | |
991 if ((bevent->x != 0 || bevent->y != 0) && | |
992 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), bevent->x, bevent->y, | |
993 &tpath, NULL, NULL, NULL)) | |
994 { | |
995 GtkTreeModel *store; | |
996 | |
997 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget)); | |
998 gtk_tree_model_get_iter(store, &iter, tpath); | |
999 gtk_tree_model_get(store, &iter, DIR_COLUMN_POINTER, &fd, -1); | |
1000 gtk_tree_path_free(tpath); | |
1001 } | |
1002 | |
1003 if (fd && vdl->click_fd == fd) | |
1004 { | |
1005 vdlist_select_row(vdl, vdl->click_fd); | |
1006 } | |
1007 | |
1008 return TRUE; | |
1009 } | |
1010 | |
1011 static void vdlist_select_cb(GtkTreeView *tview, GtkTreePath *tpath, GtkTreeViewColumn *column, gpointer data) | |
1012 { | |
1013 ViewDirList *vdl = data; | |
1014 GtkTreeModel *store; | |
1015 GtkTreeIter iter; | |
1016 FileData *fd; | |
1017 | |
1018 store = gtk_tree_view_get_model(tview); | |
1019 gtk_tree_model_get_iter(store, &iter, tpath); | |
1020 gtk_tree_model_get(store, &iter, DIR_COLUMN_POINTER, &fd, -1); | |
1021 | |
1022 vdlist_select_row(vdl, fd); | |
1023 } | |
1024 | |
1025 static GdkColor *vdlist_color_shifted(GtkWidget *widget) | |
1026 { | |
1027 static GdkColor color; | |
1028 static GtkWidget *done = NULL; | |
1029 | |
1030 if (done != widget) | |
1031 { | |
1032 GtkStyle *style; | |
1033 | |
1034 style = gtk_widget_get_style(widget); | |
1035 memcpy(&color, &style->base[GTK_STATE_NORMAL], sizeof(color)); | |
1036 shift_color(&color, -1, 0); | |
1037 done = widget; | |
1038 } | |
1039 | |
1040 return &color; | |
1041 } | |
1042 | |
1043 static void vdlist_color_cb(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, | |
1044 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data) | |
1045 { | |
1046 ViewDirList *vdl = data; | |
1047 gboolean set; | |
1048 | |
1049 gtk_tree_model_get(tree_model, iter, DIR_COLUMN_COLOR, &set, -1); | |
1050 g_object_set(G_OBJECT(cell), | |
1051 "cell-background-gdk", vdlist_color_shifted(vdl->listview), | |
1052 "cell-background-set", set, NULL); | |
1053 } | |
1054 | |
1055 static void vdlist_destroy_cb(GtkWidget *widget, gpointer data) | |
1056 { | |
1057 ViewDirList *vdl = data; | |
1058 | |
1059 if (vdl->popup) | |
1060 { | |
1061 g_signal_handlers_disconnect_matched(G_OBJECT(vdl->popup), G_SIGNAL_MATCH_DATA, | |
1062 0, 0, 0, NULL, vdl); | |
1063 gtk_widget_destroy(vdl->popup); | |
1064 } | |
1065 | |
1066 vdlist_dnd_drop_scroll_cancel(vdl); | |
1067 widget_auto_scroll_stop(vdl->listview); | |
1068 | |
138 | 1069 filelist_free(vdl->drop_list); |
9 | 1070 |
1071 folder_icons_free(vdl->pf); | |
1072 | |
1073 g_free(vdl->path); | |
1074 filelist_free(vdl->list); | |
1075 g_free(vdl); | |
1076 } | |
1077 | |
1078 ViewDirList *vdlist_new(const gchar *path) | |
1079 { | |
1080 ViewDirList *vdl; | |
1081 GtkListStore *store; | |
1082 GtkTreeSelection *selection; | |
1083 GtkTreeViewColumn *column; | |
1084 GtkCellRenderer *renderer; | |
1085 | |
1086 vdl = g_new0(ViewDirList, 1); | |
1087 | |
1088 vdl->path = NULL; | |
1089 vdl->list = NULL; | |
1090 vdl->click_fd = NULL; | |
1091 | |
1092 vdl->drop_fd = NULL; | |
1093 vdl->drop_list = NULL; | |
1094 | |
1095 vdl->drop_scroll_id = -1; | |
1096 | |
1097 vdl->popup = NULL; | |
1098 | |
1099 vdl->widget = gtk_scrolled_window_new(NULL, NULL); | |
1100 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(vdl->widget), GTK_SHADOW_IN); | |
1101 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(vdl->widget), | |
1102 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); | |
1103 g_signal_connect(G_OBJECT(vdl->widget), "destroy", | |
1104 G_CALLBACK(vdlist_destroy_cb), vdl); | |
1105 | |
1106 store = gtk_list_store_new(4, G_TYPE_POINTER, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_BOOLEAN); | |
1107 vdl->listview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); | |
1108 g_object_unref(store); | |
1109 | |
1110 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(vdl->listview), FALSE); | |
1111 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(vdl->listview), FALSE); | |
1112 g_signal_connect(G_OBJECT(vdl->listview), "row_activated", | |
1113 | |
1114 G_CALLBACK(vdlist_select_cb), vdl); | |
1115 | |
1116 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vdl->listview)); | |
1117 gtk_tree_selection_set_mode(selection, GTK_SELECTION_NONE); | |
1118 | |
1119 column = gtk_tree_view_column_new(); | |
1120 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); | |
1121 | |
1122 renderer = gtk_cell_renderer_pixbuf_new(); | |
1123 gtk_tree_view_column_pack_start(column, renderer, FALSE); | |
1124 gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", DIR_COLUMN_ICON); | |
1125 gtk_tree_view_column_set_cell_data_func(column, renderer, vdlist_color_cb, vdl, NULL); | |
1126 | |
1127 renderer = gtk_cell_renderer_text_new(); | |
1128 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
1129 gtk_tree_view_column_add_attribute(column, renderer, "text", DIR_COLUMN_NAME); | |
1130 gtk_tree_view_column_set_cell_data_func(column, renderer, vdlist_color_cb, vdl, NULL); | |
1131 | |
1132 gtk_tree_view_append_column(GTK_TREE_VIEW(vdl->listview), column); | |
1133 | |
1134 g_signal_connect(G_OBJECT(vdl->listview), "key_press_event", | |
1135 G_CALLBACK(vdlist_press_key_cb), vdl); | |
1136 gtk_container_add(GTK_CONTAINER(vdl->widget), vdl->listview); | |
1137 gtk_widget_show(vdl->listview); | |
1138 | |
1139 vdl->pf = folder_icons_new(); | |
1140 | |
1141 vdlist_dnd_init(vdl); | |
1142 | |
1143 g_signal_connect(G_OBJECT(vdl->listview), "button_press_event", | |
1144 G_CALLBACK(vdlist_press_cb), vdl); | |
1145 g_signal_connect(G_OBJECT(vdl->listview), "button_release_event", | |
1146 G_CALLBACK(vdlist_release_cb), vdl); | |
1147 | |
1148 if (path) vdlist_set_path(vdl, path); | |
1149 | |
1150 return vdl; | |
1151 } | |
1152 | |
1153 void vdlist_set_select_func(ViewDirList *vdl, | |
1154 void (*func)(ViewDirList *vdl, const gchar *path, gpointer data), gpointer data) | |
1155 { | |
1156 vdl->select_func = func; | |
1157 vdl->select_data = data; | |
1158 } | |
1159 | |
1160 void vdlist_set_layout(ViewDirList *vdl, LayoutWindow *layout) | |
1161 { | |
1162 vdl->layout = layout; | |
1163 } | |
1164 |