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,
44 FILE_COLUMN_MARKS_LAST = FILE_COLUMN_MARKS + FILEDATA_MARKS_SIZE - 1,
49 static gint vflist_row_is_selected(ViewFile *vf, FileData *fd);
50 static gint vflist_row_rename_cb(TreeEditData *td, const gchar *old, const gchar *new, gpointer data);
51 static void vflist_populate_view(ViewFile *vf);
55 *-----------------------------------------------------------------------------
57 *-----------------------------------------------------------------------------
64 } ViewFileFindRowData;
66 static gboolean vflist_find_row_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
68 ViewFileFindRowData *find = data;
70 gtk_tree_model_get(model, iter, FILE_COLUMN_POINTER, &fd, -1);
81 static gint vflist_find_row(ViewFile *vf, FileData *fd, GtkTreeIter *iter)
84 ViewFileFindRowData data = {fd, iter, 0, 0};
86 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
87 gtk_tree_model_foreach(store, vflist_find_row_cb, &data);
99 static gint vflist_find_sidecar_list_idx(GList *work, FileData *fd)
104 FileData *fd_p = work->data;
105 if (fd == fd_p) return i;
109 GList *work2 = fd_p->sidecar_files;
113 if (fd == fd_p) return i;
124 static gint vflist_sidecar_list_count(GList *work)
129 FileData *fd = work->data;
132 GList *work2 = fd->sidecar_files;
144 void vflist_color_set(ViewFile *vf, FileData *fd, gint color_set)
149 if (vflist_find_row(vf, fd, &iter) < 0) return;
150 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
151 gtk_tree_store_set(GTK_TREE_STORE(store), &iter, FILE_COLUMN_COLOR, color_set, -1);
154 static void vflist_move_cursor(ViewFile *vf, GtkTreeIter *iter)
159 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
161 tpath = gtk_tree_model_get_path(store, iter);
162 gtk_tree_view_set_cursor(GTK_TREE_VIEW(vf->listview), tpath, NULL, FALSE);
163 gtk_tree_path_free(tpath);
167 static gint vflist_column_idx(ViewFile *vf, gint store_idx)
169 GList *columns, *work;
172 columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(vf->listview));
176 GtkTreeViewColumn *column = work->data;
177 if (store_idx == GPOINTER_TO_INT(g_object_get_data (G_OBJECT(column), "column_store_idx")))
183 g_list_free(columns);
189 *-----------------------------------------------------------------------------
191 *-----------------------------------------------------------------------------
194 static void vflist_dnd_get(GtkWidget *widget, GdkDragContext *context,
195 GtkSelectionData *selection_data, guint info,
196 guint time, gpointer data)
200 gchar *uri_text = NULL;
203 if (!VFLIST_INFO(vf, click_fd)) return;
205 if (vflist_row_is_selected(vf, VFLIST_INFO(vf, click_fd)))
207 list = vf_selection_get_list(vf);
211 list = g_list_append(NULL, file_data_ref(VFLIST_INFO(vf, click_fd)));
216 uri_text = uri_text_from_filelist(list, &total, (info == TARGET_TEXT_PLAIN));
221 gtk_selection_data_set(selection_data, selection_data->target,
222 8, (guchar *)uri_text, total);
226 static void vflist_dnd_begin(GtkWidget *widget, GdkDragContext *context, gpointer data)
230 vflist_color_set(vf, VFLIST_INFO(vf, click_fd), TRUE);
232 if (VFLIST_INFO(vf, thumbs_enabled) &&
233 VFLIST_INFO(vf, click_fd) && VFLIST_INFO(vf, click_fd)->pixbuf)
237 if (vflist_row_is_selected(vf, VFLIST_INFO(vf, click_fd)))
238 items = vf_selection_count(vf, NULL);
242 dnd_set_drag_icon(widget, context, VFLIST_INFO(vf, click_fd)->pixbuf, items);
246 static void vflist_dnd_end(GtkWidget *widget, GdkDragContext *context, gpointer data)
250 vflist_color_set(vf, VFLIST_INFO(vf, click_fd), FALSE);
252 if (context->action == GDK_ACTION_MOVE)
258 void vflist_dnd_init(ViewFile *vf)
260 gtk_drag_source_set(vf->listview, GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
261 dnd_file_drag_types, dnd_file_drag_types_count,
262 GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK);
263 g_signal_connect(G_OBJECT(vf->listview), "drag_data_get",
264 G_CALLBACK(vflist_dnd_get), vf);
265 g_signal_connect(G_OBJECT(vf->listview), "drag_begin",
266 G_CALLBACK(vflist_dnd_begin), vf);
267 g_signal_connect(G_OBJECT(vf->listview), "drag_end",
268 G_CALLBACK(vflist_dnd_end), vf);
272 *-----------------------------------------------------------------------------
274 *-----------------------------------------------------------------------------
277 GList *vflist_pop_menu_file_list(ViewFile *vf)
279 if (!VFLIST_INFO(vf, click_fd)) return NULL;
281 if (vflist_row_is_selected(vf, VFLIST_INFO(vf, click_fd)))
283 return vf_selection_get_list(vf);
286 return g_list_append(NULL, file_data_ref(VFLIST_INFO(vf, click_fd)));
289 void vflist_pop_menu_view_cb(GtkWidget *widget, gpointer data)
293 if (vflist_row_is_selected(vf, VFLIST_INFO(vf, click_fd)))
297 list = vf_selection_get_list(vf);
298 view_window_new_from_list(list);
303 view_window_new(VFLIST_INFO(vf, click_fd));
307 void vflist_pop_menu_rename_cb(GtkWidget *widget, gpointer data)
312 list = vf_pop_menu_file_list(vf);
313 if (options->file_ops.enable_in_place_rename &&
314 list && !list->next && VFLIST_INFO(vf, click_fd))
321 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
322 if (vflist_find_row(vf, VFLIST_INFO(vf, click_fd), &iter) >= 0)
326 tpath = gtk_tree_model_get_path(store, &iter);
327 tree_edit_by_path(GTK_TREE_VIEW(vf->listview), tpath,
328 vflist_column_idx(vf, FILE_COLUMN_NAME), VFLIST_INFO(vf, click_fd)->name,
329 vflist_row_rename_cb, vf);
330 gtk_tree_path_free(tpath);
335 file_util_rename(NULL, list, vf->listview);
338 void vflist_pop_menu_thumbs_cb(GtkWidget *widget, gpointer data)
342 vflist_color_set(vf, VFLIST_INFO(vf, click_fd), FALSE);
345 layout_thumb_set(vf->layout, !VFLIST_INFO(vf, thumbs_enabled));
349 vflist_thumb_set(vf, !VFLIST_INFO(vf, thumbs_enabled));
353 void vflist_pop_menu_refresh_cb(GtkWidget *widget, gpointer data)
357 vflist_color_set(vf, VFLIST_INFO(vf, click_fd), FALSE);
361 void vflist_popup_destroy_cb(GtkWidget *widget, gpointer data)
364 vflist_color_set(vf, VFLIST_INFO(vf, click_fd), FALSE);
365 VFLIST_INFO(vf, click_fd) = NULL;
371 *-----------------------------------------------------------------------------
373 *-----------------------------------------------------------------------------
376 static gint vflist_row_rename_cb(TreeEditData *td, const gchar *old, const gchar *new, gpointer data)
382 if (strlen(new) == 0) return FALSE;
384 old_path = g_build_filename(vf->path, old, NULL);
385 new_path = g_build_filename(vf->path, new, NULL);
387 if (strchr(new, G_DIR_SEPARATOR) != NULL)
389 gchar *text = g_strdup_printf(_("Invalid file name:\n%s"), new);
390 file_util_warning_dialog(_("Error renaming file"), text, GTK_STOCK_DIALOG_ERROR, vf->listview);
393 else if (isfile(new_path))
395 gchar *text = g_strdup_printf(_("A file with name %s already exists."), new);
396 file_util_warning_dialog(_("Error renaming file"), text, GTK_STOCK_DIALOG_ERROR, vf->listview);
401 gint row = vf_index_by_path(vf, old_path);
404 GList *work = g_list_nth(vf->list, row);
405 FileData *fd = work->data;
407 file_util_rename_simple(fd, new_path, vf->listview);
418 static void vflist_menu_position_cb(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer data)
426 if (vflist_find_row(vf, VFLIST_INFO(vf, click_fd), &iter) < 0) return;
427 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
428 tpath = gtk_tree_model_get_path(store, &iter);
429 tree_view_get_cell_clamped(GTK_TREE_VIEW(vf->listview), tpath, FILE_COLUMN_NAME - 1, TRUE, x, y, &cw, &ch);
430 gtk_tree_path_free(tpath);
432 popup_menu_position_clamp(menu, x, y, 0);
435 gint vflist_press_key_cb(GtkWidget *widget, GdkEventKey *event, gpointer data)
440 if (event->keyval != GDK_Menu) return FALSE;
442 gtk_tree_view_get_cursor(GTK_TREE_VIEW(vf->listview), &tpath, NULL);
448 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
449 gtk_tree_model_get_iter(store, &iter, tpath);
450 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &VFLIST_INFO(vf, click_fd), -1);
451 gtk_tree_path_free(tpath);
455 VFLIST_INFO(vf, click_fd) = NULL;
458 vf->popup = vf_pop_menu(vf);
459 gtk_menu_popup(GTK_MENU(vf->popup), NULL, NULL, vflist_menu_position_cb, vf, 0, GDK_CURRENT_TIME);
464 gint vflist_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
470 GtkTreeViewColumn *column;
472 vf->clicked_mark = 0;
474 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), bevent->x, bevent->y,
475 &tpath, &column, NULL, NULL))
478 gint col_idx = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(column), "column_store_idx"));
480 if (bevent->button == MOUSE_BUTTON_LEFT &&
481 col_idx >= FILE_COLUMN_MARKS && col_idx <= FILE_COLUMN_MARKS_LAST)
484 if (col_idx >= FILE_COLUMN_MARKS && col_idx <= FILE_COLUMN_MARKS_LAST)
485 vf->clicked_mark = 1 + (col_idx - FILE_COLUMN_MARKS);
487 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
489 gtk_tree_model_get_iter(store, &iter, tpath);
490 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
492 gtk_tree_view_set_cursor(GTK_TREE_VIEW(widget), tpath, NULL, FALSE);
494 gtk_tree_path_free(tpath);
497 VFLIST_INFO(vf, click_fd) = fd;
499 if (bevent->button == MOUSE_BUTTON_RIGHT)
501 vf->popup = vf_pop_menu(vf);
502 gtk_menu_popup(GTK_MENU(vf->popup), NULL, NULL, NULL, NULL,
503 bevent->button, bevent->time);
507 if (!fd) return FALSE;
509 if (bevent->button == MOUSE_BUTTON_MIDDLE)
511 if (!vflist_row_is_selected(vf, fd))
513 vflist_color_set(vf, fd, TRUE);
519 if (bevent->button == MOUSE_BUTTON_LEFT && bevent->type == GDK_BUTTON_PRESS &&
520 !(bevent->state & GDK_SHIFT_MASK ) &&
521 !(bevent->state & GDK_CONTROL_MASK ) &&
522 vflist_row_is_selected(vf, fd))
524 GtkTreeSelection *selection;
526 gtk_widget_grab_focus(widget);
529 /* returning FALSE and further processing of the event is needed for
530 correct operation of the expander, to show the sidecar files.
531 It however resets the selection of multiple files. With this condition
532 it should work for both cases */
533 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
534 return (gtk_tree_selection_count_selected_rows(selection) > 1);
538 if (bevent->button == MOUSE_BUTTON_LEFT && bevent->type == GDK_2BUTTON_PRESS)
540 if (vf->layout) layout_image_full_screen_start(vf->layout);
547 gint vflist_release_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
554 if (bevent->button == MOUSE_BUTTON_MIDDLE)
556 vflist_color_set(vf, VFLIST_INFO(vf, click_fd), FALSE);
559 if (bevent->button != MOUSE_BUTTON_LEFT && bevent->button != MOUSE_BUTTON_MIDDLE)
564 if ((bevent->x != 0 || bevent->y != 0) &&
565 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), bevent->x, bevent->y,
566 &tpath, NULL, NULL, NULL))
570 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
571 gtk_tree_model_get_iter(store, &iter, tpath);
572 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
573 gtk_tree_path_free(tpath);
576 if (bevent->button == MOUSE_BUTTON_MIDDLE)
578 if (fd && VFLIST_INFO(vf, click_fd) == fd)
580 GtkTreeSelection *selection;
582 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
583 if (vflist_row_is_selected(vf, fd))
585 gtk_tree_selection_unselect_iter(selection, &iter);
589 gtk_tree_selection_select_iter(selection, &iter);
595 if (fd && VFLIST_INFO(vf, click_fd) == fd &&
596 !(bevent->state & GDK_SHIFT_MASK ) &&
597 !(bevent->state & GDK_CONTROL_MASK ) &&
598 vflist_row_is_selected(vf, fd))
600 GtkTreeSelection *selection;
602 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
603 gtk_tree_selection_unselect_all(selection);
604 gtk_tree_selection_select_iter(selection, &iter);
605 vflist_move_cursor(vf, &iter);
606 // return TRUE;// FIXME - expand
612 static void vflist_select_image(ViewFile *vf, FileData *sel_fd)
614 FileData *read_ahead_fd = NULL;
619 cur_fd = layout_image_get_fd(vf->layout);
620 if (sel_fd == cur_fd) return; /* no change */
622 row = g_list_index(vf->list, sel_fd);
623 // FIXME sidecar data
625 if (sel_fd && options->image.enable_read_ahead && row >= 0)
627 if (row > g_list_index(vf->list, cur_fd) &&
628 (guint) (row + 1) < vf_count(vf, NULL))
630 read_ahead_fd = vf_index_get_data(vf, row + 1);
634 read_ahead_fd = vf_index_get_data(vf, row - 1);
638 layout_image_set_with_ahead(vf->layout, sel_fd, read_ahead_fd);
641 static gint vflist_select_idle_cb(gpointer data)
647 VFLIST_INFO(vf, select_idle_id) = -1;
653 if (VFLIST_INFO(vf, select_fd))
655 vflist_select_image(vf, VFLIST_INFO(vf, select_fd));
656 VFLIST_INFO(vf, select_fd) = NULL;
659 VFLIST_INFO(vf, select_idle_id) = -1;
663 static void vflist_select_idle_cancel(ViewFile *vf)
665 if (VFLIST_INFO(vf, select_idle_id) != -1) g_source_remove(VFLIST_INFO(vf, select_idle_id));
666 VFLIST_INFO(vf, select_idle_id) = -1;
669 static gboolean vflist_select_cb(GtkTreeSelection *selection, GtkTreeModel *store, GtkTreePath *tpath,
670 gboolean path_currently_selected, gpointer data)
675 if (!path_currently_selected &&
676 gtk_tree_model_get_iter(store, &iter, tpath))
678 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &VFLIST_INFO(vf, select_fd), -1);
682 VFLIST_INFO(vf, select_fd) = NULL;
686 VFLIST_INFO(vf, select_idle_id) == -1)
688 VFLIST_INFO(vf, select_idle_id) = g_idle_add(vflist_select_idle_cb, vf);
695 *-----------------------------------------------------------------------------
697 *-----------------------------------------------------------------------------
701 static gboolean vflist_dummy_select_cb(GtkTreeSelection *selection, GtkTreeModel *store, GtkTreePath *tpath,
702 gboolean path_currently_selected, gpointer data)
709 static void vflist_setup_iter(ViewFile *vf, GtkTreeStore *store, GtkTreeIter *iter, FileData *fd)
713 gchar *sidecars = NULL;
715 if (fd->sidecar_files)
716 sidecars = file_data_sc_list_to_string(fd);
717 size = text_from_size(fd->size);
719 gtk_tree_store_set(store, iter, FILE_COLUMN_POINTER, fd,
720 FILE_COLUMN_THUMB, (VFLIST_INFO(vf, thumbs_enabled)) ? fd->pixbuf : NULL,
721 FILE_COLUMN_NAME, fd->name,
722 FILE_COLUMN_SIDECARS, sidecars,
723 FILE_COLUMN_SIZE, size,
724 FILE_COLUMN_DATE, text_from_time(fd->date),
725 FILE_COLUMN_COLOR, FALSE, -1);
726 for (i = 0; i < FILEDATA_MARKS_SIZE; i++)
727 gtk_tree_store_set(store, iter, FILE_COLUMN_MARKS + i, fd->marks[i], -1);
734 static void vflist_setup_iter_with_sidecars(ViewFile *vf, GtkTreeStore *store, GtkTreeIter *iter, FileData *fd)
740 vflist_setup_iter(vf, store, iter, fd);
743 /* this is almost the same code as in vflist_populate_view
744 maybe it should be made more generic and used in both places */
747 valid = gtk_tree_model_iter_children(GTK_TREE_MODEL(store), &s_iter, iter);
749 work = fd->sidecar_files;
753 FileData *sfd = work->data;
758 FileData *old_sfd = NULL;
762 gtk_tree_model_get(GTK_TREE_MODEL(store), &s_iter, FILE_COLUMN_POINTER, &old_sfd, -1);
770 match = filelist_sort_compare_filedata_full(sfd, old_sfd, SORT_NAME, TRUE);
785 gtk_tree_store_insert_before(store, &new, iter, &s_iter);
789 gtk_tree_store_append(store, &new, iter);
792 vflist_setup_iter(vf, store, &new, sfd);
798 valid = gtk_tree_store_remove(store, &s_iter);
802 vflist_setup_iter(vf, store, &s_iter, sfd);
804 if (valid) valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &s_iter);
814 valid = gtk_tree_store_remove(store, &s_iter);
818 void vflist_sort_set(ViewFile *vf, SortType type, gint ascend)
821 GHashTable *fd_idx_hash = g_hash_table_new(NULL, NULL);
826 if (vf->sort_method == type && vf->sort_ascend == ascend) return;
827 if (!vf->list) return;
833 FileData *fd = work->data;
834 g_hash_table_insert(fd_idx_hash, fd, GINT_TO_POINTER(i));
839 vf->sort_method = type;
840 vf->sort_ascend = ascend;
842 vf->list = filelist_sort(vf->list, vf->sort_method, vf->sort_ascend);
844 new_order = g_malloc(i * sizeof(gint));
850 FileData *fd = work->data;
851 new_order[i] = GPOINTER_TO_INT(g_hash_table_lookup(fd_idx_hash, fd));
856 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
857 gtk_tree_store_reorder(store, NULL, new_order);
860 g_hash_table_destroy(fd_idx_hash);
864 *-----------------------------------------------------------------------------
866 *-----------------------------------------------------------------------------
869 static gint vflist_thumb_next(ViewFile *vf);
871 static void vflist_thumb_status(ViewFile *vf, gdouble val, const gchar *text)
873 if (vf->func_thumb_status)
875 vf->func_thumb_status(vf, val, text, vf->data_thumb_status);
879 static void vflist_thumb_cleanup(ViewFile *vf)
881 vflist_thumb_status(vf, 0.0, NULL);
883 vf->thumbs_count = 0;
884 vf->thumbs_running = FALSE;
886 thumb_loader_free(vf->thumbs_loader);
887 vf->thumbs_loader = NULL;
889 vf->thumbs_filedata = NULL;
892 static void vflist_thumb_stop(ViewFile *vf)
894 if (vf->thumbs_running) vflist_thumb_cleanup(vf);
897 static void vflist_thumb_do(ViewFile *vf, ThumbLoader *tl, FileData *fd)
902 if (!fd || vflist_find_row(vf, fd, &iter) < 0) return;
904 if (fd->pixbuf) g_object_unref(fd->pixbuf);
905 fd->pixbuf = thumb_loader_get_pixbuf(tl, TRUE);
907 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
908 gtk_tree_store_set(store, &iter, FILE_COLUMN_THUMB, fd->pixbuf, -1);
910 vflist_thumb_status(vf, (gdouble)(vf->thumbs_count) / vflist_sidecar_list_count(vf->list), _("Loading thumbs..."));
913 static void vflist_thumb_error_cb(ThumbLoader *tl, gpointer data)
917 if (vf->thumbs_filedata && vf->thumbs_loader == tl)
919 vflist_thumb_do(vf, tl, vf->thumbs_filedata);
922 while (vflist_thumb_next(vf));
925 static void vflist_thumb_done_cb(ThumbLoader *tl, gpointer data)
929 if (vf->thumbs_filedata && vf->thumbs_loader == tl)
931 vflist_thumb_do(vf, tl, vf->thumbs_filedata);
934 while (vflist_thumb_next(vf));
937 static gint vflist_thumb_next(ViewFile *vf)
942 /* first check the visible files */
944 if (GTK_WIDGET_REALIZED(vf->listview) &&
945 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(vf->listview), 0, 0, &tpath, NULL, NULL, NULL))
951 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
952 gtk_tree_model_get_iter(store, &iter, tpath);
953 gtk_tree_path_free(tpath);
955 while (!fd && valid && tree_view_row_get_visibility(GTK_TREE_VIEW(vf->listview), &iter, FALSE) == 0)
957 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
958 if (fd->pixbuf) fd = NULL;
960 valid = gtk_tree_model_iter_next(store, &iter);
964 /* then find first undone */
968 GList *work = vf->list;
971 FileData *fd_p = work->data;
976 GList *work2 = fd_p->sidecar_files;
981 if (!fd_p->pixbuf) fd = fd_p;
992 vflist_thumb_cleanup(vf);
998 vf->thumbs_filedata = fd;
1000 thumb_loader_free(vf->thumbs_loader);
1002 vf->thumbs_loader = thumb_loader_new(options->thumbnails.max_width, options->thumbnails.max_height);
1003 thumb_loader_set_callbacks(vf->thumbs_loader,
1004 vflist_thumb_done_cb,
1005 vflist_thumb_error_cb,
1009 if (!thumb_loader_start(vf->thumbs_loader, fd->path))
1011 /* set icon to unknown, continue */
1012 DEBUG_1("thumb loader start failed %s", vf->thumbs_loader->path);
1013 vflist_thumb_do(vf, vf->thumbs_loader, fd);
1021 static void vflist_thumb_update(ViewFile *vf)
1023 vflist_thumb_stop(vf);
1024 if (!VFLIST_INFO(vf, thumbs_enabled)) return;
1026 vflist_thumb_status(vf, 0.0, _("Loading thumbs..."));
1027 vf->thumbs_running = TRUE;
1029 while (vflist_thumb_next(vf));
1033 *-----------------------------------------------------------------------------
1035 *-----------------------------------------------------------------------------
1038 FileData *vflist_index_get_data(ViewFile *vf, gint row)
1040 return g_list_nth_data(vf->list, row);
1043 gint vflist_index_by_path(ViewFile *vf, const gchar *path)
1048 if (!path) return -1;
1053 FileData *fd = work->data;
1054 if (strcmp(path, fd->path) == 0) return p;
1063 guint vflist_count(ViewFile *vf, gint64 *bytes)
1073 FileData *fd = work->data;
1081 return g_list_length(vf->list);
1084 GList *vflist_get_list(ViewFile *vf)
1092 FileData *fd = work->data;
1095 list = g_list_prepend(list, file_data_ref(fd));
1098 return g_list_reverse(list);
1102 *-----------------------------------------------------------------------------
1104 *-----------------------------------------------------------------------------
1107 static gint vflist_row_is_selected(ViewFile *vf, FileData *fd)
1109 GtkTreeModel *store;
1110 GtkTreeSelection *selection;
1115 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1116 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1118 while (!found && work)
1120 GtkTreePath *tpath = work->data;
1124 gtk_tree_model_get_iter(store, &iter, tpath);
1125 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd_n, -1);
1126 if (fd_n == fd) found = TRUE;
1129 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1135 gint vflist_index_is_selected(ViewFile *vf, gint row)
1139 fd = vf_index_get_data(vf, row);
1140 return vflist_row_is_selected(vf, fd);
1143 guint vflist_selection_count(ViewFile *vf, gint64 *bytes)
1145 GtkTreeModel *store;
1146 GtkTreeSelection *selection;
1150 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1151 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1161 GtkTreePath *tpath = work->data;
1165 gtk_tree_model_get_iter(store, &iter, tpath);
1166 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
1175 count = g_list_length(slist);
1176 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1182 GList *vflist_selection_get_list(ViewFile *vf)
1184 GtkTreeModel *store;
1185 GtkTreeSelection *selection;
1190 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1191 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1195 GtkTreePath *tpath = work->data;
1199 gtk_tree_model_get_iter(store, &iter, tpath);
1200 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
1202 list = g_list_prepend(list, file_data_ref(fd));
1206 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1209 return g_list_reverse(list);
1212 GList *vflist_selection_get_list_by_index(ViewFile *vf)
1214 GtkTreeModel *store;
1215 GtkTreeSelection *selection;
1220 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1221 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1225 GtkTreePath *tpath = work->data;
1229 gtk_tree_model_get_iter(store, &iter, tpath);
1230 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
1232 list = g_list_prepend(list, GINT_TO_POINTER(g_list_index(vf->list, fd)));
1236 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1239 return g_list_reverse(list);
1242 void vflist_select_all(ViewFile *vf)
1244 GtkTreeSelection *selection;
1246 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1247 gtk_tree_selection_select_all(selection);
1249 VFLIST_INFO(vf, select_fd) = NULL;
1252 void vflist_select_none(ViewFile *vf)
1254 GtkTreeSelection *selection;
1256 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1257 gtk_tree_selection_unselect_all(selection);
1260 static gboolean tree_model_iter_prev(GtkTreeModel *store, GtkTreeIter *iter)
1265 tpath = gtk_tree_model_get_path(store, iter);
1266 result = gtk_tree_path_prev(tpath);
1268 gtk_tree_model_get_iter(store, iter, tpath);
1270 gtk_tree_path_free(tpath);
1275 static gboolean tree_model_get_iter_last(GtkTreeModel *store, GtkTreeIter *iter)
1277 if (!gtk_tree_model_get_iter_first(store, iter))
1282 GtkTreeIter next = *iter;
1284 if (gtk_tree_model_iter_next(store, &next))
1293 void vflist_select_invert(ViewFile *vf)
1296 GtkTreeSelection *selection;
1297 GtkTreeModel *store;
1300 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
1301 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1303 /* Backward iteration prevents scrolling to the end of the list,
1304 * it scrolls to the first selected row instead. */
1305 valid = tree_model_get_iter_last(store, &iter);
1309 gint selected = gtk_tree_selection_iter_is_selected(selection, &iter);
1312 gtk_tree_selection_unselect_iter(selection, &iter);
1314 gtk_tree_selection_select_iter(selection, &iter);
1316 valid = tree_model_iter_prev(store, &iter);
1320 void vflist_select_by_fd(ViewFile *vf, FileData *fd)
1324 if (vflist_find_row(vf, fd, &iter) < 0) return;
1326 tree_view_row_make_visible(GTK_TREE_VIEW(vf->listview), &iter, TRUE);
1328 if (!vflist_row_is_selected(vf, fd))
1330 GtkTreeSelection *selection;
1331 GtkTreeModel *store;
1334 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1335 gtk_tree_selection_unselect_all(selection);
1336 gtk_tree_selection_select_iter(selection, &iter);
1337 vflist_move_cursor(vf, &iter);
1339 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
1340 tpath = gtk_tree_model_get_path(store, &iter);
1341 gtk_tree_view_set_cursor(GTK_TREE_VIEW(vf->listview), tpath, NULL, FALSE);
1342 gtk_tree_path_free(tpath);
1346 void vflist_mark_to_selection(ViewFile *vf, gint mark, MarkToSelectionMode mode)
1348 GtkTreeModel *store;
1350 GtkTreeSelection *selection;
1354 g_assert(mark >= 1 && mark <= FILEDATA_MARKS_SIZE);
1356 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
1357 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1359 valid = gtk_tree_model_get_iter_first(store, &iter);
1363 gboolean mark_val, selected;
1364 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, FILE_COLUMN_POINTER, &fd, -1);
1366 mark_val = fd->marks[n];
1367 selected = gtk_tree_selection_iter_is_selected(selection, &iter);
1371 case MTS_MODE_SET: selected = mark_val;
1373 case MTS_MODE_OR: selected = mark_val | selected;
1375 case MTS_MODE_AND: selected = mark_val & selected;
1377 case MTS_MODE_MINUS: selected = !mark_val & selected;
1382 gtk_tree_selection_select_iter(selection, &iter);
1384 gtk_tree_selection_unselect_iter(selection, &iter);
1386 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
1390 void vflist_selection_to_mark(ViewFile *vf, gint mark, SelectionToMarkMode mode)
1392 GtkTreeModel *store;
1393 GtkTreeSelection *selection;
1398 g_assert(mark >= 1 && mark <= FILEDATA_MARKS_SIZE);
1400 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1401 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1405 GtkTreePath *tpath = work->data;
1409 gtk_tree_model_get_iter(store, &iter, tpath);
1410 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
1414 case STM_MODE_SET: fd->marks[n] = 1;
1416 case STM_MODE_RESET: fd->marks[n] = 0;
1418 case STM_MODE_TOGGLE: fd->marks[n] = !fd->marks[n];
1422 gtk_tree_store_set(GTK_TREE_STORE(store), &iter, FILE_COLUMN_MARKS + n, fd->marks[n], -1);
1426 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1431 *-----------------------------------------------------------------------------
1433 *-----------------------------------------------------------------------------
1436 static void vflist_listview_set_height(GtkWidget *listview, gint thumb)
1438 GtkTreeViewColumn *column;
1439 GtkCellRenderer *cell;
1442 column = gtk_tree_view_get_column(GTK_TREE_VIEW(listview), FILE_COLUMN_THUMB - 1);
1443 if (!column) return;
1445 gtk_tree_view_column_set_fixed_width(column, ((thumb) ? options->thumbnails.max_width : 4) + 10);
1447 list = gtk_tree_view_column_get_cell_renderers(column);
1452 g_object_set(G_OBJECT(cell), "height", (thumb) ? options->thumbnails.max_height : -1, NULL);
1453 gtk_tree_view_columns_autosize(GTK_TREE_VIEW(listview));
1456 static void vflist_populate_view(ViewFile *vf)
1458 GtkTreeStore *store;
1462 GtkTreeRowReference *visible_row = NULL;
1466 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
1467 thumbs = VFLIST_INFO(vf, thumbs_enabled);
1469 vflist_thumb_stop(vf);
1473 gtk_tree_store_clear(store);
1478 if (GTK_WIDGET_REALIZED(vf->listview) &&
1479 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(vf->listview), 0, 0, &tpath, NULL, NULL, NULL))
1481 visible_row = gtk_tree_row_reference_new(GTK_TREE_MODEL(store), tpath);
1482 gtk_tree_path_free(tpath);
1485 vflist_listview_set_height(vf->listview, thumbs);
1487 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
1493 FileData *fd = work->data;
1498 FileData *old_fd = NULL;
1502 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, FILE_COLUMN_POINTER, &old_fd, -1);
1510 match = filelist_sort_compare_filedata_full(fd, old_fd, vf->sort_method, vf->sort_ascend);
1512 match = -1; /* probably should not happen*/
1527 gtk_tree_store_insert_before(store, &new, NULL, &iter);
1531 gtk_tree_store_append(store, &new, NULL);
1533 vflist_setup_iter_with_sidecars(vf, store, &new, fd);
1539 valid = gtk_tree_store_remove(store, &iter);
1543 vflist_setup_iter_with_sidecars(vf, store, &iter, fd);
1545 if (valid) valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
1555 valid = gtk_tree_store_remove(store, &iter);
1560 if (gtk_tree_row_reference_valid(visible_row))
1562 tpath = gtk_tree_row_reference_get_path(visible_row);
1563 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(vf->listview), tpath, NULL, TRUE, 0.0, 0.0);
1564 gtk_tree_path_free(tpath);
1566 gtk_tree_row_reference_free(visible_row);
1570 vflist_thumb_update(vf);
1573 gint vflist_refresh(ViewFile *vf)
1578 old_list = vf->list;
1583 ret = filelist_read(vf->path, &vf->list, NULL);
1586 vf->list = filelist_sort(vf->list, vf->sort_method, vf->sort_ascend);
1587 vflist_populate_view(vf);
1589 filelist_free(old_list);
1594 /* this overrides the low default of a GtkCellRenderer from 100 to CELL_HEIGHT_OVERRIDE, something sane for our purposes */
1596 #define CELL_HEIGHT_OVERRIDE 512
1598 static void cell_renderer_height_override(GtkCellRenderer *renderer)
1602 spec = g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(renderer)), "height");
1603 if (spec && G_IS_PARAM_SPEC_INT(spec))
1605 GParamSpecInt *spec_int;
1607 spec_int = G_PARAM_SPEC_INT(spec);
1608 if (spec_int->maximum < CELL_HEIGHT_OVERRIDE) spec_int->maximum = CELL_HEIGHT_OVERRIDE;
1612 static GdkColor *vflist_listview_color_shifted(GtkWidget *widget)
1614 static GdkColor color;
1615 static GtkWidget *done = NULL;
1621 style = gtk_widget_get_style(widget);
1622 memcpy(&color, &style->base[GTK_STATE_NORMAL], sizeof(color));
1623 shift_color(&color, -1, 0);
1630 static void vflist_listview_color_cb(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1631 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1633 ViewFile *vf = data;
1636 gtk_tree_model_get(tree_model, iter, FILE_COLUMN_COLOR, &set, -1);
1637 g_object_set(G_OBJECT(cell),
1638 "cell-background-gdk", vflist_listview_color_shifted(vf->listview),
1639 "cell-background-set", set, NULL);
1642 static void vflist_listview_add_column(ViewFile *vf, gint n, const gchar *title, gint image, gint right_justify, gint expand)
1644 GtkTreeViewColumn *column;
1645 GtkCellRenderer *renderer;
1647 column = gtk_tree_view_column_new();
1648 gtk_tree_view_column_set_title(column, title);
1649 gtk_tree_view_column_set_min_width(column, 4);
1653 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_GROW_ONLY);
1654 renderer = gtk_cell_renderer_text_new();
1657 g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
1659 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1660 gtk_tree_view_column_add_attribute(column, renderer, "text", n);
1662 gtk_tree_view_column_set_expand(column, TRUE);
1666 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
1667 renderer = gtk_cell_renderer_pixbuf_new();
1668 cell_renderer_height_override(renderer);
1669 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1670 gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", n);
1673 gtk_tree_view_column_set_cell_data_func(column, renderer, vflist_listview_color_cb, vf, NULL);
1674 g_object_set_data(G_OBJECT(column), "column_store_idx", GUINT_TO_POINTER(n));
1675 g_object_set_data(G_OBJECT(renderer), "column_store_idx", GUINT_TO_POINTER(n));
1677 gtk_tree_view_append_column(GTK_TREE_VIEW(vf->listview), column);
1680 static void vflist_listview_mark_toggled(GtkCellRendererToggle *cell, gchar *path_str, GtkTreeStore *store)
1682 GtkTreePath *path = gtk_tree_path_new_from_string(path_str);
1688 if (!path || !gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, path))
1691 col_idx = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cell), "column_store_idx"));
1693 g_assert(col_idx >= FILE_COLUMN_MARKS && col_idx <= FILE_COLUMN_MARKS_LAST);
1695 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, FILE_COLUMN_POINTER, &fd, col_idx, &mark, -1);
1697 fd->marks[col_idx - FILE_COLUMN_MARKS] = mark;
1699 gtk_tree_store_set(store, &iter, col_idx, mark, -1);
1700 gtk_tree_path_free(path);
1703 static void vflist_listview_add_column_toggle(ViewFile *vf, gint n, const gchar *title)
1705 GtkTreeViewColumn *column;
1706 GtkCellRenderer *renderer;
1707 GtkTreeStore *store;
1710 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
1712 renderer = gtk_cell_renderer_toggle_new();
1713 column = gtk_tree_view_column_new_with_attributes(title, renderer, "active", n, NULL);
1715 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
1716 g_object_set_data(G_OBJECT(column), "column_store_idx", GUINT_TO_POINTER(n));
1717 g_object_set_data(G_OBJECT(renderer), "column_store_idx", GUINT_TO_POINTER(n));
1719 index = gtk_tree_view_append_column(GTK_TREE_VIEW(vf->listview), column);
1720 gtk_tree_view_column_set_fixed_width(column, 16);
1721 gtk_tree_view_column_set_visible(column, vf->marks_enabled);
1724 g_signal_connect(G_OBJECT(renderer), "toggled", G_CALLBACK(vflist_listview_mark_toggled), store);
1728 *-----------------------------------------------------------------------------
1730 *-----------------------------------------------------------------------------
1733 gint vflist_set_path(ViewFile *vf, const gchar *path)
1735 GtkTreeStore *store;
1737 if (!path) return FALSE;
1738 if (vf->path && strcmp(path, vf->path) == 0) return TRUE;
1741 vf->path = g_strdup(path);
1743 /* force complete reload */
1744 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
1745 gtk_tree_store_clear(store);
1747 filelist_free(vf->list);
1750 return vf_refresh(vf);
1753 void vflist_destroy_cb(GtkWidget *widget, gpointer data)
1755 ViewFile *vf = data;
1757 vflist_select_idle_cancel(vf);
1758 vflist_thumb_stop(vf);
1760 filelist_free(vf->list);
1763 ViewFile *vflist_new(ViewFile *vf, const gchar *path)
1765 GtkTreeStore *store;
1766 GtkTreeSelection *selection;
1768 GType flist_types[FILE_COLUMN_COUNT];
1771 vf->info = g_new0(ViewFileInfoList, 1);
1773 VFLIST_INFO(vf, click_fd) = NULL;
1774 VFLIST_INFO(vf, select_fd) = NULL;
1775 VFLIST_INFO(vf, thumbs_enabled) = FALSE;
1777 VFLIST_INFO(vf, select_idle_id) = -1;
1779 flist_types[FILE_COLUMN_POINTER] = G_TYPE_POINTER;
1780 flist_types[FILE_COLUMN_THUMB] = GDK_TYPE_PIXBUF;
1781 flist_types[FILE_COLUMN_NAME] = G_TYPE_STRING;
1782 flist_types[FILE_COLUMN_SIDECARS] = G_TYPE_STRING;
1783 flist_types[FILE_COLUMN_SIZE] = G_TYPE_STRING;
1784 flist_types[FILE_COLUMN_DATE] = G_TYPE_STRING;
1785 flist_types[FILE_COLUMN_COLOR] = G_TYPE_BOOLEAN;
1786 for (i = FILE_COLUMN_MARKS; i < FILE_COLUMN_MARKS + FILEDATA_MARKS_SIZE; i++)
1787 flist_types[i] = G_TYPE_BOOLEAN;
1789 store = gtk_tree_store_newv(FILE_COLUMN_COUNT, flist_types);
1791 vf->listview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
1792 g_object_unref(store);
1794 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1795 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
1796 gtk_tree_selection_set_select_function(selection, vflist_select_cb, vf, NULL);
1798 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(vf->listview), FALSE);
1799 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(vf->listview), FALSE);
1801 vflist_listview_add_column(vf, FILE_COLUMN_THUMB, "", TRUE, FALSE, FALSE);
1803 for (i = 0; i < FILEDATA_MARKS_SIZE; i++)
1804 vflist_listview_add_column_toggle(vf, i + FILE_COLUMN_MARKS, "");
1806 vflist_listview_add_column(vf, FILE_COLUMN_NAME, _("Name"), FALSE, FALSE, FALSE);
1807 vflist_listview_add_column(vf, FILE_COLUMN_SIDECARS, _("SC"), FALSE, FALSE, FALSE);
1809 vflist_listview_add_column(vf, FILE_COLUMN_SIZE, _("Size"), FALSE, TRUE, FALSE);
1810 vflist_listview_add_column(vf, FILE_COLUMN_DATE, _("Date"), FALSE, TRUE, FALSE);
1815 void vflist_thumb_set(ViewFile *vf, gint enable)
1817 if (VFLIST_INFO(vf, thumbs_enabled) == enable) return;
1819 VFLIST_INFO(vf, thumbs_enabled) = enable;
1820 if (vf->layout) vf_refresh(vf);
1823 void vflist_marks_set(ViewFile *vf, gint enable)
1825 GList *columns, *work;
1827 if (vf->marks_enabled == enable) return;
1829 vf->marks_enabled = enable;
1831 columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(vf->listview));
1836 GtkTreeViewColumn *column = work->data;
1837 gint col_idx = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(column), "column_store_idx"));
1840 if (col_idx <= FILE_COLUMN_MARKS_LAST && col_idx >= FILE_COLUMN_MARKS)
1841 gtk_tree_view_column_set_visible(column, enable);
1844 g_list_free(columns);
1849 *-----------------------------------------------------------------------------
1850 * maintenance (for rename, move, remove)
1851 *-----------------------------------------------------------------------------
1854 static gint vflist_maint_find_closest(ViewFile *vf, gint row, gint count, GList *ignore_list)
1864 gint f = vf_index_by_path(vf, work->data);
1865 if (f >= 0) list = g_list_prepend(list, GINT_TO_POINTER(f));
1875 gpointer p = work->data;
1877 if (row == GPOINTER_TO_INT(p))
1882 if (rev == GPOINTER_TO_INT(p))
1887 if (!c) list = g_list_remove(list, p);
1895 if (row > count - 1)
1908 gint vflist_maint_renamed(ViewFile *vf, FileData *fd)
1914 if (g_list_index(vf->list, fd) < 0) return FALSE;
1916 source_base = remove_level_from_path(fd->change->source);
1917 dest_base = remove_level_from_path(fd->change->dest);
1920 if (strcmp(source_base, dest_base) == 0)
1922 GtkTreeStore *store;
1924 GtkTreeIter position;
1928 old_row = g_list_index(vf->list, fd);
1930 vf->list = g_list_remove(vf->list, fd);
1932 vf->list = filelist_insert_sort(vf->list, fd, vf->sort_method, vf->sort_ascend);
1933 n = g_list_index(vf->list, fd);
1935 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
1936 if (vflist_find_row(vf, fd, &iter) >= 0 &&
1937 gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &position, NULL, n))
1941 gtk_tree_store_move_before(store, &iter, &position);
1945 gtk_tree_store_move_after(store, &iter, &position);
1948 gtk_tree_store_set(store, &iter, FILE_COLUMN_NAME, fd->name, -1);
1954 ret = vflist_maint_removed(vf, fd, NULL);
1957 g_free(source_base);
1963 gint vflist_maint_removed(ViewFile *vf, FileData *fd, GList *ignore_list)
1970 row = g_list_index(vf->list, fd);
1971 if (row < 0) return FALSE;
1973 if (vflist_index_is_selected(vf, row) &&
1974 layout_image_get_collection(vf->layout, NULL) == NULL)
1978 n = vf_count(vf, NULL);
1981 new_row = vflist_maint_find_closest(vf, row, n, ignore_list);
1982 DEBUG_1("row = %d, closest is %d", row, new_row);
1998 fd = vf_index_get_data(vf, new_row);
1999 if (vflist_find_row(vf, fd, &iter) >= 0)
2001 GtkTreeSelection *selection;
2003 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
2004 gtk_tree_selection_select_iter(selection, &iter);
2005 vflist_move_cursor(vf, &iter);
2010 fd = vf_index_get_data(vf, row);
2011 if (vflist_find_row(vf, fd, &iter) >= 0)
2013 GtkTreeStore *store;
2014 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
2015 gtk_tree_store_remove(store, &iter);
2017 list = g_list_nth(vf->list, row);
2020 /* thumbnail loader check */
2021 if (fd == vf->thumbs_filedata) vf->thumbs_filedata = NULL;
2022 if (vf->thumbs_count > 0) vf->thumbs_count--;
2024 vf->list = g_list_remove(vf->list, fd);
2025 file_data_unref(fd);
2032 gint vflist_maint_moved(ViewFile *vf, FileData *fd, GList *ignore_list)
2037 if (!fd->change->source || !vf->path) return FALSE;
2039 buf = remove_level_from_path(fd->change->source);
2041 if (strcmp(buf, vf->path) == 0)
2043 ret = vflist_maint_removed(vf, fd, ignore_list);