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"
23 #include "layout_image.h"
27 #include "ui_bookmark.h"
28 #include "ui_fileops.h"
30 #include "ui_tree_edit.h"
31 #include "view_file.h"
33 #include <gdk/gdkkeysyms.h> /* for keyboard values */
37 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;
145 void vflist_color_set(ViewFile *vf, FileData *fd, gint color_set)
150 if (vflist_find_row(vf, fd, &iter) < 0) return;
151 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
152 gtk_tree_store_set(GTK_TREE_STORE(store), &iter, FILE_COLUMN_COLOR, color_set, -1);
155 static void vflist_move_cursor(ViewFile *vf, GtkTreeIter *iter)
160 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
162 tpath = gtk_tree_model_get_path(store, iter);
163 gtk_tree_view_set_cursor(GTK_TREE_VIEW(vf->listview), tpath, NULL, FALSE);
164 gtk_tree_path_free(tpath);
168 static gint vflist_column_idx(ViewFile *vf, gint store_idx)
170 GList *columns, *work;
173 columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(vf->listview));
177 GtkTreeViewColumn *column = work->data;
178 if (store_idx == GPOINTER_TO_INT(g_object_get_data (G_OBJECT(column), "column_store_idx")))
184 g_list_free(columns);
190 *-----------------------------------------------------------------------------
192 *-----------------------------------------------------------------------------
195 static void vflist_dnd_get(GtkWidget *widget, GdkDragContext *context,
196 GtkSelectionData *selection_data, guint info,
197 guint time, gpointer data)
201 gchar *uri_text = NULL;
204 if (!VFLIST_INFO(vf, click_fd)) return;
206 if (vflist_row_is_selected(vf, VFLIST_INFO(vf, click_fd)))
208 list = vf_selection_get_list(vf);
212 list = g_list_append(NULL, file_data_ref(VFLIST_INFO(vf, click_fd)));
217 uri_text = uri_text_from_filelist(list, &total, (info == TARGET_TEXT_PLAIN));
222 gtk_selection_data_set(selection_data, selection_data->target,
223 8, (guchar *)uri_text, total);
227 static void vflist_dnd_begin(GtkWidget *widget, GdkDragContext *context, gpointer data)
231 vflist_color_set(vf, VFLIST_INFO(vf, click_fd), TRUE);
233 if (VFLIST_INFO(vf, thumbs_enabled) &&
234 VFLIST_INFO(vf, click_fd) && VFLIST_INFO(vf, click_fd)->pixbuf)
238 if (vflist_row_is_selected(vf, VFLIST_INFO(vf, click_fd)))
239 items = vf_selection_count(vf, NULL);
243 dnd_set_drag_icon(widget, context, VFLIST_INFO(vf, click_fd)->pixbuf, items);
247 static void vflist_dnd_end(GtkWidget *widget, GdkDragContext *context, gpointer data)
251 vflist_color_set(vf, VFLIST_INFO(vf, click_fd), FALSE);
253 if (context->action == GDK_ACTION_MOVE)
259 void vflist_dnd_init(ViewFile *vf)
261 gtk_drag_source_set(vf->listview, GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
262 dnd_file_drag_types, dnd_file_drag_types_count,
263 GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK);
264 g_signal_connect(G_OBJECT(vf->listview), "drag_data_get",
265 G_CALLBACK(vflist_dnd_get), vf);
266 g_signal_connect(G_OBJECT(vf->listview), "drag_begin",
267 G_CALLBACK(vflist_dnd_begin), vf);
268 g_signal_connect(G_OBJECT(vf->listview), "drag_end",
269 G_CALLBACK(vflist_dnd_end), vf);
273 *-----------------------------------------------------------------------------
275 *-----------------------------------------------------------------------------
278 GList *vflist_pop_menu_file_list(ViewFile *vf)
280 if (!VFLIST_INFO(vf, click_fd)) return NULL;
282 if (vflist_row_is_selected(vf, VFLIST_INFO(vf, click_fd)))
284 return vf_selection_get_list(vf);
287 return g_list_append(NULL, file_data_ref(VFLIST_INFO(vf, click_fd)));
290 void vflist_pop_menu_view_cb(GtkWidget *widget, gpointer data)
294 if (vflist_row_is_selected(vf, VFLIST_INFO(vf, click_fd)))
298 list = vf_selection_get_list(vf);
299 view_window_new_from_list(list);
304 view_window_new(VFLIST_INFO(vf, click_fd));
308 void vflist_pop_menu_rename_cb(GtkWidget *widget, gpointer data)
313 list = vf_pop_menu_file_list(vf);
314 if (options->file_ops.enable_in_place_rename &&
315 list && !list->next && VFLIST_INFO(vf, click_fd))
322 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
323 if (vflist_find_row(vf, VFLIST_INFO(vf, click_fd), &iter) >= 0)
327 tpath = gtk_tree_model_get_path(store, &iter);
328 tree_edit_by_path(GTK_TREE_VIEW(vf->listview), tpath,
329 vflist_column_idx(vf, FILE_COLUMN_NAME), VFLIST_INFO(vf, click_fd)->name,
330 vflist_row_rename_cb, vf);
331 gtk_tree_path_free(tpath);
336 file_util_rename(NULL, list, vf->listview);
339 void vflist_pop_menu_thumbs_cb(GtkWidget *widget, gpointer data)
343 vflist_color_set(vf, VFLIST_INFO(vf, click_fd), FALSE);
346 layout_thumb_set(vf->layout, !VFLIST_INFO(vf, thumbs_enabled));
350 vflist_thumb_set(vf, !VFLIST_INFO(vf, thumbs_enabled));
354 void vflist_pop_menu_refresh_cb(GtkWidget *widget, gpointer data)
358 vflist_color_set(vf, VFLIST_INFO(vf, click_fd), FALSE);
362 void vflist_popup_destroy_cb(GtkWidget *widget, gpointer data)
365 vflist_color_set(vf, VFLIST_INFO(vf, click_fd), FALSE);
366 VFLIST_INFO(vf, click_fd) = NULL;
372 *-----------------------------------------------------------------------------
374 *-----------------------------------------------------------------------------
377 static gint vflist_row_rename_cb(TreeEditData *td, const gchar *old, const gchar *new, gpointer data)
383 if (strlen(new) == 0) return FALSE;
385 old_path = concat_dir_and_file(vf->path, old);
386 new_path = concat_dir_and_file(vf->path, new);
388 if (strchr(new, '/') != NULL)
390 gchar *text = g_strdup_printf(_("Invalid file name:\n%s"), new);
391 file_util_warning_dialog(_("Error renaming file"), text, GTK_STOCK_DIALOG_ERROR, vf->listview);
394 else if (isfile(new_path))
396 gchar *text = g_strdup_printf(_("A file with name %s already exists."), new);
397 file_util_warning_dialog(_("Error renaming file"), text, GTK_STOCK_DIALOG_ERROR, vf->listview);
402 gint row = vf_index_by_path(vf, old_path);
405 GList *work = g_list_nth(vf->list, row);
406 FileData *fd = work->data;
408 if (!file_data_add_change_info(fd, FILEDATA_CHANGE_RENAME, old_path, new_path) || !rename_file_ext(fd))
410 gchar *text = g_strdup_printf(_("Unable to rename file:\n%s\nto:\n%s"), old, new);
411 file_util_warning_dialog(_("Error renaming file"), text, GTK_STOCK_DIALOG_ERROR, vf->listview);
423 static void vflist_menu_position_cb(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer data)
431 if (vflist_find_row(vf, VFLIST_INFO(vf, click_fd), &iter) < 0) return;
432 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
433 tpath = gtk_tree_model_get_path(store, &iter);
434 tree_view_get_cell_clamped(GTK_TREE_VIEW(vf->listview), tpath, FILE_COLUMN_NAME - 1, TRUE, x, y, &cw, &ch);
435 gtk_tree_path_free(tpath);
437 popup_menu_position_clamp(menu, x, y, 0);
440 gint vflist_press_key_cb(GtkWidget *widget, GdkEventKey *event, gpointer data)
445 if (event->keyval != GDK_Menu) return FALSE;
447 gtk_tree_view_get_cursor(GTK_TREE_VIEW(vf->listview), &tpath, NULL);
453 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
454 gtk_tree_model_get_iter(store, &iter, tpath);
455 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &VFLIST_INFO(vf, click_fd), -1);
456 gtk_tree_path_free(tpath);
460 VFLIST_INFO(vf, click_fd) = NULL;
463 vf->popup = vf_pop_menu(vf);
464 gtk_menu_popup(GTK_MENU(vf->popup), NULL, NULL, vflist_menu_position_cb, vf, 0, GDK_CURRENT_TIME);
469 gint vflist_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
475 GtkTreeViewColumn *column;
477 vf->clicked_mark = 0;
479 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), bevent->x, bevent->y,
480 &tpath, &column, NULL, NULL))
483 gint col_idx = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(column), "column_store_idx"));
485 if (bevent->button == MOUSE_BUTTON_LEFT &&
486 col_idx >= FILE_COLUMN_MARKS && col_idx <= FILE_COLUMN_MARKS_LAST)
489 if (col_idx >= FILE_COLUMN_MARKS && col_idx <= FILE_COLUMN_MARKS_LAST)
490 vf->clicked_mark = 1 + (col_idx - FILE_COLUMN_MARKS);
492 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
494 gtk_tree_model_get_iter(store, &iter, tpath);
495 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
497 gtk_tree_view_set_cursor(GTK_TREE_VIEW(widget), tpath, NULL, FALSE);
499 gtk_tree_path_free(tpath);
502 VFLIST_INFO(vf, click_fd) = fd;
504 if (bevent->button == MOUSE_BUTTON_RIGHT)
506 vf->popup = vf_pop_menu(vf);
507 gtk_menu_popup(GTK_MENU(vf->popup), NULL, NULL, NULL, NULL,
508 bevent->button, bevent->time);
512 if (!fd) return FALSE;
514 if (bevent->button == MOUSE_BUTTON_MIDDLE)
516 if (!vflist_row_is_selected(vf, fd))
518 vflist_color_set(vf, fd, TRUE);
524 if (bevent->button == MOUSE_BUTTON_LEFT && bevent->type == GDK_BUTTON_PRESS &&
525 !(bevent->state & GDK_SHIFT_MASK ) &&
526 !(bevent->state & GDK_CONTROL_MASK ) &&
527 vflist_row_is_selected(vf, fd))
529 GtkTreeSelection *selection;
531 gtk_widget_grab_focus(widget);
534 /* returning FALSE and further processing of the event is needed for
535 correct operation of the expander, to show the sidecar files.
536 It however resets the selection of multiple files. With this condition
537 it should work for both cases */
538 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
539 return (gtk_tree_selection_count_selected_rows(selection) > 1);
543 if (bevent->button == MOUSE_BUTTON_LEFT && bevent->type == GDK_2BUTTON_PRESS)
545 if (vf->layout) layout_image_full_screen_start(vf->layout);
552 gint vflist_release_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
559 if (bevent->button == MOUSE_BUTTON_MIDDLE)
561 vflist_color_set(vf, VFLIST_INFO(vf, click_fd), FALSE);
564 if (bevent->button != MOUSE_BUTTON_LEFT && bevent->button != MOUSE_BUTTON_MIDDLE)
569 if ((bevent->x != 0 || bevent->y != 0) &&
570 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), bevent->x, bevent->y,
571 &tpath, NULL, NULL, NULL))
575 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
576 gtk_tree_model_get_iter(store, &iter, tpath);
577 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
578 gtk_tree_path_free(tpath);
581 if (bevent->button == MOUSE_BUTTON_MIDDLE)
583 if (fd && VFLIST_INFO(vf, click_fd) == fd)
585 GtkTreeSelection *selection;
587 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
588 if (vflist_row_is_selected(vf, fd))
590 gtk_tree_selection_unselect_iter(selection, &iter);
594 gtk_tree_selection_select_iter(selection, &iter);
600 if (fd && VFLIST_INFO(vf, click_fd) == fd &&
601 !(bevent->state & GDK_SHIFT_MASK ) &&
602 !(bevent->state & GDK_CONTROL_MASK ) &&
603 vflist_row_is_selected(vf, fd))
605 GtkTreeSelection *selection;
607 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
608 gtk_tree_selection_unselect_all(selection);
609 gtk_tree_selection_select_iter(selection, &iter);
610 vflist_move_cursor(vf, &iter);
611 // return TRUE;// FIXME - expand
617 static void vflist_select_image(ViewFile *vf, FileData *sel_fd)
619 FileData *read_ahead_fd = NULL;
624 cur_fd = layout_image_get_fd(vf->layout);
625 if (sel_fd == cur_fd) return; /* no change */
627 row = g_list_index(vf->list, sel_fd);
628 // FIXME sidecar data
630 if (sel_fd && options->image.enable_read_ahead && row >= 0)
632 if (row > g_list_index(vf->list, cur_fd) &&
633 row + 1 < vf_count(vf, NULL))
635 read_ahead_fd = vf_index_get_data(vf, row + 1);
639 read_ahead_fd = vf_index_get_data(vf, row - 1);
643 layout_image_set_with_ahead(vf->layout, sel_fd, read_ahead_fd);
646 static gint vflist_select_idle_cb(gpointer data)
652 VFLIST_INFO(vf, select_idle_id) = -1;
658 if (VFLIST_INFO(vf, select_fd))
660 vflist_select_image(vf, VFLIST_INFO(vf, select_fd));
661 VFLIST_INFO(vf, select_fd) = NULL;
664 VFLIST_INFO(vf, select_idle_id) = -1;
668 static void vflist_select_idle_cancel(ViewFile *vf)
670 if (VFLIST_INFO(vf, select_idle_id) != -1) g_source_remove(VFLIST_INFO(vf, select_idle_id));
671 VFLIST_INFO(vf, select_idle_id) = -1;
674 static gboolean vflist_select_cb(GtkTreeSelection *selection, GtkTreeModel *store, GtkTreePath *tpath,
675 gboolean path_currently_selected, gpointer data)
680 if (!path_currently_selected &&
681 gtk_tree_model_get_iter(store, &iter, tpath))
683 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &VFLIST_INFO(vf, select_fd), -1);
687 VFLIST_INFO(vf, select_fd) = NULL;
691 VFLIST_INFO(vf, select_idle_id) == -1)
693 VFLIST_INFO(vf, select_idle_id) = g_idle_add(vflist_select_idle_cb, vf);
700 *-----------------------------------------------------------------------------
702 *-----------------------------------------------------------------------------
706 static gboolean vflist_dummy_select_cb(GtkTreeSelection *selection, GtkTreeModel *store, GtkTreePath *tpath,
707 gboolean path_currently_selected, gpointer data)
714 static void vflist_setup_iter(ViewFile *vf, GtkTreeStore *store, GtkTreeIter *iter, FileData *fd)
718 gchar *sidecars = NULL;
720 if (fd->sidecar_files)
721 sidecars = file_data_sc_list_to_string(fd);
722 size = text_from_size(fd->size);
724 gtk_tree_store_set(store, iter, FILE_COLUMN_POINTER, fd,
725 FILE_COLUMN_THUMB, (VFLIST_INFO(vf, thumbs_enabled)) ? fd->pixbuf : NULL,
726 FILE_COLUMN_NAME, fd->name,
727 FILE_COLUMN_SIDECARS, sidecars,
728 FILE_COLUMN_SIZE, size,
729 FILE_COLUMN_DATE, text_from_time(fd->date),
730 FILE_COLUMN_COLOR, FALSE, -1);
731 for (i = 0; i < FILEDATA_MARKS_SIZE; i++)
732 gtk_tree_store_set(store, iter, FILE_COLUMN_MARKS + i, fd->marks[i], -1);
739 static void vflist_setup_iter_with_sidecars(ViewFile *vf, GtkTreeStore *store, GtkTreeIter *iter, FileData *fd)
745 vflist_setup_iter(vf, store, iter, fd);
748 /* this is almost the same code as in vflist_populate_view
749 maybe it should be made more generic and used in both places */
752 valid = gtk_tree_model_iter_children(GTK_TREE_MODEL(store), &s_iter, iter);
754 work = fd->sidecar_files;
758 FileData *sfd = work->data;
763 FileData *old_sfd = NULL;
767 gtk_tree_model_get(GTK_TREE_MODEL(store), &s_iter, FILE_COLUMN_POINTER, &old_sfd, -1);
775 match = filelist_sort_compare_filedata_full(sfd, old_sfd, SORT_NAME, TRUE);
790 gtk_tree_store_insert_before(store, &new, iter, &s_iter);
794 gtk_tree_store_append(store, &new, iter);
797 vflist_setup_iter(vf, store, &new, sfd);
803 valid = gtk_tree_store_remove(store, &s_iter);
807 vflist_setup_iter(vf, store, &s_iter, sfd);
809 if (valid) valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &s_iter);
819 valid = gtk_tree_store_remove(store, &s_iter);
823 void vflist_sort_set(ViewFile *vf, SortType type, gint ascend)
826 GHashTable *fd_idx_hash = g_hash_table_new(NULL, NULL);
831 if (vf->sort_method == type && vf->sort_ascend == ascend) return;
832 if (!vf->list) return;
838 FileData *fd = work->data;
839 g_hash_table_insert(fd_idx_hash, fd, GINT_TO_POINTER(i));
844 vf->sort_method = type;
845 vf->sort_ascend = ascend;
847 vf->list = filelist_sort(vf->list, vf->sort_method, vf->sort_ascend);
849 new_order = g_malloc(i * sizeof(gint));
855 FileData *fd = work->data;
856 new_order[i] = GPOINTER_TO_INT(g_hash_table_lookup(fd_idx_hash, fd));
861 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
862 gtk_tree_store_reorder(store, NULL, new_order);
865 g_hash_table_destroy(fd_idx_hash);
869 *-----------------------------------------------------------------------------
871 *-----------------------------------------------------------------------------
874 static gint vflist_thumb_next(ViewFile *vf);
876 static void vflist_thumb_status(ViewFile *vf, gdouble val, const gchar *text)
878 if (vf->func_thumb_status)
880 vf->func_thumb_status(vf, val, text, vf->data_thumb_status);
884 static void vflist_thumb_cleanup(ViewFile *vf)
886 vflist_thumb_status(vf, 0.0, NULL);
888 vf->thumbs_count = 0;
889 vf->thumbs_running = FALSE;
891 thumb_loader_free(vf->thumbs_loader);
892 vf->thumbs_loader = NULL;
894 vf->thumbs_filedata = NULL;
897 static void vflist_thumb_stop(ViewFile *vf)
899 if (vf->thumbs_running) vflist_thumb_cleanup(vf);
902 static void vflist_thumb_do(ViewFile *vf, ThumbLoader *tl, FileData *fd)
907 if (!fd || vflist_find_row(vf, fd, &iter) < 0) return;
909 if (fd->pixbuf) g_object_unref(fd->pixbuf);
910 fd->pixbuf = thumb_loader_get_pixbuf(tl, TRUE);
912 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
913 gtk_tree_store_set(store, &iter, FILE_COLUMN_THUMB, fd->pixbuf, -1);
915 vflist_thumb_status(vf, (gdouble)(vf->thumbs_count) / vflist_sidecar_list_count(vf->list), _("Loading thumbs..."));
918 static void vflist_thumb_error_cb(ThumbLoader *tl, gpointer data)
922 if (vf->thumbs_filedata && vf->thumbs_loader == tl)
924 vflist_thumb_do(vf, tl, vf->thumbs_filedata);
927 while (vflist_thumb_next(vf));
930 static void vflist_thumb_done_cb(ThumbLoader *tl, gpointer data)
934 if (vf->thumbs_filedata && vf->thumbs_loader == tl)
936 vflist_thumb_do(vf, tl, vf->thumbs_filedata);
939 while (vflist_thumb_next(vf));
942 static gint vflist_thumb_next(ViewFile *vf)
947 /* first check the visible files */
949 if (GTK_WIDGET_REALIZED(vf->listview) &&
950 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(vf->listview), 0, 0, &tpath, NULL, NULL, NULL))
956 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
957 gtk_tree_model_get_iter(store, &iter, tpath);
958 gtk_tree_path_free(tpath);
960 while (!fd && valid && tree_view_row_get_visibility(GTK_TREE_VIEW(vf->listview), &iter, FALSE) == 0)
962 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
963 if (fd->pixbuf) fd = NULL;
965 valid = gtk_tree_model_iter_next(store, &iter);
969 /* then find first undone */
973 GList *work = vf->list;
976 FileData *fd_p = work->data;
981 GList *work2 = fd_p->sidecar_files;
986 if (!fd_p->pixbuf) fd = fd_p;
997 vflist_thumb_cleanup(vf);
1003 vf->thumbs_filedata = fd;
1005 thumb_loader_free(vf->thumbs_loader);
1007 vf->thumbs_loader = thumb_loader_new(options->thumbnails.max_width, options->thumbnails.max_height);
1008 thumb_loader_set_callbacks(vf->thumbs_loader,
1009 vflist_thumb_done_cb,
1010 vflist_thumb_error_cb,
1014 if (!thumb_loader_start(vf->thumbs_loader, fd->path))
1016 /* set icon to unknown, continue */
1017 DEBUG_1("thumb loader start failed %s", vf->thumbs_loader->path);
1018 vflist_thumb_do(vf, vf->thumbs_loader, fd);
1026 static void vflist_thumb_update(ViewFile *vf)
1028 vflist_thumb_stop(vf);
1029 if (!VFLIST_INFO(vf, thumbs_enabled)) return;
1031 vflist_thumb_status(vf, 0.0, _("Loading thumbs..."));
1032 vf->thumbs_running = TRUE;
1034 while (vflist_thumb_next(vf));
1038 *-----------------------------------------------------------------------------
1040 *-----------------------------------------------------------------------------
1043 FileData *vflist_index_get_data(ViewFile *vf, gint row)
1045 return g_list_nth_data(vf->list, row);
1048 gint vflist_index_by_path(ViewFile *vf, const gchar *path)
1053 if (!path) return -1;
1058 FileData *fd = work->data;
1059 if (strcmp(path, fd->path) == 0) return p;
1068 gint vflist_count(ViewFile *vf, gint64 *bytes)
1078 FileData *fd = work->data;
1086 return g_list_length(vf->list);
1089 GList *vflist_get_list(ViewFile *vf)
1097 FileData *fd = work->data;
1100 list = g_list_prepend(list, file_data_ref(fd));
1103 return g_list_reverse(list);
1107 *-----------------------------------------------------------------------------
1109 *-----------------------------------------------------------------------------
1112 static gint vflist_row_is_selected(ViewFile *vf, FileData *fd)
1114 GtkTreeModel *store;
1115 GtkTreeSelection *selection;
1120 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1121 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1123 while (!found && work)
1125 GtkTreePath *tpath = work->data;
1129 gtk_tree_model_get_iter(store, &iter, tpath);
1130 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd_n, -1);
1131 if (fd_n == fd) found = TRUE;
1134 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1140 gint vflist_index_is_selected(ViewFile *vf, gint row)
1144 fd = vf_index_get_data(vf, row);
1145 return vflist_row_is_selected(vf, fd);
1148 gint vflist_selection_count(ViewFile *vf, gint64 *bytes)
1150 GtkTreeModel *store;
1151 GtkTreeSelection *selection;
1155 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1156 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1166 GtkTreePath *tpath = work->data;
1170 gtk_tree_model_get_iter(store, &iter, tpath);
1171 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
1180 count = g_list_length(slist);
1181 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1187 GList *vflist_selection_get_list(ViewFile *vf)
1189 GtkTreeModel *store;
1190 GtkTreeSelection *selection;
1195 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1196 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1200 GtkTreePath *tpath = work->data;
1204 gtk_tree_model_get_iter(store, &iter, tpath);
1205 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
1207 list = g_list_prepend(list, file_data_ref(fd));
1211 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1214 return g_list_reverse(list);
1217 GList *vflist_selection_get_list_by_index(ViewFile *vf)
1219 GtkTreeModel *store;
1220 GtkTreeSelection *selection;
1225 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1226 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1230 GtkTreePath *tpath = work->data;
1234 gtk_tree_model_get_iter(store, &iter, tpath);
1235 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
1237 list = g_list_prepend(list, GINT_TO_POINTER(g_list_index(vf->list, fd)));
1241 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1244 return g_list_reverse(list);
1247 void vflist_select_all(ViewFile *vf)
1249 GtkTreeSelection *selection;
1251 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1252 gtk_tree_selection_select_all(selection);
1254 VFLIST_INFO(vf, select_fd) = NULL;
1257 void vflist_select_none(ViewFile *vf)
1259 GtkTreeSelection *selection;
1261 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1262 gtk_tree_selection_unselect_all(selection);
1265 static gboolean tree_model_iter_prev(GtkTreeModel *store, GtkTreeIter *iter)
1270 tpath = gtk_tree_model_get_path(store, iter);
1271 result = gtk_tree_path_prev(tpath);
1273 gtk_tree_model_get_iter(store, iter, tpath);
1275 gtk_tree_path_free(tpath);
1280 static gboolean tree_model_get_iter_last(GtkTreeModel *store, GtkTreeIter *iter)
1282 if (!gtk_tree_model_get_iter_first(store, iter))
1287 GtkTreeIter next = *iter;
1289 if (gtk_tree_model_iter_next(store, &next))
1298 void vflist_select_invert(ViewFile *vf)
1301 GtkTreeSelection *selection;
1302 GtkTreeModel *store;
1305 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
1306 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1308 /* Backward iteration prevents scrolling to the end of the list,
1309 * it scrolls to the first selected row instead. */
1310 valid = tree_model_get_iter_last(store, &iter);
1314 gint selected = gtk_tree_selection_iter_is_selected(selection, &iter);
1317 gtk_tree_selection_unselect_iter(selection, &iter);
1319 gtk_tree_selection_select_iter(selection, &iter);
1321 valid = tree_model_iter_prev(store, &iter);
1325 void vflist_select_by_fd(ViewFile *vf, FileData *fd)
1329 if (vflist_find_row(vf, fd, &iter) < 0) return;
1331 tree_view_row_make_visible(GTK_TREE_VIEW(vf->listview), &iter, TRUE);
1333 if (!vflist_row_is_selected(vf, fd))
1335 GtkTreeSelection *selection;
1336 GtkTreeModel *store;
1339 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1340 gtk_tree_selection_unselect_all(selection);
1341 gtk_tree_selection_select_iter(selection, &iter);
1342 vflist_move_cursor(vf, &iter);
1344 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
1345 tpath = gtk_tree_model_get_path(store, &iter);
1346 gtk_tree_view_set_cursor(GTK_TREE_VIEW(vf->listview), tpath, NULL, FALSE);
1347 gtk_tree_path_free(tpath);
1351 void vflist_mark_to_selection(ViewFile *vf, gint mark, MarkToSelectionMode mode)
1353 GtkTreeModel *store;
1355 GtkTreeSelection *selection;
1359 g_assert(mark >= 1 && mark <= FILEDATA_MARKS_SIZE);
1361 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
1362 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1364 valid = gtk_tree_model_get_iter_first(store, &iter);
1368 gboolean mark_val, selected;
1369 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, FILE_COLUMN_POINTER, &fd, -1);
1371 mark_val = fd->marks[n];
1372 selected = gtk_tree_selection_iter_is_selected(selection, &iter);
1376 case MTS_MODE_SET: selected = mark_val;
1378 case MTS_MODE_OR: selected = mark_val | selected;
1380 case MTS_MODE_AND: selected = mark_val & selected;
1382 case MTS_MODE_MINUS: selected = !mark_val & selected;
1387 gtk_tree_selection_select_iter(selection, &iter);
1389 gtk_tree_selection_unselect_iter(selection, &iter);
1391 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
1395 void vflist_selection_to_mark(ViewFile *vf, gint mark, SelectionToMarkMode mode)
1397 GtkTreeModel *store;
1398 GtkTreeSelection *selection;
1403 g_assert(mark >= 1 && mark <= FILEDATA_MARKS_SIZE);
1405 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1406 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1410 GtkTreePath *tpath = work->data;
1414 gtk_tree_model_get_iter(store, &iter, tpath);
1415 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
1419 case STM_MODE_SET: fd->marks[n] = 1;
1421 case STM_MODE_RESET: fd->marks[n] = 0;
1423 case STM_MODE_TOGGLE: fd->marks[n] = !fd->marks[n];
1427 gtk_tree_store_set(GTK_TREE_STORE(store), &iter, FILE_COLUMN_MARKS + n, fd->marks[n], -1);
1431 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1436 *-----------------------------------------------------------------------------
1438 *-----------------------------------------------------------------------------
1441 static void vflist_listview_set_height(GtkWidget *listview, gint thumb)
1443 GtkTreeViewColumn *column;
1444 GtkCellRenderer *cell;
1447 column = gtk_tree_view_get_column(GTK_TREE_VIEW(listview), FILE_COLUMN_THUMB - 1);
1448 if (!column) return;
1450 gtk_tree_view_column_set_fixed_width(column, ((thumb) ? options->thumbnails.max_width : 4) + 10);
1452 list = gtk_tree_view_column_get_cell_renderers(column);
1457 g_object_set(G_OBJECT(cell), "height", (thumb) ? options->thumbnails.max_height : -1, NULL);
1458 gtk_tree_view_columns_autosize(GTK_TREE_VIEW(listview));
1461 static void vflist_populate_view(ViewFile *vf)
1463 GtkTreeStore *store;
1467 GtkTreeRowReference *visible_row = NULL;
1471 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
1472 thumbs = VFLIST_INFO(vf, thumbs_enabled);
1474 vflist_thumb_stop(vf);
1478 gtk_tree_store_clear(store);
1483 if (GTK_WIDGET_REALIZED(vf->listview) &&
1484 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(vf->listview), 0, 0, &tpath, NULL, NULL, NULL))
1486 visible_row = gtk_tree_row_reference_new(GTK_TREE_MODEL(store), tpath);
1487 gtk_tree_path_free(tpath);
1490 vflist_listview_set_height(vf->listview, thumbs);
1492 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
1498 FileData *fd = work->data;
1503 FileData *old_fd = NULL;
1507 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, FILE_COLUMN_POINTER, &old_fd, -1);
1515 match = filelist_sort_compare_filedata_full(fd, old_fd, vf->sort_method, vf->sort_ascend);
1517 match = -1; /* probably should not happen*/
1532 gtk_tree_store_insert_before(store, &new, NULL, &iter);
1536 gtk_tree_store_append(store, &new, NULL);
1538 vflist_setup_iter_with_sidecars(vf, store, &new, fd);
1544 valid = gtk_tree_store_remove(store, &iter);
1548 vflist_setup_iter_with_sidecars(vf, store, &iter, fd);
1550 if (valid) valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
1560 valid = gtk_tree_store_remove(store, &iter);
1565 if (gtk_tree_row_reference_valid(visible_row))
1567 tpath = gtk_tree_row_reference_get_path(visible_row);
1568 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(vf->listview), tpath, NULL, TRUE, 0.0, 0.0);
1569 gtk_tree_path_free(tpath);
1571 gtk_tree_row_reference_free(visible_row);
1575 vflist_thumb_update(vf);
1578 gint vflist_refresh(ViewFile *vf)
1583 old_list = vf->list;
1588 ret = filelist_read(vf->path, &vf->list, NULL);
1591 vf->list = filelist_sort(vf->list, vf->sort_method, vf->sort_ascend);
1592 vflist_populate_view(vf);
1594 filelist_free(old_list);
1599 /* this overrides the low default of a GtkCellRenderer from 100 to CELL_HEIGHT_OVERRIDE, something sane for our purposes */
1601 #define CELL_HEIGHT_OVERRIDE 512
1603 static void cell_renderer_height_override(GtkCellRenderer *renderer)
1607 spec = g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(renderer)), "height");
1608 if (spec && G_IS_PARAM_SPEC_INT(spec))
1610 GParamSpecInt *spec_int;
1612 spec_int = G_PARAM_SPEC_INT(spec);
1613 if (spec_int->maximum < CELL_HEIGHT_OVERRIDE) spec_int->maximum = CELL_HEIGHT_OVERRIDE;
1617 static GdkColor *vflist_listview_color_shifted(GtkWidget *widget)
1619 static GdkColor color;
1620 static GtkWidget *done = NULL;
1626 style = gtk_widget_get_style(widget);
1627 memcpy(&color, &style->base[GTK_STATE_NORMAL], sizeof(color));
1628 shift_color(&color, -1, 0);
1635 static void vflist_listview_color_cb(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1636 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1638 ViewFile *vf = data;
1641 gtk_tree_model_get(tree_model, iter, FILE_COLUMN_COLOR, &set, -1);
1642 g_object_set(G_OBJECT(cell),
1643 "cell-background-gdk", vflist_listview_color_shifted(vf->listview),
1644 "cell-background-set", set, NULL);
1647 static void vflist_listview_add_column(ViewFile *vf, gint n, const gchar *title, gint image, gint right_justify, gint expand)
1649 GtkTreeViewColumn *column;
1650 GtkCellRenderer *renderer;
1652 column = gtk_tree_view_column_new();
1653 gtk_tree_view_column_set_title(column, title);
1654 gtk_tree_view_column_set_min_width(column, 4);
1658 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_GROW_ONLY);
1659 renderer = gtk_cell_renderer_text_new();
1662 g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
1664 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1665 gtk_tree_view_column_add_attribute(column, renderer, "text", n);
1667 gtk_tree_view_column_set_expand(column, TRUE);
1671 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
1672 renderer = gtk_cell_renderer_pixbuf_new();
1673 cell_renderer_height_override(renderer);
1674 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1675 gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", n);
1678 gtk_tree_view_column_set_cell_data_func(column, renderer, vflist_listview_color_cb, vf, NULL);
1679 g_object_set_data(G_OBJECT(column), "column_store_idx", GUINT_TO_POINTER(n));
1680 g_object_set_data(G_OBJECT(renderer), "column_store_idx", GUINT_TO_POINTER(n));
1682 gtk_tree_view_append_column(GTK_TREE_VIEW(vf->listview), column);
1685 static void vflist_listview_mark_toggled(GtkCellRendererToggle *cell, gchar *path_str, GtkTreeStore *store)
1687 GtkTreePath *path = gtk_tree_path_new_from_string(path_str);
1693 if (!path || !gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, path))
1696 col_idx = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cell), "column_store_idx"));
1698 g_assert(col_idx >= FILE_COLUMN_MARKS && col_idx <= FILE_COLUMN_MARKS_LAST);
1700 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, FILE_COLUMN_POINTER, &fd, col_idx, &mark, -1);
1702 fd->marks[col_idx - FILE_COLUMN_MARKS] = mark;
1704 gtk_tree_store_set(store, &iter, col_idx, mark, -1);
1705 gtk_tree_path_free(path);
1708 static void vflist_listview_add_column_toggle(ViewFile *vf, gint n, const gchar *title)
1710 GtkTreeViewColumn *column;
1711 GtkCellRenderer *renderer;
1712 GtkTreeStore *store;
1715 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
1717 renderer = gtk_cell_renderer_toggle_new();
1718 column = gtk_tree_view_column_new_with_attributes(title, renderer, "active", n, NULL);
1720 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
1721 g_object_set_data(G_OBJECT(column), "column_store_idx", GUINT_TO_POINTER(n));
1722 g_object_set_data(G_OBJECT(renderer), "column_store_idx", GUINT_TO_POINTER(n));
1724 index = gtk_tree_view_append_column(GTK_TREE_VIEW(vf->listview), column);
1725 gtk_tree_view_column_set_fixed_width(column, 16);
1726 gtk_tree_view_column_set_visible(column, vf->marks_enabled);
1729 g_signal_connect(G_OBJECT(renderer), "toggled", G_CALLBACK(vflist_listview_mark_toggled), store);
1733 *-----------------------------------------------------------------------------
1735 *-----------------------------------------------------------------------------
1738 gint vflist_set_path(ViewFile *vf, const gchar *path)
1740 GtkTreeStore *store;
1742 if (!path) return FALSE;
1743 if (vf->path && strcmp(path, vf->path) == 0) return TRUE;
1746 vf->path = g_strdup(path);
1748 /* force complete reload */
1749 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
1750 gtk_tree_store_clear(store);
1752 filelist_free(vf->list);
1755 return vf_refresh(vf);
1758 void vflist_destroy_cb(GtkWidget *widget, gpointer data)
1760 ViewFile *vf = data;
1762 vflist_select_idle_cancel(vf);
1763 vflist_thumb_stop(vf);
1765 filelist_free(vf->list);
1768 ViewFile *vflist_new(ViewFile *vf, const gchar *path)
1770 GtkTreeStore *store;
1771 GtkTreeSelection *selection;
1773 GType flist_types[FILE_COLUMN_COUNT];
1776 vf->info = g_new0(ViewFileInfoList, 1);
1778 VFLIST_INFO(vf, click_fd) = NULL;
1779 VFLIST_INFO(vf, select_fd) = NULL;
1780 VFLIST_INFO(vf, thumbs_enabled) = FALSE;
1782 VFLIST_INFO(vf, select_idle_id) = -1;
1784 flist_types[FILE_COLUMN_POINTER] = G_TYPE_POINTER;
1785 flist_types[FILE_COLUMN_THUMB] = GDK_TYPE_PIXBUF;
1786 flist_types[FILE_COLUMN_NAME] = G_TYPE_STRING;
1787 flist_types[FILE_COLUMN_SIDECARS] = G_TYPE_STRING;
1788 flist_types[FILE_COLUMN_SIZE] = G_TYPE_STRING;
1789 flist_types[FILE_COLUMN_DATE] = G_TYPE_STRING;
1790 flist_types[FILE_COLUMN_COLOR] = G_TYPE_BOOLEAN;
1791 for (i = FILE_COLUMN_MARKS; i < FILE_COLUMN_MARKS + FILEDATA_MARKS_SIZE; i++)
1792 flist_types[i] = G_TYPE_BOOLEAN;
1794 store = gtk_tree_store_newv(FILE_COLUMN_COUNT, flist_types);
1796 vf->listview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
1797 g_object_unref(store);
1799 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1800 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
1801 gtk_tree_selection_set_select_function(selection, vflist_select_cb, vf, NULL);
1803 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(vf->listview), FALSE);
1804 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(vf->listview), FALSE);
1806 vflist_listview_add_column(vf, FILE_COLUMN_THUMB, "", TRUE, FALSE, FALSE);
1808 for (i = 0; i < FILEDATA_MARKS_SIZE; i++)
1809 vflist_listview_add_column_toggle(vf, i + FILE_COLUMN_MARKS, "");
1811 vflist_listview_add_column(vf, FILE_COLUMN_NAME, _("Name"), FALSE, FALSE, FALSE);
1812 vflist_listview_add_column(vf, FILE_COLUMN_SIDECARS, _("SC"), FALSE, FALSE, FALSE);
1814 vflist_listview_add_column(vf, FILE_COLUMN_SIZE, _("Size"), FALSE, TRUE, FALSE);
1815 vflist_listview_add_column(vf, FILE_COLUMN_DATE, _("Date"), FALSE, TRUE, FALSE);
1820 void vflist_thumb_set(ViewFile *vf, gint enable)
1822 if (VFLIST_INFO(vf, thumbs_enabled) == enable) return;
1824 VFLIST_INFO(vf, thumbs_enabled) = enable;
1825 if (vf->layout) vf_refresh(vf);
1828 void vflist_marks_set(ViewFile *vf, gint enable)
1830 GList *columns, *work;
1832 if (vf->marks_enabled == enable) return;
1834 vf->marks_enabled = enable;
1836 columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(vf->listview));
1841 GtkTreeViewColumn *column = work->data;
1842 gint col_idx = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(column), "column_store_idx"));
1845 if (col_idx <= FILE_COLUMN_MARKS_LAST && col_idx >= FILE_COLUMN_MARKS)
1846 gtk_tree_view_column_set_visible(column, enable);
1849 g_list_free(columns);
1854 *-----------------------------------------------------------------------------
1855 * maintenance (for rename, move, remove)
1856 *-----------------------------------------------------------------------------
1859 static gint vflist_maint_find_closest(ViewFile *vf, gint row, gint count, GList *ignore_list)
1869 gint f = vf_index_by_path(vf, work->data);
1870 if (f >= 0) list = g_list_prepend(list, GINT_TO_POINTER(f));
1880 gpointer p = work->data;
1882 if (row == GPOINTER_TO_INT(p))
1887 if (rev == GPOINTER_TO_INT(p))
1892 if (!c) list = g_list_remove(list, p);
1900 if (row > count - 1)
1913 gint vflist_maint_renamed(ViewFile *vf, FileData *fd)
1919 if (g_list_index(vf->list, fd) < 0) return FALSE;
1921 source_base = remove_level_from_path(fd->change->source);
1922 dest_base = remove_level_from_path(fd->change->dest);
1925 if (strcmp(source_base, dest_base) == 0)
1927 GtkTreeStore *store;
1929 GtkTreeIter position;
1933 old_row = g_list_index(vf->list, fd);
1935 vf->list = g_list_remove(vf->list, fd);
1937 vf->list = filelist_insert_sort(vf->list, fd, vf->sort_method, vf->sort_ascend);
1938 n = g_list_index(vf->list, fd);
1940 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
1941 if (vflist_find_row(vf, fd, &iter) >= 0 &&
1942 gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &position, NULL, n))
1946 gtk_tree_store_move_before(store, &iter, &position);
1950 gtk_tree_store_move_after(store, &iter, &position);
1953 gtk_tree_store_set(store, &iter, FILE_COLUMN_NAME, fd->name, -1);
1959 ret = vflist_maint_removed(vf, fd, NULL);
1962 g_free(source_base);
1968 gint vflist_maint_removed(ViewFile *vf, FileData *fd, GList *ignore_list)
1975 row = g_list_index(vf->list, fd);
1976 if (row < 0) return FALSE;
1978 if (vflist_index_is_selected(vf, row) &&
1979 layout_image_get_collection(vf->layout, NULL) == NULL)
1983 n = vf_count(vf, NULL);
1986 new_row = vflist_maint_find_closest(vf, row, n, ignore_list);
1987 DEBUG_1("row = %d, closest is %d", row, new_row);
2003 fd = vf_index_get_data(vf, new_row);
2004 if (vflist_find_row(vf, fd, &iter) >= 0)
2006 GtkTreeSelection *selection;
2008 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
2009 gtk_tree_selection_select_iter(selection, &iter);
2010 vflist_move_cursor(vf, &iter);
2015 fd = vf_index_get_data(vf, row);
2016 if (vflist_find_row(vf, fd, &iter) >= 0)
2018 GtkTreeStore *store;
2019 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
2020 gtk_tree_store_remove(store, &iter);
2022 list = g_list_nth(vf->list, row);
2025 /* thumbnail loader check */
2026 if (fd == vf->thumbs_filedata) vf->thumbs_filedata = NULL;
2027 if (vf->thumbs_count > 0) vf->thumbs_count--;
2029 vf->list = g_list_remove(vf->list, fd);
2030 file_data_unref(fd);
2037 gint vflist_maint_moved(ViewFile *vf, FileData *fd, GList *ignore_list)
2042 if (!fd->change->source || !vf->path) return FALSE;
2044 buf = remove_level_from_path(fd->change->source);
2046 if (strcmp(buf, vf->path) == 0)
2048 ret = vflist_maint_removed(vf, fd, ignore_list);