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;
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 = g_build_filename(vf->path, old, NULL);
386 new_path = g_build_filename(vf->path, new, NULL);
388 if (strchr(new, G_DIR_SEPARATOR) != 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 file_util_rename_simple(fd, new_path, vf->listview);
419 static void vflist_menu_position_cb(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer data)
427 if (vflist_find_row(vf, VFLIST_INFO(vf, click_fd), &iter) < 0) return;
428 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
429 tpath = gtk_tree_model_get_path(store, &iter);
430 tree_view_get_cell_clamped(GTK_TREE_VIEW(vf->listview), tpath, FILE_COLUMN_NAME - 1, TRUE, x, y, &cw, &ch);
431 gtk_tree_path_free(tpath);
433 popup_menu_position_clamp(menu, x, y, 0);
436 gint vflist_press_key_cb(GtkWidget *widget, GdkEventKey *event, gpointer data)
441 if (event->keyval != GDK_Menu) return FALSE;
443 gtk_tree_view_get_cursor(GTK_TREE_VIEW(vf->listview), &tpath, NULL);
449 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
450 gtk_tree_model_get_iter(store, &iter, tpath);
451 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &VFLIST_INFO(vf, click_fd), -1);
452 gtk_tree_path_free(tpath);
456 VFLIST_INFO(vf, click_fd) = NULL;
459 vf->popup = vf_pop_menu(vf);
460 gtk_menu_popup(GTK_MENU(vf->popup), NULL, NULL, vflist_menu_position_cb, vf, 0, GDK_CURRENT_TIME);
465 gint vflist_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
471 GtkTreeViewColumn *column;
473 vf->clicked_mark = 0;
475 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), bevent->x, bevent->y,
476 &tpath, &column, NULL, NULL))
479 gint col_idx = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(column), "column_store_idx"));
481 if (bevent->button == MOUSE_BUTTON_LEFT &&
482 col_idx >= FILE_COLUMN_MARKS && col_idx <= FILE_COLUMN_MARKS_LAST)
485 if (col_idx >= FILE_COLUMN_MARKS && col_idx <= FILE_COLUMN_MARKS_LAST)
486 vf->clicked_mark = 1 + (col_idx - FILE_COLUMN_MARKS);
488 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
490 gtk_tree_model_get_iter(store, &iter, tpath);
491 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
493 gtk_tree_view_set_cursor(GTK_TREE_VIEW(widget), tpath, NULL, FALSE);
495 gtk_tree_path_free(tpath);
498 VFLIST_INFO(vf, click_fd) = fd;
500 if (bevent->button == MOUSE_BUTTON_RIGHT)
502 vf->popup = vf_pop_menu(vf);
503 gtk_menu_popup(GTK_MENU(vf->popup), NULL, NULL, NULL, NULL,
504 bevent->button, bevent->time);
508 if (!fd) return FALSE;
510 if (bevent->button == MOUSE_BUTTON_MIDDLE)
512 if (!vflist_row_is_selected(vf, fd))
514 vflist_color_set(vf, fd, TRUE);
520 if (bevent->button == MOUSE_BUTTON_LEFT && bevent->type == GDK_BUTTON_PRESS &&
521 !(bevent->state & GDK_SHIFT_MASK ) &&
522 !(bevent->state & GDK_CONTROL_MASK ) &&
523 vflist_row_is_selected(vf, fd))
525 GtkTreeSelection *selection;
527 gtk_widget_grab_focus(widget);
530 /* returning FALSE and further processing of the event is needed for
531 correct operation of the expander, to show the sidecar files.
532 It however resets the selection of multiple files. With this condition
533 it should work for both cases */
534 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
535 return (gtk_tree_selection_count_selected_rows(selection) > 1);
539 if (bevent->button == MOUSE_BUTTON_LEFT && bevent->type == GDK_2BUTTON_PRESS)
541 if (vf->layout) layout_image_full_screen_start(vf->layout);
548 gint vflist_release_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
555 if (bevent->button == MOUSE_BUTTON_MIDDLE)
557 vflist_color_set(vf, VFLIST_INFO(vf, click_fd), FALSE);
560 if (bevent->button != MOUSE_BUTTON_LEFT && bevent->button != MOUSE_BUTTON_MIDDLE)
565 if ((bevent->x != 0 || bevent->y != 0) &&
566 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), bevent->x, bevent->y,
567 &tpath, NULL, NULL, NULL))
571 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
572 gtk_tree_model_get_iter(store, &iter, tpath);
573 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
574 gtk_tree_path_free(tpath);
577 if (bevent->button == MOUSE_BUTTON_MIDDLE)
579 if (fd && VFLIST_INFO(vf, click_fd) == fd)
581 GtkTreeSelection *selection;
583 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
584 if (vflist_row_is_selected(vf, fd))
586 gtk_tree_selection_unselect_iter(selection, &iter);
590 gtk_tree_selection_select_iter(selection, &iter);
596 if (fd && VFLIST_INFO(vf, click_fd) == fd &&
597 !(bevent->state & GDK_SHIFT_MASK ) &&
598 !(bevent->state & GDK_CONTROL_MASK ) &&
599 vflist_row_is_selected(vf, fd))
601 GtkTreeSelection *selection;
603 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
604 gtk_tree_selection_unselect_all(selection);
605 gtk_tree_selection_select_iter(selection, &iter);
606 vflist_move_cursor(vf, &iter);
607 // return TRUE;// FIXME - expand
613 static void vflist_select_image(ViewFile *vf, FileData *sel_fd)
615 FileData *read_ahead_fd = NULL;
620 cur_fd = layout_image_get_fd(vf->layout);
621 if (sel_fd == cur_fd) return; /* no change */
623 row = g_list_index(vf->list, sel_fd);
624 // FIXME sidecar data
626 if (sel_fd && options->image.enable_read_ahead && row >= 0)
628 if (row > g_list_index(vf->list, cur_fd) &&
629 (guint) (row + 1) < vf_count(vf, NULL))
631 read_ahead_fd = vf_index_get_data(vf, row + 1);
635 read_ahead_fd = vf_index_get_data(vf, row - 1);
639 layout_image_set_with_ahead(vf->layout, sel_fd, read_ahead_fd);
642 static gint vflist_select_idle_cb(gpointer data)
648 VFLIST_INFO(vf, select_idle_id) = -1;
654 if (VFLIST_INFO(vf, select_fd))
656 vflist_select_image(vf, VFLIST_INFO(vf, select_fd));
657 VFLIST_INFO(vf, select_fd) = NULL;
660 VFLIST_INFO(vf, select_idle_id) = -1;
664 static void vflist_select_idle_cancel(ViewFile *vf)
666 if (VFLIST_INFO(vf, select_idle_id) != -1) g_source_remove(VFLIST_INFO(vf, select_idle_id));
667 VFLIST_INFO(vf, select_idle_id) = -1;
670 static gboolean vflist_select_cb(GtkTreeSelection *selection, GtkTreeModel *store, GtkTreePath *tpath,
671 gboolean path_currently_selected, gpointer data)
676 if (!path_currently_selected &&
677 gtk_tree_model_get_iter(store, &iter, tpath))
679 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &VFLIST_INFO(vf, select_fd), -1);
683 VFLIST_INFO(vf, select_fd) = NULL;
687 VFLIST_INFO(vf, select_idle_id) == -1)
689 VFLIST_INFO(vf, select_idle_id) = g_idle_add(vflist_select_idle_cb, vf);
696 *-----------------------------------------------------------------------------
698 *-----------------------------------------------------------------------------
702 static gboolean vflist_dummy_select_cb(GtkTreeSelection *selection, GtkTreeModel *store, GtkTreePath *tpath,
703 gboolean path_currently_selected, gpointer data)
710 static void vflist_setup_iter(ViewFile *vf, GtkTreeStore *store, GtkTreeIter *iter, FileData *fd)
714 gchar *sidecars = NULL;
716 if (fd->sidecar_files)
717 sidecars = file_data_sc_list_to_string(fd);
718 size = text_from_size(fd->size);
720 gtk_tree_store_set(store, iter, FILE_COLUMN_POINTER, fd,
721 FILE_COLUMN_VERSION, fd->version,
722 FILE_COLUMN_THUMB, (VFLIST_INFO(vf, thumbs_enabled)) ? fd->pixbuf : NULL,
723 FILE_COLUMN_NAME, fd->name,
724 FILE_COLUMN_SIDECARS, sidecars,
725 FILE_COLUMN_SIZE, size,
726 FILE_COLUMN_DATE, text_from_time(fd->date),
727 FILE_COLUMN_COLOR, FALSE, -1);
728 for (i = 0; i < FILEDATA_MARKS_SIZE; i++)
729 gtk_tree_store_set(store, iter, FILE_COLUMN_MARKS + i, fd->marks[i], -1);
736 static void vflist_setup_iter_recursive(ViewFile *vf, GtkTreeStore *store, GtkTreeIter *parent_iter, GList *list, GList *selection)
742 valid = gtk_tree_model_iter_children(GTK_TREE_MODEL(store), &iter, parent_iter);
748 FileData *fd = work->data;
753 FileData *old_fd = NULL;
754 gint old_version = 0;
758 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
759 FILE_COLUMN_POINTER, &old_fd,
760 FILE_COLUMN_VERSION, &old_version,
770 match = filelist_sort_compare_filedata_full(fd, old_fd, SORT_NAME, TRUE); /* always sort sidecars by name */
772 match = filelist_sort_compare_filedata_full(fd, old_fd, vf->sort_method, vf->sort_ascend);
774 if (match == 0) g_warning("multiple fd for the same path");
789 gtk_tree_store_insert_before(store, &new, parent_iter, &iter);
793 gtk_tree_store_append(store, &new, parent_iter);
796 vflist_setup_iter(vf, store, &new, fd);
797 vflist_setup_iter_recursive(vf, store, &new, fd->sidecar_files, selection);
803 valid = gtk_tree_store_remove(store, &iter);
807 if (fd->version != old_version)
809 vflist_setup_iter(vf, store, &iter, fd);
810 vflist_setup_iter_recursive(vf, store, &iter, fd->sidecar_files, selection);
813 if (valid) valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
823 valid = gtk_tree_store_remove(store, &iter);
827 void vflist_sort_set(ViewFile *vf, SortType type, gint ascend)
830 GHashTable *fd_idx_hash = g_hash_table_new(NULL, NULL);
835 if (vf->sort_method == type && vf->sort_ascend == ascend) return;
836 if (!vf->list) return;
842 FileData *fd = work->data;
843 g_hash_table_insert(fd_idx_hash, fd, GINT_TO_POINTER(i));
848 vf->sort_method = type;
849 vf->sort_ascend = ascend;
851 vf->list = filelist_sort(vf->list, vf->sort_method, vf->sort_ascend);
853 new_order = g_malloc(i * sizeof(gint));
859 FileData *fd = work->data;
860 new_order[i] = GPOINTER_TO_INT(g_hash_table_lookup(fd_idx_hash, fd));
865 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
866 gtk_tree_store_reorder(store, NULL, new_order);
869 g_hash_table_destroy(fd_idx_hash);
873 *-----------------------------------------------------------------------------
875 *-----------------------------------------------------------------------------
878 static gint vflist_thumb_next(ViewFile *vf);
880 static void vflist_thumb_status(ViewFile *vf, gdouble val, const gchar *text)
882 if (vf->func_thumb_status)
884 vf->func_thumb_status(vf, val, text, vf->data_thumb_status);
888 static void vflist_thumb_cleanup(ViewFile *vf)
890 vflist_thumb_status(vf, 0.0, NULL);
892 vf->thumbs_count = 0;
893 vf->thumbs_running = FALSE;
895 thumb_loader_free(vf->thumbs_loader);
896 vf->thumbs_loader = NULL;
898 vf->thumbs_filedata = NULL;
901 static void vflist_thumb_stop(ViewFile *vf)
903 if (vf->thumbs_running) vflist_thumb_cleanup(vf);
906 static void vflist_thumb_do(ViewFile *vf, ThumbLoader *tl, FileData *fd)
911 if (!fd || vflist_find_row(vf, fd, &iter) < 0) return;
913 if (fd->pixbuf) g_object_unref(fd->pixbuf);
914 fd->pixbuf = thumb_loader_get_pixbuf(tl, TRUE);
916 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
917 gtk_tree_store_set(store, &iter, FILE_COLUMN_THUMB, fd->pixbuf, -1);
919 vflist_thumb_status(vf, (gdouble)(vf->thumbs_count) / vflist_sidecar_list_count(vf->list), _("Loading thumbs..."));
922 static void vflist_thumb_error_cb(ThumbLoader *tl, gpointer data)
926 if (vf->thumbs_filedata && vf->thumbs_loader == tl)
928 vflist_thumb_do(vf, tl, vf->thumbs_filedata);
931 while (vflist_thumb_next(vf));
934 static void vflist_thumb_done_cb(ThumbLoader *tl, gpointer data)
938 if (vf->thumbs_filedata && vf->thumbs_loader == tl)
940 vflist_thumb_do(vf, tl, vf->thumbs_filedata);
943 while (vflist_thumb_next(vf));
946 static gint vflist_thumb_next(ViewFile *vf)
951 /* first check the visible files */
953 if (GTK_WIDGET_REALIZED(vf->listview) &&
954 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(vf->listview), 0, 0, &tpath, NULL, NULL, NULL))
960 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
961 gtk_tree_model_get_iter(store, &iter, tpath);
962 gtk_tree_path_free(tpath);
964 while (!fd && valid && tree_view_row_get_visibility(GTK_TREE_VIEW(vf->listview), &iter, FALSE) == 0)
966 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
967 if (fd->pixbuf) fd = NULL;
969 valid = gtk_tree_model_iter_next(store, &iter);
973 /* then find first undone */
977 GList *work = vf->list;
980 FileData *fd_p = work->data;
985 GList *work2 = fd_p->sidecar_files;
990 if (!fd_p->pixbuf) fd = fd_p;
1001 vflist_thumb_cleanup(vf);
1007 vf->thumbs_filedata = fd;
1009 thumb_loader_free(vf->thumbs_loader);
1011 vf->thumbs_loader = thumb_loader_new(options->thumbnails.max_width, options->thumbnails.max_height);
1012 thumb_loader_set_callbacks(vf->thumbs_loader,
1013 vflist_thumb_done_cb,
1014 vflist_thumb_error_cb,
1018 if (!thumb_loader_start(vf->thumbs_loader, fd->path))
1020 /* set icon to unknown, continue */
1021 DEBUG_1("thumb loader start failed %s", vf->thumbs_loader->path);
1022 vflist_thumb_do(vf, vf->thumbs_loader, fd);
1030 static void vflist_thumb_update(ViewFile *vf)
1032 vflist_thumb_stop(vf);
1033 if (!VFLIST_INFO(vf, thumbs_enabled)) return;
1035 vflist_thumb_status(vf, 0.0, _("Loading thumbs..."));
1036 vf->thumbs_running = TRUE;
1038 while (vflist_thumb_next(vf));
1042 *-----------------------------------------------------------------------------
1044 *-----------------------------------------------------------------------------
1047 FileData *vflist_index_get_data(ViewFile *vf, gint row)
1049 return g_list_nth_data(vf->list, row);
1052 gint vflist_index_by_path(ViewFile *vf, const gchar *path)
1057 if (!path) return -1;
1062 FileData *fd = work->data;
1063 if (strcmp(path, fd->path) == 0) return p;
1072 guint vflist_count(ViewFile *vf, gint64 *bytes)
1082 FileData *fd = work->data;
1090 return g_list_length(vf->list);
1093 GList *vflist_get_list(ViewFile *vf)
1101 FileData *fd = work->data;
1104 list = g_list_prepend(list, file_data_ref(fd));
1107 return g_list_reverse(list);
1111 *-----------------------------------------------------------------------------
1113 *-----------------------------------------------------------------------------
1116 static gint vflist_row_is_selected(ViewFile *vf, FileData *fd)
1118 GtkTreeModel *store;
1119 GtkTreeSelection *selection;
1124 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1125 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1127 while (!found && work)
1129 GtkTreePath *tpath = work->data;
1133 gtk_tree_model_get_iter(store, &iter, tpath);
1134 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd_n, -1);
1135 if (fd_n == fd) found = TRUE;
1138 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1144 gint vflist_index_is_selected(ViewFile *vf, gint row)
1148 fd = vf_index_get_data(vf, row);
1149 return vflist_row_is_selected(vf, fd);
1152 guint vflist_selection_count(ViewFile *vf, gint64 *bytes)
1154 GtkTreeModel *store;
1155 GtkTreeSelection *selection;
1159 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1160 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1170 GtkTreePath *tpath = work->data;
1174 gtk_tree_model_get_iter(store, &iter, tpath);
1175 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
1184 count = g_list_length(slist);
1185 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1191 GList *vflist_selection_get_list(ViewFile *vf)
1193 GtkTreeModel *store;
1194 GtkTreeSelection *selection;
1199 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1200 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1204 GtkTreePath *tpath = work->data;
1208 gtk_tree_model_get_iter(store, &iter, tpath);
1209 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
1211 list = g_list_prepend(list, file_data_ref(fd));
1215 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1218 return g_list_reverse(list);
1221 GList *vflist_selection_get_list_by_index(ViewFile *vf)
1223 GtkTreeModel *store;
1224 GtkTreeSelection *selection;
1229 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1230 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1234 GtkTreePath *tpath = work->data;
1238 gtk_tree_model_get_iter(store, &iter, tpath);
1239 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
1241 list = g_list_prepend(list, GINT_TO_POINTER(g_list_index(vf->list, fd)));
1245 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1248 return g_list_reverse(list);
1251 void vflist_select_all(ViewFile *vf)
1253 GtkTreeSelection *selection;
1255 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1256 gtk_tree_selection_select_all(selection);
1258 VFLIST_INFO(vf, select_fd) = NULL;
1261 void vflist_select_none(ViewFile *vf)
1263 GtkTreeSelection *selection;
1265 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1266 gtk_tree_selection_unselect_all(selection);
1269 static gboolean tree_model_iter_prev(GtkTreeModel *store, GtkTreeIter *iter)
1274 tpath = gtk_tree_model_get_path(store, iter);
1275 result = gtk_tree_path_prev(tpath);
1277 gtk_tree_model_get_iter(store, iter, tpath);
1279 gtk_tree_path_free(tpath);
1284 static gboolean tree_model_get_iter_last(GtkTreeModel *store, GtkTreeIter *iter)
1286 if (!gtk_tree_model_get_iter_first(store, iter))
1291 GtkTreeIter next = *iter;
1293 if (gtk_tree_model_iter_next(store, &next))
1302 void vflist_select_invert(ViewFile *vf)
1305 GtkTreeSelection *selection;
1306 GtkTreeModel *store;
1309 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
1310 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1312 /* Backward iteration prevents scrolling to the end of the list,
1313 * it scrolls to the first selected row instead. */
1314 valid = tree_model_get_iter_last(store, &iter);
1318 gint selected = gtk_tree_selection_iter_is_selected(selection, &iter);
1321 gtk_tree_selection_unselect_iter(selection, &iter);
1323 gtk_tree_selection_select_iter(selection, &iter);
1325 valid = tree_model_iter_prev(store, &iter);
1329 void vflist_select_by_fd(ViewFile *vf, FileData *fd)
1333 if (vflist_find_row(vf, fd, &iter) < 0) return;
1335 tree_view_row_make_visible(GTK_TREE_VIEW(vf->listview), &iter, TRUE);
1337 if (!vflist_row_is_selected(vf, fd))
1339 GtkTreeSelection *selection;
1340 GtkTreeModel *store;
1343 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1344 gtk_tree_selection_unselect_all(selection);
1345 gtk_tree_selection_select_iter(selection, &iter);
1346 vflist_move_cursor(vf, &iter);
1348 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
1349 tpath = gtk_tree_model_get_path(store, &iter);
1350 gtk_tree_view_set_cursor(GTK_TREE_VIEW(vf->listview), tpath, NULL, FALSE);
1351 gtk_tree_path_free(tpath);
1355 void vflist_mark_to_selection(ViewFile *vf, gint mark, MarkToSelectionMode mode)
1357 GtkTreeModel *store;
1359 GtkTreeSelection *selection;
1363 g_assert(mark >= 1 && mark <= FILEDATA_MARKS_SIZE);
1365 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
1366 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1368 valid = gtk_tree_model_get_iter_first(store, &iter);
1372 gboolean mark_val, selected;
1373 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, FILE_COLUMN_POINTER, &fd, -1);
1375 mark_val = fd->marks[n];
1376 selected = gtk_tree_selection_iter_is_selected(selection, &iter);
1380 case MTS_MODE_SET: selected = mark_val;
1382 case MTS_MODE_OR: selected = mark_val | selected;
1384 case MTS_MODE_AND: selected = mark_val & selected;
1386 case MTS_MODE_MINUS: selected = !mark_val & selected;
1391 gtk_tree_selection_select_iter(selection, &iter);
1393 gtk_tree_selection_unselect_iter(selection, &iter);
1395 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
1399 void vflist_selection_to_mark(ViewFile *vf, gint mark, SelectionToMarkMode mode)
1401 GtkTreeModel *store;
1402 GtkTreeSelection *selection;
1407 g_assert(mark >= 1 && mark <= FILEDATA_MARKS_SIZE);
1409 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1410 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1414 GtkTreePath *tpath = work->data;
1418 gtk_tree_model_get_iter(store, &iter, tpath);
1419 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
1423 case STM_MODE_SET: fd->marks[n] = 1;
1425 case STM_MODE_RESET: fd->marks[n] = 0;
1427 case STM_MODE_TOGGLE: fd->marks[n] = !fd->marks[n];
1431 file_data_increment_version(fd);
1433 gtk_tree_store_set(GTK_TREE_STORE(store), &iter, FILE_COLUMN_MARKS + n, fd->marks[n], -1);
1437 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1442 *-----------------------------------------------------------------------------
1444 *-----------------------------------------------------------------------------
1447 static void vflist_listview_set_height(GtkWidget *listview, gint thumb)
1449 GtkTreeViewColumn *column;
1450 GtkCellRenderer *cell;
1453 column = gtk_tree_view_get_column(GTK_TREE_VIEW(listview), 0); /* first column is thumbnail */
1454 if (!column) return;
1456 gtk_tree_view_column_set_fixed_width(column, ((thumb) ? options->thumbnails.max_width : 4) + 10);
1458 list = gtk_tree_view_column_get_cell_renderers(column);
1463 g_object_set(G_OBJECT(cell), "height", (thumb) ? options->thumbnails.max_height : -1, NULL);
1464 gtk_tree_view_columns_autosize(GTK_TREE_VIEW(listview));
1467 static void vflist_populate_view(ViewFile *vf)
1469 GtkTreeStore *store;
1471 GtkTreeRowReference *visible_row = NULL;
1474 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
1475 thumbs = VFLIST_INFO(vf, thumbs_enabled);
1477 vflist_thumb_stop(vf);
1481 gtk_tree_store_clear(store);
1486 if (GTK_WIDGET_REALIZED(vf->listview) &&
1487 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(vf->listview), 0, 0, &tpath, NULL, NULL, NULL))
1489 visible_row = gtk_tree_row_reference_new(GTK_TREE_MODEL(store), tpath);
1490 gtk_tree_path_free(tpath);
1493 vflist_listview_set_height(vf->listview, thumbs);
1495 vflist_setup_iter_recursive(vf, store, NULL, vf->list, NULL);
1499 if (gtk_tree_row_reference_valid(visible_row))
1501 tpath = gtk_tree_row_reference_get_path(visible_row);
1502 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(vf->listview), tpath, NULL, TRUE, 0.0, 0.0);
1503 gtk_tree_path_free(tpath);
1505 gtk_tree_row_reference_free(visible_row);
1509 vflist_thumb_update(vf);
1512 gint vflist_refresh(ViewFile *vf)
1517 old_list = vf->list;
1520 DEBUG_1("%s vflist_refresh: read dir", get_exec_time());
1523 ret = filelist_read(vf->path, &vf->list, NULL);
1525 DEBUG_1("%s vflist_refresh: sort", get_exec_time());
1527 vf->list = filelist_sort(vf->list, vf->sort_method, vf->sort_ascend);
1529 DEBUG_1("%s vflist_refresh: populate view", get_exec_time());
1531 vflist_populate_view(vf);
1533 filelist_free(old_list);
1534 DEBUG_1("%s vflist_refresh: done", get_exec_time());
1539 /* this overrides the low default of a GtkCellRenderer from 100 to CELL_HEIGHT_OVERRIDE, something sane for our purposes */
1541 #define CELL_HEIGHT_OVERRIDE 512
1543 static void cell_renderer_height_override(GtkCellRenderer *renderer)
1547 spec = g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(renderer)), "height");
1548 if (spec && G_IS_PARAM_SPEC_INT(spec))
1550 GParamSpecInt *spec_int;
1552 spec_int = G_PARAM_SPEC_INT(spec);
1553 if (spec_int->maximum < CELL_HEIGHT_OVERRIDE) spec_int->maximum = CELL_HEIGHT_OVERRIDE;
1557 static GdkColor *vflist_listview_color_shifted(GtkWidget *widget)
1559 static GdkColor color;
1560 static GtkWidget *done = NULL;
1566 style = gtk_widget_get_style(widget);
1567 memcpy(&color, &style->base[GTK_STATE_NORMAL], sizeof(color));
1568 shift_color(&color, -1, 0);
1575 static void vflist_listview_color_cb(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1576 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1578 ViewFile *vf = data;
1581 gtk_tree_model_get(tree_model, iter, FILE_COLUMN_COLOR, &set, -1);
1582 g_object_set(G_OBJECT(cell),
1583 "cell-background-gdk", vflist_listview_color_shifted(vf->listview),
1584 "cell-background-set", set, NULL);
1587 static void vflist_listview_add_column(ViewFile *vf, gint n, const gchar *title, gint image, gint right_justify, gint expand)
1589 GtkTreeViewColumn *column;
1590 GtkCellRenderer *renderer;
1592 column = gtk_tree_view_column_new();
1593 gtk_tree_view_column_set_title(column, title);
1594 gtk_tree_view_column_set_min_width(column, 4);
1598 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_GROW_ONLY);
1599 renderer = gtk_cell_renderer_text_new();
1602 g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
1604 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1605 gtk_tree_view_column_add_attribute(column, renderer, "text", n);
1607 gtk_tree_view_column_set_expand(column, TRUE);
1611 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
1612 renderer = gtk_cell_renderer_pixbuf_new();
1613 cell_renderer_height_override(renderer);
1614 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1615 gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", n);
1618 gtk_tree_view_column_set_cell_data_func(column, renderer, vflist_listview_color_cb, vf, NULL);
1619 g_object_set_data(G_OBJECT(column), "column_store_idx", GUINT_TO_POINTER(n));
1620 g_object_set_data(G_OBJECT(renderer), "column_store_idx", GUINT_TO_POINTER(n));
1622 gtk_tree_view_append_column(GTK_TREE_VIEW(vf->listview), column);
1625 static void vflist_listview_mark_toggled(GtkCellRendererToggle *cell, gchar *path_str, GtkTreeStore *store)
1627 GtkTreePath *path = gtk_tree_path_new_from_string(path_str);
1633 if (!path || !gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, path))
1636 col_idx = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cell), "column_store_idx"));
1638 g_assert(col_idx >= FILE_COLUMN_MARKS && col_idx <= FILE_COLUMN_MARKS_LAST);
1640 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, FILE_COLUMN_POINTER, &fd, col_idx, &mark, -1);
1642 fd->marks[col_idx - FILE_COLUMN_MARKS] = mark;
1643 file_data_increment_version(fd);
1645 gtk_tree_store_set(store, &iter, col_idx, mark, -1);
1646 gtk_tree_path_free(path);
1649 static void vflist_listview_add_column_toggle(ViewFile *vf, gint n, const gchar *title)
1651 GtkTreeViewColumn *column;
1652 GtkCellRenderer *renderer;
1653 GtkTreeStore *store;
1656 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
1658 renderer = gtk_cell_renderer_toggle_new();
1659 column = gtk_tree_view_column_new_with_attributes(title, renderer, "active", n, NULL);
1661 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
1662 g_object_set_data(G_OBJECT(column), "column_store_idx", GUINT_TO_POINTER(n));
1663 g_object_set_data(G_OBJECT(renderer), "column_store_idx", GUINT_TO_POINTER(n));
1665 index = gtk_tree_view_append_column(GTK_TREE_VIEW(vf->listview), column);
1666 gtk_tree_view_column_set_fixed_width(column, 16);
1667 gtk_tree_view_column_set_visible(column, vf->marks_enabled);
1670 g_signal_connect(G_OBJECT(renderer), "toggled", G_CALLBACK(vflist_listview_mark_toggled), store);
1674 *-----------------------------------------------------------------------------
1676 *-----------------------------------------------------------------------------
1679 gint vflist_set_path(ViewFile *vf, const gchar *path)
1681 GtkTreeStore *store;
1683 if (!path) return FALSE;
1684 if (vf->path && strcmp(path, vf->path) == 0) return TRUE;
1687 vf->path = g_strdup(path);
1689 /* force complete reload */
1690 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
1691 gtk_tree_store_clear(store);
1693 filelist_free(vf->list);
1696 return vf_refresh(vf);
1699 void vflist_destroy_cb(GtkWidget *widget, gpointer data)
1701 ViewFile *vf = data;
1703 vflist_select_idle_cancel(vf);
1704 vflist_thumb_stop(vf);
1706 filelist_free(vf->list);
1709 ViewFile *vflist_new(ViewFile *vf, const gchar *path)
1711 GtkTreeStore *store;
1712 GtkTreeSelection *selection;
1714 GType flist_types[FILE_COLUMN_COUNT];
1717 vf->info = g_new0(ViewFileInfoList, 1);
1719 VFLIST_INFO(vf, click_fd) = NULL;
1720 VFLIST_INFO(vf, select_fd) = NULL;
1721 VFLIST_INFO(vf, thumbs_enabled) = FALSE;
1723 VFLIST_INFO(vf, select_idle_id) = -1;
1725 flist_types[FILE_COLUMN_POINTER] = G_TYPE_POINTER;
1726 flist_types[FILE_COLUMN_VERSION] = G_TYPE_INT;
1727 flist_types[FILE_COLUMN_THUMB] = GDK_TYPE_PIXBUF;
1728 flist_types[FILE_COLUMN_NAME] = G_TYPE_STRING;
1729 flist_types[FILE_COLUMN_SIDECARS] = G_TYPE_STRING;
1730 flist_types[FILE_COLUMN_SIZE] = G_TYPE_STRING;
1731 flist_types[FILE_COLUMN_DATE] = G_TYPE_STRING;
1732 flist_types[FILE_COLUMN_COLOR] = G_TYPE_BOOLEAN;
1733 for (i = FILE_COLUMN_MARKS; i < FILE_COLUMN_MARKS + FILEDATA_MARKS_SIZE; i++)
1734 flist_types[i] = G_TYPE_BOOLEAN;
1736 store = gtk_tree_store_newv(FILE_COLUMN_COUNT, flist_types);
1738 vf->listview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
1739 g_object_unref(store);
1741 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1742 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
1743 gtk_tree_selection_set_select_function(selection, vflist_select_cb, vf, NULL);
1745 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(vf->listview), FALSE);
1746 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(vf->listview), FALSE);
1748 vflist_listview_add_column(vf, FILE_COLUMN_THUMB, "", TRUE, FALSE, FALSE);
1750 for (i = 0; i < FILEDATA_MARKS_SIZE; i++)
1751 vflist_listview_add_column_toggle(vf, i + FILE_COLUMN_MARKS, "");
1753 vflist_listview_add_column(vf, FILE_COLUMN_NAME, _("Name"), FALSE, FALSE, FALSE);
1754 vflist_listview_add_column(vf, FILE_COLUMN_SIDECARS, _("SC"), FALSE, FALSE, FALSE);
1756 vflist_listview_add_column(vf, FILE_COLUMN_SIZE, _("Size"), FALSE, TRUE, FALSE);
1757 vflist_listview_add_column(vf, FILE_COLUMN_DATE, _("Date"), FALSE, TRUE, FALSE);
1762 void vflist_thumb_set(ViewFile *vf, gint enable)
1764 if (VFLIST_INFO(vf, thumbs_enabled) == enable) return;
1766 VFLIST_INFO(vf, thumbs_enabled) = enable;
1767 if (vf->layout) vf_refresh(vf);
1770 void vflist_marks_set(ViewFile *vf, gint enable)
1772 GList *columns, *work;
1774 if (vf->marks_enabled == enable) return;
1776 vf->marks_enabled = enable;
1778 columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(vf->listview));
1783 GtkTreeViewColumn *column = work->data;
1784 gint col_idx = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(column), "column_store_idx"));
1787 if (col_idx <= FILE_COLUMN_MARKS_LAST && col_idx >= FILE_COLUMN_MARKS)
1788 gtk_tree_view_column_set_visible(column, enable);
1791 g_list_free(columns);
1796 *-----------------------------------------------------------------------------
1797 * maintenance (for rename, move, remove)
1798 *-----------------------------------------------------------------------------
1801 static gint vflist_maint_find_closest(ViewFile *vf, gint row, gint count, GList *ignore_list)
1811 gint f = vf_index_by_path(vf, work->data);
1812 if (f >= 0) list = g_list_prepend(list, GINT_TO_POINTER(f));
1822 gpointer p = work->data;
1824 if (row == GPOINTER_TO_INT(p))
1829 if (rev == GPOINTER_TO_INT(p))
1834 if (!c) list = g_list_remove(list, p);
1842 if (row > count - 1)
1855 gint vflist_maint_renamed(ViewFile *vf, FileData *fd)
1861 DEBUG_1("%s vflist_maint_renamed: start", get_exec_time());
1863 if (g_list_index(vf->list, fd) < 0) return FALSE;
1865 source_base = remove_level_from_path(fd->change->source);
1866 dest_base = remove_level_from_path(fd->change->dest);
1869 if (strcmp(source_base, dest_base) == 0)
1871 GtkTreeStore *store;
1873 GtkTreeIter position;
1877 old_row = g_list_index(vf->list, fd);
1879 vf->list = g_list_remove(vf->list, fd);
1881 vf->list = filelist_insert_sort(vf->list, fd, vf->sort_method, vf->sort_ascend);
1882 n = g_list_index(vf->list, fd);
1884 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
1885 if (vflist_find_row(vf, fd, &iter) >= 0 &&
1886 gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &position, NULL, n))
1890 gtk_tree_store_move_before(store, &iter, &position);
1894 gtk_tree_store_move_after(store, &iter, &position);
1897 gtk_tree_store_set(store, &iter, FILE_COLUMN_NAME, fd->name, -1);
1903 ret = vflist_maint_removed(vf, fd, NULL);
1906 g_free(source_base);
1909 DEBUG_1("%s vflist_maint_renamed: done", get_exec_time());
1914 gint vflist_maint_removed(ViewFile *vf, FileData *fd, GList *ignore_list)
1921 DEBUG_1("%s vflist_maint_removed: start", get_exec_time());
1923 row = g_list_index(vf->list, fd);
1924 if (row < 0) return FALSE;
1926 if (vflist_index_is_selected(vf, row) &&
1927 layout_image_get_collection(vf->layout, NULL) == NULL)
1931 n = vf_count(vf, NULL);
1934 new_row = vflist_maint_find_closest(vf, row, n, ignore_list);
1935 DEBUG_1("row = %d, closest is %d", row, new_row);
1951 fd = vf_index_get_data(vf, new_row);
1952 if (vflist_find_row(vf, fd, &iter) >= 0)
1954 GtkTreeSelection *selection;
1956 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1957 gtk_tree_selection_select_iter(selection, &iter);
1958 vflist_move_cursor(vf, &iter);
1963 fd = vf_index_get_data(vf, row);
1964 if (vflist_find_row(vf, fd, &iter) >= 0)
1966 GtkTreeStore *store;
1967 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
1968 gtk_tree_store_remove(store, &iter);
1970 list = g_list_nth(vf->list, row);
1973 /* thumbnail loader check */
1974 if (fd == vf->thumbs_filedata) vf->thumbs_filedata = NULL;
1975 if (vf->thumbs_count > 0) vf->thumbs_count--;
1977 vf->list = g_list_remove(vf->list, fd);
1978 file_data_unref(fd);
1982 DEBUG_1("%s vflist_maint_removed: done", get_exec_time());
1987 gint vflist_maint_moved(ViewFile *vf, FileData *fd, GList *ignore_list)
1992 if (!fd->change->source || !vf->path) return FALSE;
1994 buf = remove_level_from_path(fd->change->source);
1996 if (strcmp(buf, vf->path) == 0)
1998 ret = vflist_maint_removed(vf, fd, ignore_list);