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)
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_VERSION, fd->version,
721 FILE_COLUMN_THUMB, (VFLIST_INFO(vf, thumbs_enabled)) ? fd->pixbuf : NULL,
722 FILE_COLUMN_NAME, fd->name,
723 FILE_COLUMN_SIDECARS, sidecars,
724 FILE_COLUMN_SIZE, size,
725 FILE_COLUMN_DATE, text_from_time(fd->date),
726 FILE_COLUMN_COLOR, FALSE, -1);
727 for (i = 0; i < FILEDATA_MARKS_SIZE; i++)
728 gtk_tree_store_set(store, iter, FILE_COLUMN_MARKS + i, fd->marks[i], -1);
735 static void vflist_setup_iter_recursive(ViewFile *vf, GtkTreeStore *store, GtkTreeIter *parent_iter, GList *list, GList *selected)
741 valid = gtk_tree_model_iter_children(GTK_TREE_MODEL(store), &iter, parent_iter);
747 FileData *fd = work->data;
752 FileData *old_fd = NULL;
753 gint old_version = 0;
757 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
758 FILE_COLUMN_POINTER, &old_fd,
759 FILE_COLUMN_VERSION, &old_version,
769 match = filelist_sort_compare_filedata_full(fd, old_fd, SORT_NAME, TRUE); /* always sort sidecars by name */
771 match = filelist_sort_compare_filedata_full(fd, old_fd, vf->sort_method, vf->sort_ascend);
773 if (match == 0) g_warning("multiple fd for the same path");
788 gtk_tree_store_insert_before(store, &new, parent_iter, &iter);
792 gtk_tree_store_append(store, &new, parent_iter);
795 vflist_setup_iter(vf, store, &new, fd);
796 vflist_setup_iter_recursive(vf, store, &new, fd->sidecar_files, selected);
798 if (g_list_find(selected, fd))
800 /* renamed files - the same fd appears at different position - select it again*/
801 GtkTreeSelection *selection;
802 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
803 gtk_tree_selection_select_iter(selection, &new);
810 valid = gtk_tree_store_remove(store, &iter);
814 if (fd->version != old_version)
816 vflist_setup_iter(vf, store, &iter, fd);
817 vflist_setup_iter_recursive(vf, store, &iter, fd->sidecar_files, selected);
820 if (valid) valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
830 valid = gtk_tree_store_remove(store, &iter);
834 void vflist_sort_set(ViewFile *vf, SortType type, gint ascend)
837 GHashTable *fd_idx_hash = g_hash_table_new(NULL, NULL);
842 if (vf->sort_method == type && vf->sort_ascend == ascend) return;
843 if (!vf->list) return;
849 FileData *fd = work->data;
850 g_hash_table_insert(fd_idx_hash, fd, GINT_TO_POINTER(i));
855 vf->sort_method = type;
856 vf->sort_ascend = ascend;
858 vf->list = filelist_sort(vf->list, vf->sort_method, vf->sort_ascend);
860 new_order = g_malloc(i * sizeof(gint));
866 FileData *fd = work->data;
867 new_order[i] = GPOINTER_TO_INT(g_hash_table_lookup(fd_idx_hash, fd));
872 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
873 gtk_tree_store_reorder(store, NULL, new_order);
876 g_hash_table_destroy(fd_idx_hash);
880 *-----------------------------------------------------------------------------
882 *-----------------------------------------------------------------------------
885 static gint vflist_thumb_next(ViewFile *vf);
887 static void vflist_thumb_status(ViewFile *vf, gdouble val, const gchar *text)
889 if (vf->func_thumb_status)
891 vf->func_thumb_status(vf, val, text, vf->data_thumb_status);
895 static void vflist_thumb_cleanup(ViewFile *vf)
897 vflist_thumb_status(vf, 0.0, NULL);
899 vf->thumbs_count = 0;
900 vf->thumbs_running = FALSE;
902 thumb_loader_free(vf->thumbs_loader);
903 vf->thumbs_loader = NULL;
905 vf->thumbs_filedata = NULL;
908 static void vflist_thumb_stop(ViewFile *vf)
910 if (vf->thumbs_running) vflist_thumb_cleanup(vf);
913 static void vflist_thumb_do(ViewFile *vf, ThumbLoader *tl, FileData *fd)
918 if (!fd || vflist_find_row(vf, fd, &iter) < 0) return;
920 if (fd->pixbuf) g_object_unref(fd->pixbuf);
921 fd->pixbuf = thumb_loader_get_pixbuf(tl, TRUE);
923 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
924 gtk_tree_store_set(store, &iter, FILE_COLUMN_THUMB, fd->pixbuf, -1);
926 vflist_thumb_status(vf, (gdouble)(vf->thumbs_count) / vflist_sidecar_list_count(vf->list), _("Loading thumbs..."));
929 static void vflist_thumb_error_cb(ThumbLoader *tl, gpointer data)
933 if (vf->thumbs_filedata && vf->thumbs_loader == tl)
935 vflist_thumb_do(vf, tl, vf->thumbs_filedata);
938 while (vflist_thumb_next(vf));
941 static void vflist_thumb_done_cb(ThumbLoader *tl, gpointer data)
945 if (vf->thumbs_filedata && vf->thumbs_loader == tl)
947 vflist_thumb_do(vf, tl, vf->thumbs_filedata);
950 while (vflist_thumb_next(vf));
953 static gint vflist_thumb_next(ViewFile *vf)
958 /* first check the visible files */
960 if (GTK_WIDGET_REALIZED(vf->listview) &&
961 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(vf->listview), 0, 0, &tpath, NULL, NULL, NULL))
967 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
968 gtk_tree_model_get_iter(store, &iter, tpath);
969 gtk_tree_path_free(tpath);
971 while (!fd && valid && tree_view_row_get_visibility(GTK_TREE_VIEW(vf->listview), &iter, FALSE) == 0)
973 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
974 if (fd->pixbuf) fd = NULL;
976 valid = gtk_tree_model_iter_next(store, &iter);
980 /* then find first undone */
984 GList *work = vf->list;
987 FileData *fd_p = work->data;
992 GList *work2 = fd_p->sidecar_files;
997 if (!fd_p->pixbuf) fd = fd_p;
1008 vflist_thumb_cleanup(vf);
1014 vf->thumbs_filedata = fd;
1016 thumb_loader_free(vf->thumbs_loader);
1018 vf->thumbs_loader = thumb_loader_new(options->thumbnails.max_width, options->thumbnails.max_height);
1019 thumb_loader_set_callbacks(vf->thumbs_loader,
1020 vflist_thumb_done_cb,
1021 vflist_thumb_error_cb,
1025 if (!thumb_loader_start(vf->thumbs_loader, fd->path))
1027 /* set icon to unknown, continue */
1028 DEBUG_1("thumb loader start failed %s", vf->thumbs_loader->path);
1029 vflist_thumb_do(vf, vf->thumbs_loader, fd);
1037 static void vflist_thumb_update(ViewFile *vf)
1039 vflist_thumb_stop(vf);
1040 if (!VFLIST_INFO(vf, thumbs_enabled)) return;
1042 vflist_thumb_status(vf, 0.0, _("Loading thumbs..."));
1043 vf->thumbs_running = TRUE;
1045 while (vflist_thumb_next(vf));
1049 *-----------------------------------------------------------------------------
1051 *-----------------------------------------------------------------------------
1054 FileData *vflist_index_get_data(ViewFile *vf, gint row)
1056 return g_list_nth_data(vf->list, row);
1059 gint vflist_index_by_path(ViewFile *vf, const gchar *path)
1064 if (!path) return -1;
1069 FileData *fd = work->data;
1070 if (strcmp(path, fd->path) == 0) return p;
1079 guint vflist_count(ViewFile *vf, gint64 *bytes)
1089 FileData *fd = work->data;
1097 return g_list_length(vf->list);
1100 GList *vflist_get_list(ViewFile *vf)
1108 FileData *fd = work->data;
1111 list = g_list_prepend(list, file_data_ref(fd));
1114 return g_list_reverse(list);
1118 *-----------------------------------------------------------------------------
1120 *-----------------------------------------------------------------------------
1123 static gint vflist_row_is_selected(ViewFile *vf, FileData *fd)
1125 GtkTreeModel *store;
1126 GtkTreeSelection *selection;
1131 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1132 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1134 while (!found && work)
1136 GtkTreePath *tpath = work->data;
1140 gtk_tree_model_get_iter(store, &iter, tpath);
1141 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd_n, -1);
1142 if (fd_n == fd) found = TRUE;
1145 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1151 gint vflist_index_is_selected(ViewFile *vf, gint row)
1155 fd = vf_index_get_data(vf, row);
1156 return vflist_row_is_selected(vf, fd);
1159 guint vflist_selection_count(ViewFile *vf, gint64 *bytes)
1161 GtkTreeModel *store;
1162 GtkTreeSelection *selection;
1166 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1167 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1177 GtkTreePath *tpath = work->data;
1181 gtk_tree_model_get_iter(store, &iter, tpath);
1182 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
1191 count = g_list_length(slist);
1192 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1198 GList *vflist_selection_get_list(ViewFile *vf)
1200 GtkTreeModel *store;
1201 GtkTreeSelection *selection;
1206 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1207 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1211 GtkTreePath *tpath = work->data;
1215 gtk_tree_model_get_iter(store, &iter, tpath);
1216 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
1218 list = g_list_prepend(list, file_data_ref(fd));
1222 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1225 return g_list_reverse(list);
1228 GList *vflist_selection_get_list_by_index(ViewFile *vf)
1230 GtkTreeModel *store;
1231 GtkTreeSelection *selection;
1236 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1237 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1241 GtkTreePath *tpath = work->data;
1245 gtk_tree_model_get_iter(store, &iter, tpath);
1246 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
1248 list = g_list_prepend(list, GINT_TO_POINTER(g_list_index(vf->list, fd)));
1252 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1255 return g_list_reverse(list);
1258 void vflist_select_all(ViewFile *vf)
1260 GtkTreeSelection *selection;
1262 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1263 gtk_tree_selection_select_all(selection);
1265 VFLIST_INFO(vf, select_fd) = NULL;
1268 void vflist_select_none(ViewFile *vf)
1270 GtkTreeSelection *selection;
1272 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1273 gtk_tree_selection_unselect_all(selection);
1276 static gboolean tree_model_iter_prev(GtkTreeModel *store, GtkTreeIter *iter)
1281 tpath = gtk_tree_model_get_path(store, iter);
1282 result = gtk_tree_path_prev(tpath);
1284 gtk_tree_model_get_iter(store, iter, tpath);
1286 gtk_tree_path_free(tpath);
1291 static gboolean tree_model_get_iter_last(GtkTreeModel *store, GtkTreeIter *iter)
1293 if (!gtk_tree_model_get_iter_first(store, iter))
1298 GtkTreeIter next = *iter;
1300 if (gtk_tree_model_iter_next(store, &next))
1309 void vflist_select_invert(ViewFile *vf)
1312 GtkTreeSelection *selection;
1313 GtkTreeModel *store;
1316 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
1317 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1319 /* Backward iteration prevents scrolling to the end of the list,
1320 * it scrolls to the first selected row instead. */
1321 valid = tree_model_get_iter_last(store, &iter);
1325 gint selected = gtk_tree_selection_iter_is_selected(selection, &iter);
1328 gtk_tree_selection_unselect_iter(selection, &iter);
1330 gtk_tree_selection_select_iter(selection, &iter);
1332 valid = tree_model_iter_prev(store, &iter);
1336 void vflist_select_by_fd(ViewFile *vf, FileData *fd)
1340 if (vflist_find_row(vf, fd, &iter) < 0) return;
1342 tree_view_row_make_visible(GTK_TREE_VIEW(vf->listview), &iter, TRUE);
1344 if (!vflist_row_is_selected(vf, fd))
1346 GtkTreeSelection *selection;
1347 GtkTreeModel *store;
1350 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1351 gtk_tree_selection_unselect_all(selection);
1352 gtk_tree_selection_select_iter(selection, &iter);
1353 vflist_move_cursor(vf, &iter);
1355 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
1356 tpath = gtk_tree_model_get_path(store, &iter);
1357 gtk_tree_view_set_cursor(GTK_TREE_VIEW(vf->listview), tpath, NULL, FALSE);
1358 gtk_tree_path_free(tpath);
1362 static void vflist_select_closest(ViewFile *vf, FileData *sel_fd)
1366 if (sel_fd->parent) sel_fd = sel_fd->parent;
1372 FileData *fd = work->data;
1376 match = filelist_sort_compare_filedata_full(fd, sel_fd, vf->sort_method, vf->sort_ascend);
1380 vflist_select_by_fd(vf, fd);
1387 void vflist_mark_to_selection(ViewFile *vf, gint mark, MarkToSelectionMode mode)
1389 GtkTreeModel *store;
1391 GtkTreeSelection *selection;
1395 g_assert(mark >= 1 && mark <= FILEDATA_MARKS_SIZE);
1397 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
1398 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1400 valid = gtk_tree_model_get_iter_first(store, &iter);
1404 gboolean mark_val, selected;
1405 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, FILE_COLUMN_POINTER, &fd, -1);
1407 mark_val = fd->marks[n];
1408 selected = gtk_tree_selection_iter_is_selected(selection, &iter);
1412 case MTS_MODE_SET: selected = mark_val;
1414 case MTS_MODE_OR: selected = mark_val | selected;
1416 case MTS_MODE_AND: selected = mark_val & selected;
1418 case MTS_MODE_MINUS: selected = !mark_val & selected;
1423 gtk_tree_selection_select_iter(selection, &iter);
1425 gtk_tree_selection_unselect_iter(selection, &iter);
1427 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
1431 void vflist_selection_to_mark(ViewFile *vf, gint mark, SelectionToMarkMode mode)
1433 GtkTreeModel *store;
1434 GtkTreeSelection *selection;
1439 g_assert(mark >= 1 && mark <= FILEDATA_MARKS_SIZE);
1441 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1442 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1446 GtkTreePath *tpath = work->data;
1450 gtk_tree_model_get_iter(store, &iter, tpath);
1451 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
1455 case STM_MODE_SET: fd->marks[n] = 1;
1457 case STM_MODE_RESET: fd->marks[n] = 0;
1459 case STM_MODE_TOGGLE: fd->marks[n] = !fd->marks[n];
1463 file_data_increment_version(fd);
1465 gtk_tree_store_set(GTK_TREE_STORE(store), &iter, FILE_COLUMN_MARKS + n, fd->marks[n], -1);
1469 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1474 *-----------------------------------------------------------------------------
1476 *-----------------------------------------------------------------------------
1479 static void vflist_listview_set_height(GtkWidget *listview, gint thumb)
1481 GtkTreeViewColumn *column;
1482 GtkCellRenderer *cell;
1485 column = gtk_tree_view_get_column(GTK_TREE_VIEW(listview), 0); /* first column is thumbnail */
1486 if (!column) return;
1488 gtk_tree_view_column_set_fixed_width(column, ((thumb) ? options->thumbnails.max_width : 4) + 10);
1490 list = gtk_tree_view_column_get_cell_renderers(column);
1495 g_object_set(G_OBJECT(cell), "height", (thumb) ? options->thumbnails.max_height : -1, NULL);
1496 gtk_tree_view_columns_autosize(GTK_TREE_VIEW(listview));
1499 static void vflist_populate_view(ViewFile *vf)
1501 GtkTreeStore *store;
1503 GtkTreeRowReference *visible_row = NULL;
1507 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
1508 thumbs = VFLIST_INFO(vf, thumbs_enabled);
1510 vflist_thumb_stop(vf);
1514 gtk_tree_store_clear(store);
1519 if (GTK_WIDGET_REALIZED(vf->listview) &&
1520 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(vf->listview), 0, 0, &tpath, NULL, NULL, NULL))
1522 visible_row = gtk_tree_row_reference_new(GTK_TREE_MODEL(store), tpath);
1523 gtk_tree_path_free(tpath);
1526 vflist_listview_set_height(vf->listview, thumbs);
1528 selected = vflist_selection_get_list(vf);
1530 vflist_setup_iter_recursive(vf, store, NULL, vf->list, selected);
1532 if (selected && vflist_selection_count(vf, NULL) == 0)
1534 /* all selected files disappeared */
1535 vflist_select_closest(vf, selected->data);
1538 filelist_free(selected);
1542 if (gtk_tree_row_reference_valid(visible_row))
1544 tpath = gtk_tree_row_reference_get_path(visible_row);
1545 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(vf->listview), tpath, NULL, TRUE, 0.0, 0.0);
1546 gtk_tree_path_free(tpath);
1548 gtk_tree_row_reference_free(visible_row);
1552 vflist_thumb_update(vf);
1555 gint vflist_refresh(ViewFile *vf)
1560 old_list = vf->list;
1563 DEBUG_1("%s vflist_refresh: read dir", get_exec_time());
1566 ret = filelist_read(vf->path, &vf->list, NULL);
1568 DEBUG_1("%s vflist_refresh: sort", get_exec_time());
1570 vf->list = filelist_sort(vf->list, vf->sort_method, vf->sort_ascend);
1572 DEBUG_1("%s vflist_refresh: populate view", get_exec_time());
1574 vflist_populate_view(vf);
1576 filelist_free(old_list);
1577 DEBUG_1("%s vflist_refresh: done", get_exec_time());
1582 /* this overrides the low default of a GtkCellRenderer from 100 to CELL_HEIGHT_OVERRIDE, something sane for our purposes */
1584 #define CELL_HEIGHT_OVERRIDE 512
1586 static void cell_renderer_height_override(GtkCellRenderer *renderer)
1590 spec = g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(renderer)), "height");
1591 if (spec && G_IS_PARAM_SPEC_INT(spec))
1593 GParamSpecInt *spec_int;
1595 spec_int = G_PARAM_SPEC_INT(spec);
1596 if (spec_int->maximum < CELL_HEIGHT_OVERRIDE) spec_int->maximum = CELL_HEIGHT_OVERRIDE;
1600 static GdkColor *vflist_listview_color_shifted(GtkWidget *widget)
1602 static GdkColor color;
1603 static GtkWidget *done = NULL;
1609 style = gtk_widget_get_style(widget);
1610 memcpy(&color, &style->base[GTK_STATE_NORMAL], sizeof(color));
1611 shift_color(&color, -1, 0);
1618 static void vflist_listview_color_cb(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1619 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1621 ViewFile *vf = data;
1624 gtk_tree_model_get(tree_model, iter, FILE_COLUMN_COLOR, &set, -1);
1625 g_object_set(G_OBJECT(cell),
1626 "cell-background-gdk", vflist_listview_color_shifted(vf->listview),
1627 "cell-background-set", set, NULL);
1630 static void vflist_listview_add_column(ViewFile *vf, gint n, const gchar *title, gint image, gint right_justify, gint expand)
1632 GtkTreeViewColumn *column;
1633 GtkCellRenderer *renderer;
1635 column = gtk_tree_view_column_new();
1636 gtk_tree_view_column_set_title(column, title);
1637 gtk_tree_view_column_set_min_width(column, 4);
1641 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_GROW_ONLY);
1642 renderer = gtk_cell_renderer_text_new();
1645 g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
1647 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1648 gtk_tree_view_column_add_attribute(column, renderer, "text", n);
1650 gtk_tree_view_column_set_expand(column, TRUE);
1654 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
1655 renderer = gtk_cell_renderer_pixbuf_new();
1656 cell_renderer_height_override(renderer);
1657 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1658 gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", n);
1661 gtk_tree_view_column_set_cell_data_func(column, renderer, vflist_listview_color_cb, vf, NULL);
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 gtk_tree_view_append_column(GTK_TREE_VIEW(vf->listview), column);
1668 static void vflist_listview_mark_toggled(GtkCellRendererToggle *cell, gchar *path_str, GtkTreeStore *store)
1670 GtkTreePath *path = gtk_tree_path_new_from_string(path_str);
1676 if (!path || !gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, path))
1679 col_idx = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cell), "column_store_idx"));
1681 g_assert(col_idx >= FILE_COLUMN_MARKS && col_idx <= FILE_COLUMN_MARKS_LAST);
1683 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, FILE_COLUMN_POINTER, &fd, col_idx, &mark, -1);
1685 fd->marks[col_idx - FILE_COLUMN_MARKS] = mark;
1686 file_data_increment_version(fd);
1688 gtk_tree_store_set(store, &iter, col_idx, mark, -1);
1689 gtk_tree_path_free(path);
1692 static void vflist_listview_add_column_toggle(ViewFile *vf, gint n, const gchar *title)
1694 GtkTreeViewColumn *column;
1695 GtkCellRenderer *renderer;
1696 GtkTreeStore *store;
1699 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
1701 renderer = gtk_cell_renderer_toggle_new();
1702 column = gtk_tree_view_column_new_with_attributes(title, renderer, "active", n, NULL);
1704 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
1705 g_object_set_data(G_OBJECT(column), "column_store_idx", GUINT_TO_POINTER(n));
1706 g_object_set_data(G_OBJECT(renderer), "column_store_idx", GUINT_TO_POINTER(n));
1708 index = gtk_tree_view_append_column(GTK_TREE_VIEW(vf->listview), column);
1709 gtk_tree_view_column_set_fixed_width(column, 16);
1710 gtk_tree_view_column_set_visible(column, vf->marks_enabled);
1713 g_signal_connect(G_OBJECT(renderer), "toggled", G_CALLBACK(vflist_listview_mark_toggled), store);
1717 *-----------------------------------------------------------------------------
1719 *-----------------------------------------------------------------------------
1722 gint vflist_set_path(ViewFile *vf, const gchar *path)
1724 GtkTreeStore *store;
1726 if (!path) return FALSE;
1727 if (vf->path && strcmp(path, vf->path) == 0) return TRUE;
1730 vf->path = g_strdup(path);
1732 /* force complete reload */
1733 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
1734 gtk_tree_store_clear(store);
1736 filelist_free(vf->list);
1739 return vf_refresh(vf);
1742 void vflist_destroy_cb(GtkWidget *widget, gpointer data)
1744 ViewFile *vf = data;
1746 vflist_select_idle_cancel(vf);
1747 vflist_thumb_stop(vf);
1749 filelist_free(vf->list);
1752 ViewFile *vflist_new(ViewFile *vf, const gchar *path)
1754 GtkTreeStore *store;
1755 GtkTreeSelection *selection;
1757 GType flist_types[FILE_COLUMN_COUNT];
1760 vf->info = g_new0(ViewFileInfoList, 1);
1762 VFLIST_INFO(vf, click_fd) = NULL;
1763 VFLIST_INFO(vf, select_fd) = NULL;
1764 VFLIST_INFO(vf, thumbs_enabled) = FALSE;
1766 VFLIST_INFO(vf, select_idle_id) = -1;
1768 flist_types[FILE_COLUMN_POINTER] = G_TYPE_POINTER;
1769 flist_types[FILE_COLUMN_VERSION] = G_TYPE_INT;
1770 flist_types[FILE_COLUMN_THUMB] = GDK_TYPE_PIXBUF;
1771 flist_types[FILE_COLUMN_NAME] = G_TYPE_STRING;
1772 flist_types[FILE_COLUMN_SIDECARS] = G_TYPE_STRING;
1773 flist_types[FILE_COLUMN_SIZE] = G_TYPE_STRING;
1774 flist_types[FILE_COLUMN_DATE] = G_TYPE_STRING;
1775 flist_types[FILE_COLUMN_COLOR] = G_TYPE_BOOLEAN;
1776 for (i = FILE_COLUMN_MARKS; i < FILE_COLUMN_MARKS + FILEDATA_MARKS_SIZE; i++)
1777 flist_types[i] = G_TYPE_BOOLEAN;
1779 store = gtk_tree_store_newv(FILE_COLUMN_COUNT, flist_types);
1781 vf->listview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
1782 g_object_unref(store);
1784 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1785 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
1786 gtk_tree_selection_set_select_function(selection, vflist_select_cb, vf, NULL);
1788 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(vf->listview), FALSE);
1789 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(vf->listview), FALSE);
1791 vflist_listview_add_column(vf, FILE_COLUMN_THUMB, "", TRUE, FALSE, FALSE);
1793 for (i = 0; i < FILEDATA_MARKS_SIZE; i++)
1794 vflist_listview_add_column_toggle(vf, i + FILE_COLUMN_MARKS, "");
1796 vflist_listview_add_column(vf, FILE_COLUMN_NAME, _("Name"), FALSE, FALSE, FALSE);
1797 vflist_listview_add_column(vf, FILE_COLUMN_SIDECARS, _("SC"), FALSE, FALSE, FALSE);
1799 vflist_listview_add_column(vf, FILE_COLUMN_SIZE, _("Size"), FALSE, TRUE, FALSE);
1800 vflist_listview_add_column(vf, FILE_COLUMN_DATE, _("Date"), FALSE, TRUE, FALSE);
1805 void vflist_thumb_set(ViewFile *vf, gint enable)
1807 if (VFLIST_INFO(vf, thumbs_enabled) == enable) return;
1809 VFLIST_INFO(vf, thumbs_enabled) = enable;
1810 if (vf->layout) vf_refresh(vf);
1813 void vflist_marks_set(ViewFile *vf, gint enable)
1815 GList *columns, *work;
1817 if (vf->marks_enabled == enable) return;
1819 vf->marks_enabled = enable;
1821 columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(vf->listview));
1826 GtkTreeViewColumn *column = work->data;
1827 gint col_idx = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(column), "column_store_idx"));
1830 if (col_idx <= FILE_COLUMN_MARKS_LAST && col_idx >= FILE_COLUMN_MARKS)
1831 gtk_tree_view_column_set_visible(column, enable);
1834 g_list_free(columns);
1839 *-----------------------------------------------------------------------------
1840 * maintenance (for rename, move, remove)
1841 *-----------------------------------------------------------------------------
1844 static gint vflist_maint_find_closest(ViewFile *vf, gint row, gint count, GList *ignore_list)
1854 gint f = vf_index_by_path(vf, work->data);
1855 if (f >= 0) list = g_list_prepend(list, GINT_TO_POINTER(f));
1865 gpointer p = work->data;
1867 if (row == GPOINTER_TO_INT(p))
1872 if (rev == GPOINTER_TO_INT(p))
1877 if (!c) list = g_list_remove(list, p);
1885 if (row > count - 1)
1898 gint vflist_maint_renamed(ViewFile *vf, FileData *fd)
1904 DEBUG_1("%s vflist_maint_renamed: start", get_exec_time());
1906 if (g_list_index(vf->list, fd) < 0) return FALSE;
1908 source_base = remove_level_from_path(fd->change->source);
1909 dest_base = remove_level_from_path(fd->change->dest);
1912 if (strcmp(source_base, dest_base) == 0)
1914 GtkTreeStore *store;
1916 GtkTreeIter position;
1920 old_row = g_list_index(vf->list, fd);
1922 vf->list = g_list_remove(vf->list, fd);
1924 vf->list = filelist_insert_sort(vf->list, fd, vf->sort_method, vf->sort_ascend);
1925 n = g_list_index(vf->list, fd);
1927 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
1928 if (vflist_find_row(vf, fd, &iter) >= 0 &&
1929 gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &position, NULL, n))
1933 gtk_tree_store_move_before(store, &iter, &position);
1937 gtk_tree_store_move_after(store, &iter, &position);
1940 gtk_tree_store_set(store, &iter, FILE_COLUMN_NAME, fd->name, -1);
1946 ret = vflist_maint_removed(vf, fd, NULL);
1949 g_free(source_base);
1952 DEBUG_1("%s vflist_maint_renamed: done", get_exec_time());
1957 gint vflist_maint_removed(ViewFile *vf, FileData *fd, GList *ignore_list)
1964 DEBUG_1("%s vflist_maint_removed: start", get_exec_time());
1966 row = g_list_index(vf->list, fd);
1967 if (row < 0) return FALSE;
1969 if (vflist_index_is_selected(vf, row) &&
1970 layout_image_get_collection(vf->layout, NULL) == NULL)
1974 n = vf_count(vf, NULL);
1977 new_row = vflist_maint_find_closest(vf, row, n, ignore_list);
1978 DEBUG_1("row = %d, closest is %d", row, new_row);
1994 fd = vf_index_get_data(vf, new_row);
1995 if (vflist_find_row(vf, fd, &iter) >= 0)
1997 GtkTreeSelection *selection;
1999 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
2000 gtk_tree_selection_select_iter(selection, &iter);
2001 vflist_move_cursor(vf, &iter);
2006 fd = vf_index_get_data(vf, row);
2007 if (vflist_find_row(vf, fd, &iter) >= 0)
2009 GtkTreeStore *store;
2010 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
2011 gtk_tree_store_remove(store, &iter);
2013 list = g_list_nth(vf->list, row);
2016 /* thumbnail loader check */
2017 if (fd == vf->thumbs_filedata) vf->thumbs_filedata = NULL;
2018 if (vf->thumbs_count > 0) vf->thumbs_count--;
2020 vf->list = g_list_remove(vf->list, fd);
2021 file_data_unref(fd);
2025 DEBUG_1("%s vflist_maint_removed: done", get_exec_time());
2030 gint vflist_maint_moved(ViewFile *vf, FileData *fd, GList *ignore_list)
2035 if (!fd->change->source || !vf->path) return FALSE;
2037 buf = remove_level_from_path(fd->change->source);
2039 if (strcmp(buf, vf->path) == 0)
2041 ret = vflist_maint_removed(vf, fd, ignore_list);