4 * Copyright (C) 2008 The Geeqie Team
8 * This software is released under the GNU General Public License (GNU GPL).
9 * Please read the included file COPYING for more information.
10 * This software comes with no warranty of any kind, use at your own risk!
14 #include "view_file_list.h"
16 #include "cache_maint.h"
22 #include "layout_image.h"
26 #include "ui_bookmark.h"
27 #include "ui_fileops.h"
29 #include "ui_tree_edit.h"
30 #include "view_file.h"
32 #include <gdk/gdkkeysyms.h> /* for keyboard values */
36 FILE_COLUMN_POINTER = 0,
45 FILE_COLUMN_MARKS_LAST = FILE_COLUMN_MARKS + FILEDATA_MARKS_SIZE - 1,
50 static gint vflist_row_is_selected(ViewFile *vf, FileData *fd);
51 static gint vflist_row_rename_cb(TreeEditData *td, const gchar *old, const gchar *new, gpointer data);
52 static void vflist_populate_view(ViewFile *vf);
56 *-----------------------------------------------------------------------------
58 *-----------------------------------------------------------------------------
65 } ViewFileFindRowData;
67 static gboolean vflist_find_row_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
69 ViewFileFindRowData *find = data;
71 gtk_tree_model_get(model, iter, FILE_COLUMN_POINTER, &fd, -1);
82 static gint vflist_find_row(ViewFile *vf, FileData *fd, GtkTreeIter *iter)
85 ViewFileFindRowData data = {fd, iter, 0, 0};
87 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
88 gtk_tree_model_foreach(store, vflist_find_row_cb, &data);
100 static gint vflist_find_sidecar_list_idx(GList *work, FileData *fd)
105 FileData *fd_p = work->data;
106 if (fd == fd_p) return i;
110 GList *work2 = fd_p->sidecar_files;
114 if (fd == fd_p) return i;
125 static gint vflist_sidecar_list_count(GList *work)
130 FileData *fd = work->data;
133 GList *work2 = fd->sidecar_files;
144 static gboolean vflist_store_clear_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
147 gtk_tree_model_get(model, iter, FILE_COLUMN_POINTER, &fd, -1);
152 static void vflist_store_clear(ViewFile *vf)
155 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
156 gtk_tree_model_foreach(store, vflist_store_clear_cb, NULL);
157 gtk_tree_store_clear(GTK_TREE_STORE(store));
160 void vflist_color_set(ViewFile *vf, FileData *fd, gint color_set)
165 if (vflist_find_row(vf, fd, &iter) < 0) return;
166 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
167 gtk_tree_store_set(GTK_TREE_STORE(store), &iter, FILE_COLUMN_COLOR, color_set, -1);
170 static void vflist_move_cursor(ViewFile *vf, GtkTreeIter *iter)
175 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
177 tpath = gtk_tree_model_get_path(store, iter);
178 gtk_tree_view_set_cursor(GTK_TREE_VIEW(vf->listview), tpath, NULL, FALSE);
179 gtk_tree_path_free(tpath);
183 static gint vflist_column_idx(ViewFile *vf, gint store_idx)
185 GList *columns, *work;
188 columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(vf->listview));
192 GtkTreeViewColumn *column = work->data;
193 if (store_idx == GPOINTER_TO_INT(g_object_get_data (G_OBJECT(column), "column_store_idx")))
199 g_list_free(columns);
205 *-----------------------------------------------------------------------------
207 *-----------------------------------------------------------------------------
210 static void vflist_dnd_get(GtkWidget *widget, GdkDragContext *context,
211 GtkSelectionData *selection_data, guint info,
212 guint time, gpointer data)
216 gchar *uri_text = NULL;
219 if (!VFLIST_INFO(vf, click_fd)) return;
221 if (vflist_row_is_selected(vf, VFLIST_INFO(vf, click_fd)))
223 list = vf_selection_get_list(vf);
227 list = g_list_append(NULL, file_data_ref(VFLIST_INFO(vf, click_fd)));
232 uri_text = uri_text_from_filelist(list, &total, (info == TARGET_TEXT_PLAIN));
237 gtk_selection_data_set(selection_data, selection_data->target,
238 8, (guchar *)uri_text, total);
242 static void vflist_dnd_begin(GtkWidget *widget, GdkDragContext *context, gpointer data)
246 vflist_color_set(vf, VFLIST_INFO(vf, click_fd), TRUE);
248 if (VFLIST_INFO(vf, thumbs_enabled) &&
249 VFLIST_INFO(vf, click_fd) && VFLIST_INFO(vf, click_fd)->pixbuf)
253 if (vflist_row_is_selected(vf, VFLIST_INFO(vf, click_fd)))
254 items = vf_selection_count(vf, NULL);
258 dnd_set_drag_icon(widget, context, VFLIST_INFO(vf, click_fd)->pixbuf, items);
262 static void vflist_dnd_end(GtkWidget *widget, GdkDragContext *context, gpointer data)
266 vflist_color_set(vf, VFLIST_INFO(vf, click_fd), FALSE);
268 if (context->action == GDK_ACTION_MOVE)
274 void vflist_dnd_init(ViewFile *vf)
276 gtk_drag_source_set(vf->listview, GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
277 dnd_file_drag_types, dnd_file_drag_types_count,
278 GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK);
279 g_signal_connect(G_OBJECT(vf->listview), "drag_data_get",
280 G_CALLBACK(vflist_dnd_get), vf);
281 g_signal_connect(G_OBJECT(vf->listview), "drag_begin",
282 G_CALLBACK(vflist_dnd_begin), vf);
283 g_signal_connect(G_OBJECT(vf->listview), "drag_end",
284 G_CALLBACK(vflist_dnd_end), vf);
288 *-----------------------------------------------------------------------------
290 *-----------------------------------------------------------------------------
293 GList *vflist_pop_menu_file_list(ViewFile *vf)
295 if (!VFLIST_INFO(vf, click_fd)) return NULL;
297 if (vflist_row_is_selected(vf, VFLIST_INFO(vf, click_fd)))
299 return vf_selection_get_list(vf);
302 return g_list_append(NULL, file_data_ref(VFLIST_INFO(vf, click_fd)));
305 void vflist_pop_menu_view_cb(GtkWidget *widget, gpointer data)
309 if (vflist_row_is_selected(vf, VFLIST_INFO(vf, click_fd)))
313 list = vf_selection_get_list(vf);
314 view_window_new_from_list(list);
319 view_window_new(VFLIST_INFO(vf, click_fd));
323 void vflist_pop_menu_rename_cb(GtkWidget *widget, gpointer data)
328 list = vf_pop_menu_file_list(vf);
329 if (options->file_ops.enable_in_place_rename &&
330 list && !list->next && VFLIST_INFO(vf, click_fd))
337 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
338 if (vflist_find_row(vf, VFLIST_INFO(vf, click_fd), &iter) >= 0)
342 tpath = gtk_tree_model_get_path(store, &iter);
343 tree_edit_by_path(GTK_TREE_VIEW(vf->listview), tpath,
344 vflist_column_idx(vf, FILE_COLUMN_NAME), VFLIST_INFO(vf, click_fd)->name,
345 vflist_row_rename_cb, vf);
346 gtk_tree_path_free(tpath);
351 file_util_rename(NULL, list, vf->listview);
354 void vflist_pop_menu_thumbs_cb(GtkWidget *widget, gpointer data)
358 vflist_color_set(vf, VFLIST_INFO(vf, click_fd), FALSE);
361 layout_thumb_set(vf->layout, !VFLIST_INFO(vf, thumbs_enabled));
365 vflist_thumb_set(vf, !VFLIST_INFO(vf, thumbs_enabled));
369 void vflist_pop_menu_refresh_cb(GtkWidget *widget, gpointer data)
373 vflist_color_set(vf, VFLIST_INFO(vf, click_fd), FALSE);
377 void vflist_popup_destroy_cb(GtkWidget *widget, gpointer data)
380 vflist_color_set(vf, VFLIST_INFO(vf, click_fd), FALSE);
381 VFLIST_INFO(vf, click_fd) = NULL;
387 *-----------------------------------------------------------------------------
389 *-----------------------------------------------------------------------------
392 static gint vflist_row_rename_cb(TreeEditData *td, const gchar *old, const gchar *new, gpointer data)
398 if (strlen(new) == 0) return FALSE;
400 old_path = g_build_filename(vf->dir_fd->path, old, NULL);
401 new_path = g_build_filename(vf->dir_fd->path, new, NULL);
403 if (strchr(new, G_DIR_SEPARATOR) != NULL)
405 gchar *text = g_strdup_printf(_("Invalid file name:\n%s"), new);
406 file_util_warning_dialog(_("Error renaming file"), text, GTK_STOCK_DIALOG_ERROR, vf->listview);
409 else if (isfile(new_path))
411 gchar *text = g_strdup_printf(_("A file with name %s already exists."), new);
412 file_util_warning_dialog(_("Error renaming file"), text, GTK_STOCK_DIALOG_ERROR, vf->listview);
417 gint row = vf_index_by_path(vf, old_path);
420 GList *work = g_list_nth(vf->list, row);
421 FileData *fd = work->data;
423 file_util_rename_simple(fd, new_path, vf->listview);
434 static void vflist_menu_position_cb(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer data)
442 if (vflist_find_row(vf, VFLIST_INFO(vf, click_fd), &iter) < 0) return;
443 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
444 tpath = gtk_tree_model_get_path(store, &iter);
445 tree_view_get_cell_clamped(GTK_TREE_VIEW(vf->listview), tpath, FILE_COLUMN_NAME - 1, TRUE, x, y, &cw, &ch);
446 gtk_tree_path_free(tpath);
448 popup_menu_position_clamp(menu, x, y, 0);
451 gint vflist_press_key_cb(GtkWidget *widget, GdkEventKey *event, gpointer data)
456 if (event->keyval != GDK_Menu) return FALSE;
458 gtk_tree_view_get_cursor(GTK_TREE_VIEW(vf->listview), &tpath, NULL);
464 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
465 gtk_tree_model_get_iter(store, &iter, tpath);
466 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &VFLIST_INFO(vf, click_fd), -1);
467 gtk_tree_path_free(tpath);
471 VFLIST_INFO(vf, click_fd) = NULL;
474 vf->popup = vf_pop_menu(vf);
475 gtk_menu_popup(GTK_MENU(vf->popup), NULL, NULL, vflist_menu_position_cb, vf, 0, GDK_CURRENT_TIME);
480 gint vflist_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
486 GtkTreeViewColumn *column;
488 vf->clicked_mark = 0;
490 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), bevent->x, bevent->y,
491 &tpath, &column, NULL, NULL))
494 gint col_idx = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(column), "column_store_idx"));
496 if (bevent->button == MOUSE_BUTTON_LEFT &&
497 col_idx >= FILE_COLUMN_MARKS && col_idx <= FILE_COLUMN_MARKS_LAST)
500 if (col_idx >= FILE_COLUMN_MARKS && col_idx <= FILE_COLUMN_MARKS_LAST)
501 vf->clicked_mark = 1 + (col_idx - FILE_COLUMN_MARKS);
503 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
505 gtk_tree_model_get_iter(store, &iter, tpath);
506 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
508 gtk_tree_view_set_cursor(GTK_TREE_VIEW(widget), tpath, NULL, FALSE);
510 gtk_tree_path_free(tpath);
513 VFLIST_INFO(vf, click_fd) = fd;
515 if (bevent->button == MOUSE_BUTTON_RIGHT)
517 vf->popup = vf_pop_menu(vf);
518 gtk_menu_popup(GTK_MENU(vf->popup), NULL, NULL, NULL, NULL,
519 bevent->button, bevent->time);
523 if (!fd) return FALSE;
525 if (bevent->button == MOUSE_BUTTON_MIDDLE)
527 if (!vflist_row_is_selected(vf, fd))
529 vflist_color_set(vf, fd, TRUE);
535 if (bevent->button == MOUSE_BUTTON_LEFT && bevent->type == GDK_BUTTON_PRESS &&
536 !(bevent->state & GDK_SHIFT_MASK ) &&
537 !(bevent->state & GDK_CONTROL_MASK ) &&
538 vflist_row_is_selected(vf, fd))
540 GtkTreeSelection *selection;
542 gtk_widget_grab_focus(widget);
545 /* returning FALSE and further processing of the event is needed for
546 correct operation of the expander, to show the sidecar files.
547 It however resets the selection of multiple files. With this condition
548 it should work for both cases */
549 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
550 return (gtk_tree_selection_count_selected_rows(selection) > 1);
554 if (bevent->button == MOUSE_BUTTON_LEFT && bevent->type == GDK_2BUTTON_PRESS)
556 if (vf->layout) layout_image_full_screen_start(vf->layout);
563 gint vflist_release_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
570 if (bevent->button == MOUSE_BUTTON_MIDDLE)
572 vflist_color_set(vf, VFLIST_INFO(vf, click_fd), FALSE);
575 if (bevent->button != MOUSE_BUTTON_LEFT && bevent->button != MOUSE_BUTTON_MIDDLE)
580 if ((bevent->x != 0 || bevent->y != 0) &&
581 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), bevent->x, bevent->y,
582 &tpath, NULL, NULL, NULL))
586 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
587 gtk_tree_model_get_iter(store, &iter, tpath);
588 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
589 gtk_tree_path_free(tpath);
592 if (bevent->button == MOUSE_BUTTON_MIDDLE)
594 if (fd && VFLIST_INFO(vf, click_fd) == fd)
596 GtkTreeSelection *selection;
598 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
599 if (vflist_row_is_selected(vf, fd))
601 gtk_tree_selection_unselect_iter(selection, &iter);
605 gtk_tree_selection_select_iter(selection, &iter);
611 if (fd && VFLIST_INFO(vf, click_fd) == fd &&
612 !(bevent->state & GDK_SHIFT_MASK ) &&
613 !(bevent->state & GDK_CONTROL_MASK ) &&
614 vflist_row_is_selected(vf, fd))
616 GtkTreeSelection *selection;
618 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
619 gtk_tree_selection_unselect_all(selection);
620 gtk_tree_selection_select_iter(selection, &iter);
621 vflist_move_cursor(vf, &iter);
622 // return TRUE;// FIXME - expand
628 static void vflist_select_image(ViewFile *vf, FileData *sel_fd)
630 FileData *read_ahead_fd = NULL;
635 cur_fd = layout_image_get_fd(vf->layout);
636 if (sel_fd == cur_fd) return; /* no change */
638 row = g_list_index(vf->list, sel_fd);
639 // FIXME sidecar data
641 if (sel_fd && options->image.enable_read_ahead && row >= 0)
643 if (row > g_list_index(vf->list, cur_fd) &&
644 (guint) (row + 1) < vf_count(vf, NULL))
646 read_ahead_fd = vf_index_get_data(vf, row + 1);
650 read_ahead_fd = vf_index_get_data(vf, row - 1);
654 layout_image_set_with_ahead(vf->layout, sel_fd, read_ahead_fd);
657 static gint vflist_select_idle_cb(gpointer data)
663 VFLIST_INFO(vf, select_idle_id) = -1;
669 if (VFLIST_INFO(vf, select_fd))
671 vflist_select_image(vf, VFLIST_INFO(vf, select_fd));
672 VFLIST_INFO(vf, select_fd) = NULL;
675 VFLIST_INFO(vf, select_idle_id) = -1;
679 static void vflist_select_idle_cancel(ViewFile *vf)
681 if (VFLIST_INFO(vf, select_idle_id) != -1) g_source_remove(VFLIST_INFO(vf, select_idle_id));
682 VFLIST_INFO(vf, select_idle_id) = -1;
685 static gboolean vflist_select_cb(GtkTreeSelection *selection, GtkTreeModel *store, GtkTreePath *tpath,
686 gboolean path_currently_selected, gpointer data)
691 if (!path_currently_selected &&
692 gtk_tree_model_get_iter(store, &iter, tpath))
694 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &VFLIST_INFO(vf, select_fd), -1);
698 VFLIST_INFO(vf, select_fd) = NULL;
702 VFLIST_INFO(vf, select_idle_id) == -1)
704 VFLIST_INFO(vf, select_idle_id) = g_idle_add(vflist_select_idle_cb, vf);
711 *-----------------------------------------------------------------------------
713 *-----------------------------------------------------------------------------
717 static gboolean vflist_dummy_select_cb(GtkTreeSelection *selection, GtkTreeModel *store, GtkTreePath *tpath,
718 gboolean path_currently_selected, gpointer data)
724 static void vflist_setup_iter(ViewFile *vf, GtkTreeStore *store, GtkTreeIter *iter, FileData *fd)
728 gchar *sidecars = NULL;
730 if (fd->sidecar_files)
731 sidecars = file_data_sc_list_to_string(fd);
732 size = text_from_size(fd->size);
734 gtk_tree_store_set(store, iter, FILE_COLUMN_POINTER, fd,
735 FILE_COLUMN_VERSION, fd->version,
736 FILE_COLUMN_THUMB, fd->pixbuf,
737 FILE_COLUMN_NAME, fd->name,
738 FILE_COLUMN_SIDECARS, sidecars,
739 FILE_COLUMN_SIZE, size,
740 FILE_COLUMN_DATE, text_from_time(fd->date),
741 FILE_COLUMN_COLOR, FALSE, -1);
742 for (i = 0; i < FILEDATA_MARKS_SIZE; i++)
743 gtk_tree_store_set(store, iter, FILE_COLUMN_MARKS + i, file_data_get_mark(fd, i), -1);
750 static void vflist_setup_iter_recursive(ViewFile *vf, GtkTreeStore *store, GtkTreeIter *parent_iter, GList *list, GList *selected)
756 valid = gtk_tree_model_iter_children(GTK_TREE_MODEL(store), &iter, parent_iter);
762 FileData *fd = work->data;
767 FileData *old_fd = NULL;
768 gint old_version = 0;
772 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
773 FILE_COLUMN_POINTER, &old_fd,
774 FILE_COLUMN_VERSION, &old_version,
784 match = filelist_sort_compare_filedata_full(fd, old_fd, SORT_NAME, TRUE); /* always sort sidecars by name */
786 match = filelist_sort_compare_filedata_full(fd, old_fd, vf->sort_method, vf->sort_ascend);
788 if (match == 0) g_warning("multiple fd for the same path");
803 gtk_tree_store_insert_before(store, &new, parent_iter, &iter);
807 gtk_tree_store_append(store, &new, parent_iter);
810 vflist_setup_iter(vf, store, &new, file_data_ref(fd));
811 vflist_setup_iter_recursive(vf, store, &new, fd->sidecar_files, selected);
813 if (g_list_find(selected, fd))
815 /* renamed files - the same fd appears at different position - select it again*/
816 GtkTreeSelection *selection;
817 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
818 gtk_tree_selection_select_iter(selection, &new);
825 file_data_unref(old_fd);
826 valid = gtk_tree_store_remove(store, &iter);
830 if (fd->version != old_version)
832 vflist_setup_iter(vf, store, &iter, fd);
833 vflist_setup_iter_recursive(vf, store, &iter, fd->sidecar_files, selected);
836 if (valid) valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
847 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, FILE_COLUMN_POINTER, &old_fd, -1);
848 file_data_unref(old_fd);
850 valid = gtk_tree_store_remove(store, &iter);
854 void vflist_sort_set(ViewFile *vf, SortType type, gint ascend)
857 GHashTable *fd_idx_hash = g_hash_table_new(NULL, NULL);
862 if (vf->sort_method == type && vf->sort_ascend == ascend) return;
863 if (!vf->list) return;
869 FileData *fd = work->data;
870 g_hash_table_insert(fd_idx_hash, fd, GINT_TO_POINTER(i));
875 vf->sort_method = type;
876 vf->sort_ascend = ascend;
878 vf->list = filelist_sort(vf->list, vf->sort_method, vf->sort_ascend);
880 new_order = g_malloc(i * sizeof(gint));
886 FileData *fd = work->data;
887 new_order[i] = GPOINTER_TO_INT(g_hash_table_lookup(fd_idx_hash, fd));
892 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
893 gtk_tree_store_reorder(store, NULL, new_order);
896 g_hash_table_destroy(fd_idx_hash);
900 *-----------------------------------------------------------------------------
902 *-----------------------------------------------------------------------------
905 static gint vflist_thumb_next(ViewFile *vf);
907 static void vflist_thumb_status(ViewFile *vf, gdouble val, const gchar *text)
909 if (vf->func_thumb_status)
911 vf->func_thumb_status(vf, val, text, vf->data_thumb_status);
915 static void vflist_thumb_cleanup(ViewFile *vf)
917 vflist_thumb_status(vf, 0.0, NULL);
919 vf->thumbs_count = 0;
920 vf->thumbs_running = FALSE;
922 thumb_loader_free(vf->thumbs_loader);
923 vf->thumbs_loader = NULL;
925 vf->thumbs_filedata = NULL;
928 static void vflist_thumb_stop(ViewFile *vf)
930 if (vf->thumbs_running) vflist_thumb_cleanup(vf);
933 static void vflist_thumb_do(ViewFile *vf, ThumbLoader *tl, FileData *fd)
938 if (!fd || vflist_find_row(vf, fd, &iter) < 0) return;
940 if (fd->pixbuf) g_object_unref(fd->pixbuf);
941 fd->pixbuf = thumb_loader_get_pixbuf(tl, TRUE);
943 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
944 gtk_tree_store_set(store, &iter, FILE_COLUMN_THUMB, fd->pixbuf, -1);
946 vflist_thumb_status(vf, (gdouble)(vf->thumbs_count) / vflist_sidecar_list_count(vf->list), _("Loading thumbs..."));
949 static void vflist_thumb_error_cb(ThumbLoader *tl, gpointer data)
953 if (vf->thumbs_filedata && vf->thumbs_loader == tl)
955 vflist_thumb_do(vf, tl, vf->thumbs_filedata);
958 while (vflist_thumb_next(vf));
961 static void vflist_thumb_done_cb(ThumbLoader *tl, gpointer data)
965 if (vf->thumbs_filedata && vf->thumbs_loader == tl)
967 vflist_thumb_do(vf, tl, vf->thumbs_filedata);
970 while (vflist_thumb_next(vf));
973 static gint vflist_thumb_next(ViewFile *vf)
978 /* first check the visible files */
980 if (GTK_WIDGET_REALIZED(vf->listview) &&
981 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(vf->listview), 0, 0, &tpath, NULL, NULL, NULL))
987 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
988 gtk_tree_model_get_iter(store, &iter, tpath);
989 gtk_tree_path_free(tpath);
991 while (!fd && valid && tree_view_row_get_visibility(GTK_TREE_VIEW(vf->listview), &iter, FALSE) == 0)
993 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
994 if (fd->pixbuf) fd = NULL;
996 valid = gtk_tree_model_iter_next(store, &iter);
1000 /* then find first undone */
1004 GList *work = vf->list;
1007 FileData *fd_p = work->data;
1012 GList *work2 = fd_p->sidecar_files;
1014 while (work2 && !fd)
1017 if (!fd_p->pixbuf) fd = fd_p;
1018 work2 = work2->next;
1028 vflist_thumb_cleanup(vf);
1034 vf->thumbs_filedata = fd;
1036 thumb_loader_free(vf->thumbs_loader);
1038 vf->thumbs_loader = thumb_loader_new(options->thumbnails.max_width, options->thumbnails.max_height);
1039 thumb_loader_set_callbacks(vf->thumbs_loader,
1040 vflist_thumb_done_cb,
1041 vflist_thumb_error_cb,
1045 if (!thumb_loader_start(vf->thumbs_loader, fd->path))
1047 /* set icon to unknown, continue */
1048 DEBUG_1("thumb loader start failed %s", vf->thumbs_loader->path);
1049 vflist_thumb_do(vf, vf->thumbs_loader, fd);
1057 static void vflist_thumb_update(ViewFile *vf)
1059 vflist_thumb_stop(vf);
1060 if (!VFLIST_INFO(vf, thumbs_enabled)) return;
1062 vflist_thumb_status(vf, 0.0, _("Loading thumbs..."));
1063 vf->thumbs_running = TRUE;
1065 while (vflist_thumb_next(vf));
1069 *-----------------------------------------------------------------------------
1071 *-----------------------------------------------------------------------------
1074 FileData *vflist_index_get_data(ViewFile *vf, gint row)
1076 return g_list_nth_data(vf->list, row);
1079 gint vflist_index_by_path(ViewFile *vf, const gchar *path)
1084 if (!path) return -1;
1089 FileData *fd = work->data;
1090 if (strcmp(path, fd->path) == 0) return p;
1099 guint vflist_count(ViewFile *vf, gint64 *bytes)
1109 FileData *fd = work->data;
1117 return g_list_length(vf->list);
1120 GList *vflist_get_list(ViewFile *vf)
1128 FileData *fd = work->data;
1131 list = g_list_prepend(list, file_data_ref(fd));
1134 return g_list_reverse(list);
1138 *-----------------------------------------------------------------------------
1140 *-----------------------------------------------------------------------------
1143 static gint vflist_row_is_selected(ViewFile *vf, FileData *fd)
1145 GtkTreeModel *store;
1146 GtkTreeSelection *selection;
1151 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1152 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1154 while (!found && work)
1156 GtkTreePath *tpath = work->data;
1160 gtk_tree_model_get_iter(store, &iter, tpath);
1161 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd_n, -1);
1162 if (fd_n == fd) found = TRUE;
1165 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1171 gint vflist_index_is_selected(ViewFile *vf, gint row)
1175 fd = vf_index_get_data(vf, row);
1176 return vflist_row_is_selected(vf, fd);
1179 guint vflist_selection_count(ViewFile *vf, gint64 *bytes)
1181 GtkTreeModel *store;
1182 GtkTreeSelection *selection;
1186 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1187 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1197 GtkTreePath *tpath = work->data;
1201 gtk_tree_model_get_iter(store, &iter, tpath);
1202 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
1211 count = g_list_length(slist);
1212 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1218 GList *vflist_selection_get_list(ViewFile *vf)
1220 GtkTreeModel *store;
1221 GtkTreeSelection *selection;
1226 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1227 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1231 GtkTreePath *tpath = work->data;
1235 gtk_tree_model_get_iter(store, &iter, tpath);
1236 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
1238 list = g_list_prepend(list, file_data_ref(fd));
1242 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1245 return g_list_reverse(list);
1248 GList *vflist_selection_get_list_by_index(ViewFile *vf)
1250 GtkTreeModel *store;
1251 GtkTreeSelection *selection;
1256 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1257 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1261 GtkTreePath *tpath = work->data;
1265 gtk_tree_model_get_iter(store, &iter, tpath);
1266 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
1268 list = g_list_prepend(list, GINT_TO_POINTER(g_list_index(vf->list, fd)));
1272 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1275 return g_list_reverse(list);
1278 void vflist_select_all(ViewFile *vf)
1280 GtkTreeSelection *selection;
1282 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1283 gtk_tree_selection_select_all(selection);
1285 VFLIST_INFO(vf, select_fd) = NULL;
1288 void vflist_select_none(ViewFile *vf)
1290 GtkTreeSelection *selection;
1292 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1293 gtk_tree_selection_unselect_all(selection);
1296 static gboolean tree_model_iter_prev(GtkTreeModel *store, GtkTreeIter *iter)
1301 tpath = gtk_tree_model_get_path(store, iter);
1302 result = gtk_tree_path_prev(tpath);
1304 gtk_tree_model_get_iter(store, iter, tpath);
1306 gtk_tree_path_free(tpath);
1311 static gboolean tree_model_get_iter_last(GtkTreeModel *store, GtkTreeIter *iter)
1313 if (!gtk_tree_model_get_iter_first(store, iter))
1318 GtkTreeIter next = *iter;
1320 if (gtk_tree_model_iter_next(store, &next))
1329 void vflist_select_invert(ViewFile *vf)
1332 GtkTreeSelection *selection;
1333 GtkTreeModel *store;
1336 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
1337 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1339 /* Backward iteration prevents scrolling to the end of the list,
1340 * it scrolls to the first selected row instead. */
1341 valid = tree_model_get_iter_last(store, &iter);
1345 gint selected = gtk_tree_selection_iter_is_selected(selection, &iter);
1348 gtk_tree_selection_unselect_iter(selection, &iter);
1350 gtk_tree_selection_select_iter(selection, &iter);
1352 valid = tree_model_iter_prev(store, &iter);
1356 void vflist_select_by_fd(ViewFile *vf, FileData *fd)
1360 if (vflist_find_row(vf, fd, &iter) < 0) return;
1362 tree_view_row_make_visible(GTK_TREE_VIEW(vf->listview), &iter, TRUE);
1364 if (!vflist_row_is_selected(vf, fd))
1366 GtkTreeSelection *selection;
1367 GtkTreeModel *store;
1370 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1371 gtk_tree_selection_unselect_all(selection);
1372 gtk_tree_selection_select_iter(selection, &iter);
1373 vflist_move_cursor(vf, &iter);
1375 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
1376 tpath = gtk_tree_model_get_path(store, &iter);
1377 gtk_tree_view_set_cursor(GTK_TREE_VIEW(vf->listview), tpath, NULL, FALSE);
1378 gtk_tree_path_free(tpath);
1382 static void vflist_select_closest(ViewFile *vf, FileData *sel_fd)
1386 if (sel_fd->parent) sel_fd = sel_fd->parent;
1392 FileData *fd = work->data;
1396 match = filelist_sort_compare_filedata_full(fd, sel_fd, vf->sort_method, vf->sort_ascend);
1400 vflist_select_by_fd(vf, fd);
1407 void vflist_mark_to_selection(ViewFile *vf, gint mark, MarkToSelectionMode mode)
1409 GtkTreeModel *store;
1411 GtkTreeSelection *selection;
1415 g_assert(mark >= 1 && mark <= FILEDATA_MARKS_SIZE);
1417 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
1418 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1420 valid = gtk_tree_model_get_iter_first(store, &iter);
1424 gboolean mark_val, selected;
1425 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, FILE_COLUMN_POINTER, &fd, -1);
1427 mark_val = file_data_get_mark(fd, n);
1428 selected = gtk_tree_selection_iter_is_selected(selection, &iter);
1432 case MTS_MODE_SET: selected = mark_val;
1434 case MTS_MODE_OR: selected = mark_val | selected;
1436 case MTS_MODE_AND: selected = mark_val & selected;
1438 case MTS_MODE_MINUS: selected = !mark_val & selected;
1443 gtk_tree_selection_select_iter(selection, &iter);
1445 gtk_tree_selection_unselect_iter(selection, &iter);
1447 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
1451 void vflist_selection_to_mark(ViewFile *vf, gint mark, SelectionToMarkMode mode)
1453 GtkTreeModel *store;
1454 GtkTreeSelection *selection;
1459 g_assert(mark >= 1 && mark <= FILEDATA_MARKS_SIZE);
1461 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1462 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1466 GtkTreePath *tpath = work->data;
1470 gtk_tree_model_get_iter(store, &iter, tpath);
1471 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
1473 file_data_unregister_notify_func(vf_notify_cb, vf); /* we don't need the notification */
1477 case STM_MODE_SET: file_data_set_mark(fd, n, 1);
1479 case STM_MODE_RESET: file_data_set_mark(fd, n, 0);
1481 case STM_MODE_TOGGLE: file_data_set_mark(fd, n, !file_data_get_mark(fd, n));
1485 file_data_register_notify_func(vf_notify_cb, vf, NOTIFY_PRIORITY_MEDIUM);
1487 gtk_tree_store_set(GTK_TREE_STORE(store), &iter, FILE_COLUMN_MARKS + n, file_data_get_mark(fd, n), -1);
1491 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1496 *-----------------------------------------------------------------------------
1498 *-----------------------------------------------------------------------------
1501 static void vflist_listview_set_height(GtkWidget *listview, gint thumb)
1503 GtkTreeViewColumn *column;
1504 GtkCellRenderer *cell;
1507 column = gtk_tree_view_get_column(GTK_TREE_VIEW(listview), 0); /* first column is thumbnail */
1508 if (!column) return;
1510 gtk_tree_view_column_set_visible(column, thumb);
1512 gtk_tree_view_column_set_fixed_width(column, options->thumbnails.max_width + 40);
1514 list = gtk_tree_view_column_get_cell_renderers(column);
1519 g_object_set(G_OBJECT(cell), "height", options->thumbnails.max_height, NULL);
1520 gtk_tree_view_columns_autosize(GTK_TREE_VIEW(listview));
1523 static void vflist_populate_view(ViewFile *vf)
1525 GtkTreeStore *store;
1527 GtkTreeRowReference *visible_row = NULL;
1531 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
1532 thumbs = VFLIST_INFO(vf, thumbs_enabled);
1534 vflist_thumb_stop(vf);
1538 vflist_store_clear(vf);
1543 if (GTK_WIDGET_REALIZED(vf->listview) &&
1544 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(vf->listview), 0, 0, &tpath, NULL, NULL, NULL))
1546 visible_row = gtk_tree_row_reference_new(GTK_TREE_MODEL(store), tpath);
1547 gtk_tree_path_free(tpath);
1550 vflist_listview_set_height(vf->listview, thumbs);
1552 selected = vflist_selection_get_list(vf);
1554 vflist_setup_iter_recursive(vf, store, NULL, vf->list, selected);
1556 if (selected && vflist_selection_count(vf, NULL) == 0)
1558 /* all selected files disappeared */
1559 vflist_select_closest(vf, selected->data);
1562 filelist_free(selected);
1566 if (gtk_tree_row_reference_valid(visible_row))
1568 tpath = gtk_tree_row_reference_get_path(visible_row);
1569 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(vf->listview), tpath, NULL, TRUE, 0.0, 0.0);
1570 gtk_tree_path_free(tpath);
1572 gtk_tree_row_reference_free(visible_row);
1576 vflist_thumb_update(vf);
1579 gint vflist_refresh(ViewFile *vf)
1584 old_list = vf->list;
1587 DEBUG_1("%s vflist_refresh: read dir", get_exec_time());
1590 file_data_unregister_notify_func(vf_notify_cb, vf); /* we don't need the notification of changes detected by filelist_read */
1592 ret = filelist_read(vf->dir_fd, &vf->list, NULL);
1594 file_data_register_notify_func(vf_notify_cb, vf, NOTIFY_PRIORITY_MEDIUM);
1596 DEBUG_1("%s vflist_refresh: sort", get_exec_time());
1597 vf->list = filelist_sort(vf->list, vf->sort_method, vf->sort_ascend);
1600 DEBUG_1("%s vflist_refresh: populate view", get_exec_time());
1602 vflist_populate_view(vf);
1604 filelist_free(old_list);
1605 DEBUG_1("%s vflist_refresh: done", get_exec_time());
1612 /* this overrides the low default of a GtkCellRenderer from 100 to CELL_HEIGHT_OVERRIDE, something sane for our purposes */
1614 #define CELL_HEIGHT_OVERRIDE 512
1616 static void cell_renderer_height_override(GtkCellRenderer *renderer)
1620 spec = g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(renderer)), "height");
1621 if (spec && G_IS_PARAM_SPEC_INT(spec))
1623 GParamSpecInt *spec_int;
1625 spec_int = G_PARAM_SPEC_INT(spec);
1626 if (spec_int->maximum < CELL_HEIGHT_OVERRIDE) spec_int->maximum = CELL_HEIGHT_OVERRIDE;
1630 static GdkColor *vflist_listview_color_shifted(GtkWidget *widget)
1632 static GdkColor color;
1633 static GtkWidget *done = NULL;
1639 style = gtk_widget_get_style(widget);
1640 memcpy(&color, &style->base[GTK_STATE_NORMAL], sizeof(color));
1641 shift_color(&color, -1, 0);
1648 static void vflist_listview_color_cb(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1649 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1651 ViewFile *vf = data;
1654 gtk_tree_model_get(tree_model, iter, FILE_COLUMN_COLOR, &set, -1);
1655 g_object_set(G_OBJECT(cell),
1656 "cell-background-gdk", vflist_listview_color_shifted(vf->listview),
1657 "cell-background-set", set, NULL);
1660 static void vflist_listview_add_column(ViewFile *vf, gint n, const gchar *title, gint image, gint right_justify, gint expand)
1662 GtkTreeViewColumn *column;
1663 GtkCellRenderer *renderer;
1665 column = gtk_tree_view_column_new();
1666 gtk_tree_view_column_set_title(column, title);
1667 gtk_tree_view_column_set_min_width(column, 4);
1671 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_GROW_ONLY);
1672 renderer = gtk_cell_renderer_text_new();
1675 g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
1677 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1678 gtk_tree_view_column_add_attribute(column, renderer, "text", n);
1680 gtk_tree_view_column_set_expand(column, TRUE);
1684 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
1685 renderer = gtk_cell_renderer_pixbuf_new();
1686 cell_renderer_height_override(renderer);
1687 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1688 gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", n);
1691 gtk_tree_view_column_set_cell_data_func(column, renderer, vflist_listview_color_cb, vf, NULL);
1692 g_object_set_data(G_OBJECT(column), "column_store_idx", GUINT_TO_POINTER(n));
1693 g_object_set_data(G_OBJECT(renderer), "column_store_idx", GUINT_TO_POINTER(n));
1695 gtk_tree_view_append_column(GTK_TREE_VIEW(vf->listview), column);
1698 static void vflist_listview_mark_toggled_cb(GtkCellRendererToggle *cell, gchar *path_str, gpointer data)
1700 ViewFile *vf = data;
1701 GtkTreeStore *store;
1702 GtkTreePath *path = gtk_tree_path_new_from_string(path_str);
1708 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
1709 if (!path || !gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, path))
1712 col_idx = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cell), "column_store_idx"));
1714 g_assert(col_idx >= FILE_COLUMN_MARKS && col_idx <= FILE_COLUMN_MARKS_LAST);
1716 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, FILE_COLUMN_POINTER, &fd, col_idx, &mark, -1);
1718 file_data_unregister_notify_func(vf_notify_cb, vf); /* we don't need the notification */
1719 file_data_set_mark(fd, col_idx - FILE_COLUMN_MARKS, mark);
1720 file_data_register_notify_func(vf_notify_cb, vf, NOTIFY_PRIORITY_MEDIUM);
1722 gtk_tree_store_set(store, &iter, col_idx, mark, -1);
1723 gtk_tree_path_free(path);
1726 static void vflist_listview_add_column_toggle(ViewFile *vf, gint n, const gchar *title)
1728 GtkTreeViewColumn *column;
1729 GtkCellRenderer *renderer;
1730 GtkTreeStore *store;
1733 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
1735 renderer = gtk_cell_renderer_toggle_new();
1736 column = gtk_tree_view_column_new_with_attributes(title, renderer, "active", n, NULL);
1738 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
1739 g_object_set_data(G_OBJECT(column), "column_store_idx", GUINT_TO_POINTER(n));
1740 g_object_set_data(G_OBJECT(renderer), "column_store_idx", GUINT_TO_POINTER(n));
1742 index = gtk_tree_view_append_column(GTK_TREE_VIEW(vf->listview), column);
1743 gtk_tree_view_column_set_fixed_width(column, 16);
1744 gtk_tree_view_column_set_visible(column, vf->marks_enabled);
1747 g_signal_connect(G_OBJECT(renderer), "toggled", G_CALLBACK(vflist_listview_mark_toggled_cb), vf);
1751 *-----------------------------------------------------------------------------
1753 *-----------------------------------------------------------------------------
1756 gint vflist_set_fd(ViewFile *vf, FileData *dir_fd)
1758 if (!dir_fd) return FALSE;
1759 if (vf->dir_fd == dir_fd) return TRUE;
1761 file_data_unref(vf->dir_fd);
1762 vf->dir_fd = file_data_ref(dir_fd);
1764 /* force complete reload */
1765 vflist_store_clear(vf);
1767 filelist_free(vf->list);
1770 return vf_refresh(vf);
1773 void vflist_destroy_cb(GtkWidget *widget, gpointer data)
1775 ViewFile *vf = data;
1777 file_data_unregister_notify_func(vf_notify_cb, vf);
1779 vflist_select_idle_cancel(vf);
1780 vf_refresh_idle_cancel(vf);
1781 vflist_thumb_stop(vf);
1783 filelist_free(vf->list);
1786 ViewFile *vflist_new(ViewFile *vf, FileData *dir_fd)
1788 GtkTreeStore *store;
1789 GtkTreeSelection *selection;
1791 GType flist_types[FILE_COLUMN_COUNT];
1794 vf->info = g_new0(ViewFileInfoList, 1);
1796 VFLIST_INFO(vf, click_fd) = NULL;
1797 VFLIST_INFO(vf, select_fd) = NULL;
1798 VFLIST_INFO(vf, thumbs_enabled) = FALSE;
1800 VFLIST_INFO(vf, select_idle_id) = -1;
1802 flist_types[FILE_COLUMN_POINTER] = G_TYPE_POINTER;
1803 flist_types[FILE_COLUMN_VERSION] = G_TYPE_INT;
1804 flist_types[FILE_COLUMN_THUMB] = GDK_TYPE_PIXBUF;
1805 flist_types[FILE_COLUMN_NAME] = G_TYPE_STRING;
1806 flist_types[FILE_COLUMN_SIDECARS] = G_TYPE_STRING;
1807 flist_types[FILE_COLUMN_SIZE] = G_TYPE_STRING;
1808 flist_types[FILE_COLUMN_DATE] = G_TYPE_STRING;
1809 flist_types[FILE_COLUMN_COLOR] = G_TYPE_BOOLEAN;
1810 for (i = FILE_COLUMN_MARKS; i < FILE_COLUMN_MARKS + FILEDATA_MARKS_SIZE; i++)
1811 flist_types[i] = G_TYPE_BOOLEAN;
1813 store = gtk_tree_store_newv(FILE_COLUMN_COUNT, flist_types);
1815 vf->listview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
1816 g_object_unref(store);
1818 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1819 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
1820 gtk_tree_selection_set_select_function(selection, vflist_select_cb, vf, NULL);
1822 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(vf->listview), FALSE);
1823 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(vf->listview), FALSE);
1825 vflist_listview_add_column(vf, FILE_COLUMN_THUMB, "", TRUE, FALSE, FALSE);
1827 for (i = 0; i < FILEDATA_MARKS_SIZE; i++)
1828 vflist_listview_add_column_toggle(vf, i + FILE_COLUMN_MARKS, "");
1830 vflist_listview_add_column(vf, FILE_COLUMN_NAME, _("Name"), FALSE, FALSE, FALSE);
1831 vflist_listview_add_column(vf, FILE_COLUMN_SIDECARS, _("SC"), FALSE, FALSE, FALSE);
1833 vflist_listview_add_column(vf, FILE_COLUMN_SIZE, _("Size"), FALSE, TRUE, FALSE);
1834 vflist_listview_add_column(vf, FILE_COLUMN_DATE, _("Date"), FALSE, TRUE, FALSE);
1836 file_data_register_notify_func(vf_notify_cb, vf, NOTIFY_PRIORITY_MEDIUM);
1840 void vflist_thumb_set(ViewFile *vf, gint enable)
1842 if (VFLIST_INFO(vf, thumbs_enabled) == enable) return;
1844 VFLIST_INFO(vf, thumbs_enabled) = enable;
1845 if (vf->layout) vf_refresh(vf);
1848 void vflist_marks_set(ViewFile *vf, gint enable)
1850 GList *columns, *work;
1852 if (vf->marks_enabled == enable) return;
1854 vf->marks_enabled = enable;
1856 columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(vf->listview));
1861 GtkTreeViewColumn *column = work->data;
1862 gint col_idx = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(column), "column_store_idx"));
1865 if (col_idx <= FILE_COLUMN_MARKS_LAST && col_idx >= FILE_COLUMN_MARKS)
1866 gtk_tree_view_column_set_visible(column, enable);
1869 g_list_free(columns);