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 if (!file_data_add_change_info(fd, FILEDATA_CHANGE_RENAME, old_path, new_path) || !rename_file_ext(fd))
409 gchar *text = g_strdup_printf(_("Unable to rename file:\n%s\nto:\n%s"), old, new);
410 file_util_warning_dialog(_("Error renaming file"), text, GTK_STOCK_DIALOG_ERROR, vf->listview);
422 static void vflist_menu_position_cb(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer data)
430 if (vflist_find_row(vf, VFLIST_INFO(vf, click_fd), &iter) < 0) return;
431 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
432 tpath = gtk_tree_model_get_path(store, &iter);
433 tree_view_get_cell_clamped(GTK_TREE_VIEW(vf->listview), tpath, FILE_COLUMN_NAME - 1, TRUE, x, y, &cw, &ch);
434 gtk_tree_path_free(tpath);
436 popup_menu_position_clamp(menu, x, y, 0);
439 gint vflist_press_key_cb(GtkWidget *widget, GdkEventKey *event, gpointer data)
444 if (event->keyval != GDK_Menu) return FALSE;
446 gtk_tree_view_get_cursor(GTK_TREE_VIEW(vf->listview), &tpath, NULL);
452 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
453 gtk_tree_model_get_iter(store, &iter, tpath);
454 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &VFLIST_INFO(vf, click_fd), -1);
455 gtk_tree_path_free(tpath);
459 VFLIST_INFO(vf, click_fd) = NULL;
462 vf->popup = vf_pop_menu(vf);
463 gtk_menu_popup(GTK_MENU(vf->popup), NULL, NULL, vflist_menu_position_cb, vf, 0, GDK_CURRENT_TIME);
468 gint vflist_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
474 GtkTreeViewColumn *column;
476 vf->clicked_mark = 0;
478 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), bevent->x, bevent->y,
479 &tpath, &column, NULL, NULL))
482 gint col_idx = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(column), "column_store_idx"));
484 if (bevent->button == MOUSE_BUTTON_LEFT &&
485 col_idx >= FILE_COLUMN_MARKS && col_idx <= FILE_COLUMN_MARKS_LAST)
488 if (col_idx >= FILE_COLUMN_MARKS && col_idx <= FILE_COLUMN_MARKS_LAST)
489 vf->clicked_mark = 1 + (col_idx - FILE_COLUMN_MARKS);
491 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
493 gtk_tree_model_get_iter(store, &iter, tpath);
494 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
496 gtk_tree_view_set_cursor(GTK_TREE_VIEW(widget), tpath, NULL, FALSE);
498 gtk_tree_path_free(tpath);
501 VFLIST_INFO(vf, click_fd) = fd;
503 if (bevent->button == MOUSE_BUTTON_RIGHT)
505 vf->popup = vf_pop_menu(vf);
506 gtk_menu_popup(GTK_MENU(vf->popup), NULL, NULL, NULL, NULL,
507 bevent->button, bevent->time);
511 if (!fd) return FALSE;
513 if (bevent->button == MOUSE_BUTTON_MIDDLE)
515 if (!vflist_row_is_selected(vf, fd))
517 vflist_color_set(vf, fd, TRUE);
523 if (bevent->button == MOUSE_BUTTON_LEFT && bevent->type == GDK_BUTTON_PRESS &&
524 !(bevent->state & GDK_SHIFT_MASK ) &&
525 !(bevent->state & GDK_CONTROL_MASK ) &&
526 vflist_row_is_selected(vf, fd))
528 GtkTreeSelection *selection;
530 gtk_widget_grab_focus(widget);
533 /* returning FALSE and further processing of the event is needed for
534 correct operation of the expander, to show the sidecar files.
535 It however resets the selection of multiple files. With this condition
536 it should work for both cases */
537 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
538 return (gtk_tree_selection_count_selected_rows(selection) > 1);
542 if (bevent->button == MOUSE_BUTTON_LEFT && bevent->type == GDK_2BUTTON_PRESS)
544 if (vf->layout) layout_image_full_screen_start(vf->layout);
551 gint vflist_release_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
558 if (bevent->button == MOUSE_BUTTON_MIDDLE)
560 vflist_color_set(vf, VFLIST_INFO(vf, click_fd), FALSE);
563 if (bevent->button != MOUSE_BUTTON_LEFT && bevent->button != MOUSE_BUTTON_MIDDLE)
568 if ((bevent->x != 0 || bevent->y != 0) &&
569 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), bevent->x, bevent->y,
570 &tpath, NULL, NULL, NULL))
574 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
575 gtk_tree_model_get_iter(store, &iter, tpath);
576 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
577 gtk_tree_path_free(tpath);
580 if (bevent->button == MOUSE_BUTTON_MIDDLE)
582 if (fd && VFLIST_INFO(vf, click_fd) == fd)
584 GtkTreeSelection *selection;
586 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
587 if (vflist_row_is_selected(vf, fd))
589 gtk_tree_selection_unselect_iter(selection, &iter);
593 gtk_tree_selection_select_iter(selection, &iter);
599 if (fd && VFLIST_INFO(vf, click_fd) == fd &&
600 !(bevent->state & GDK_SHIFT_MASK ) &&
601 !(bevent->state & GDK_CONTROL_MASK ) &&
602 vflist_row_is_selected(vf, fd))
604 GtkTreeSelection *selection;
606 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
607 gtk_tree_selection_unselect_all(selection);
608 gtk_tree_selection_select_iter(selection, &iter);
609 vflist_move_cursor(vf, &iter);
610 // return TRUE;// FIXME - expand
616 static void vflist_select_image(ViewFile *vf, FileData *sel_fd)
618 FileData *read_ahead_fd = NULL;
623 cur_fd = layout_image_get_fd(vf->layout);
624 if (sel_fd == cur_fd) return; /* no change */
626 row = g_list_index(vf->list, sel_fd);
627 // FIXME sidecar data
629 if (sel_fd && options->image.enable_read_ahead && row >= 0)
631 if (row > g_list_index(vf->list, cur_fd) &&
632 (guint) (row + 1) < vf_count(vf, NULL))
634 read_ahead_fd = vf_index_get_data(vf, row + 1);
638 read_ahead_fd = vf_index_get_data(vf, row - 1);
642 layout_image_set_with_ahead(vf->layout, sel_fd, read_ahead_fd);
645 static gint vflist_select_idle_cb(gpointer data)
651 VFLIST_INFO(vf, select_idle_id) = -1;
657 if (VFLIST_INFO(vf, select_fd))
659 vflist_select_image(vf, VFLIST_INFO(vf, select_fd));
660 VFLIST_INFO(vf, select_fd) = NULL;
663 VFLIST_INFO(vf, select_idle_id) = -1;
667 static void vflist_select_idle_cancel(ViewFile *vf)
669 if (VFLIST_INFO(vf, select_idle_id) != -1) g_source_remove(VFLIST_INFO(vf, select_idle_id));
670 VFLIST_INFO(vf, select_idle_id) = -1;
673 static gboolean vflist_select_cb(GtkTreeSelection *selection, GtkTreeModel *store, GtkTreePath *tpath,
674 gboolean path_currently_selected, gpointer data)
679 if (!path_currently_selected &&
680 gtk_tree_model_get_iter(store, &iter, tpath))
682 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &VFLIST_INFO(vf, select_fd), -1);
686 VFLIST_INFO(vf, select_fd) = NULL;
690 VFLIST_INFO(vf, select_idle_id) == -1)
692 VFLIST_INFO(vf, select_idle_id) = g_idle_add(vflist_select_idle_cb, vf);
699 *-----------------------------------------------------------------------------
701 *-----------------------------------------------------------------------------
705 static gboolean vflist_dummy_select_cb(GtkTreeSelection *selection, GtkTreeModel *store, GtkTreePath *tpath,
706 gboolean path_currently_selected, gpointer data)
713 static void vflist_setup_iter(ViewFile *vf, GtkTreeStore *store, GtkTreeIter *iter, FileData *fd)
717 gchar *sidecars = NULL;
719 if (fd->sidecar_files)
720 sidecars = file_data_sc_list_to_string(fd);
721 size = text_from_size(fd->size);
723 gtk_tree_store_set(store, iter, FILE_COLUMN_POINTER, fd,
724 FILE_COLUMN_THUMB, (VFLIST_INFO(vf, thumbs_enabled)) ? fd->pixbuf : NULL,
725 FILE_COLUMN_NAME, fd->name,
726 FILE_COLUMN_SIDECARS, sidecars,
727 FILE_COLUMN_SIZE, size,
728 FILE_COLUMN_DATE, text_from_time(fd->date),
729 FILE_COLUMN_COLOR, FALSE, -1);
730 for (i = 0; i < FILEDATA_MARKS_SIZE; i++)
731 gtk_tree_store_set(store, iter, FILE_COLUMN_MARKS + i, fd->marks[i], -1);
738 static void vflist_setup_iter_with_sidecars(ViewFile *vf, GtkTreeStore *store, GtkTreeIter *iter, FileData *fd)
744 vflist_setup_iter(vf, store, iter, fd);
747 /* this is almost the same code as in vflist_populate_view
748 maybe it should be made more generic and used in both places */
751 valid = gtk_tree_model_iter_children(GTK_TREE_MODEL(store), &s_iter, iter);
753 work = fd->sidecar_files;
757 FileData *sfd = work->data;
762 FileData *old_sfd = NULL;
766 gtk_tree_model_get(GTK_TREE_MODEL(store), &s_iter, FILE_COLUMN_POINTER, &old_sfd, -1);
774 match = filelist_sort_compare_filedata_full(sfd, old_sfd, SORT_NAME, TRUE);
789 gtk_tree_store_insert_before(store, &new, iter, &s_iter);
793 gtk_tree_store_append(store, &new, iter);
796 vflist_setup_iter(vf, store, &new, sfd);
802 valid = gtk_tree_store_remove(store, &s_iter);
806 vflist_setup_iter(vf, store, &s_iter, sfd);
808 if (valid) valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &s_iter);
818 valid = gtk_tree_store_remove(store, &s_iter);
822 void vflist_sort_set(ViewFile *vf, SortType type, gint ascend)
825 GHashTable *fd_idx_hash = g_hash_table_new(NULL, NULL);
830 if (vf->sort_method == type && vf->sort_ascend == ascend) return;
831 if (!vf->list) return;
837 FileData *fd = work->data;
838 g_hash_table_insert(fd_idx_hash, fd, GINT_TO_POINTER(i));
843 vf->sort_method = type;
844 vf->sort_ascend = ascend;
846 vf->list = filelist_sort(vf->list, vf->sort_method, vf->sort_ascend);
848 new_order = g_malloc(i * sizeof(gint));
854 FileData *fd = work->data;
855 new_order[i] = GPOINTER_TO_INT(g_hash_table_lookup(fd_idx_hash, fd));
860 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
861 gtk_tree_store_reorder(store, NULL, new_order);
864 g_hash_table_destroy(fd_idx_hash);
868 *-----------------------------------------------------------------------------
870 *-----------------------------------------------------------------------------
873 static gint vflist_thumb_next(ViewFile *vf);
875 static void vflist_thumb_status(ViewFile *vf, gdouble val, const gchar *text)
877 if (vf->func_thumb_status)
879 vf->func_thumb_status(vf, val, text, vf->data_thumb_status);
883 static void vflist_thumb_cleanup(ViewFile *vf)
885 vflist_thumb_status(vf, 0.0, NULL);
887 vf->thumbs_count = 0;
888 vf->thumbs_running = FALSE;
890 thumb_loader_free(vf->thumbs_loader);
891 vf->thumbs_loader = NULL;
893 vf->thumbs_filedata = NULL;
896 static void vflist_thumb_stop(ViewFile *vf)
898 if (vf->thumbs_running) vflist_thumb_cleanup(vf);
901 static void vflist_thumb_do(ViewFile *vf, ThumbLoader *tl, FileData *fd)
906 if (!fd || vflist_find_row(vf, fd, &iter) < 0) return;
908 if (fd->pixbuf) g_object_unref(fd->pixbuf);
909 fd->pixbuf = thumb_loader_get_pixbuf(tl, TRUE);
911 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
912 gtk_tree_store_set(store, &iter, FILE_COLUMN_THUMB, fd->pixbuf, -1);
914 vflist_thumb_status(vf, (gdouble)(vf->thumbs_count) / vflist_sidecar_list_count(vf->list), _("Loading thumbs..."));
917 static void vflist_thumb_error_cb(ThumbLoader *tl, gpointer data)
921 if (vf->thumbs_filedata && vf->thumbs_loader == tl)
923 vflist_thumb_do(vf, tl, vf->thumbs_filedata);
926 while (vflist_thumb_next(vf));
929 static void vflist_thumb_done_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 gint vflist_thumb_next(ViewFile *vf)
946 /* first check the visible files */
948 if (GTK_WIDGET_REALIZED(vf->listview) &&
949 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(vf->listview), 0, 0, &tpath, NULL, NULL, NULL))
955 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
956 gtk_tree_model_get_iter(store, &iter, tpath);
957 gtk_tree_path_free(tpath);
959 while (!fd && valid && tree_view_row_get_visibility(GTK_TREE_VIEW(vf->listview), &iter, FALSE) == 0)
961 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
962 if (fd->pixbuf) fd = NULL;
964 valid = gtk_tree_model_iter_next(store, &iter);
968 /* then find first undone */
972 GList *work = vf->list;
975 FileData *fd_p = work->data;
980 GList *work2 = fd_p->sidecar_files;
985 if (!fd_p->pixbuf) fd = fd_p;
996 vflist_thumb_cleanup(vf);
1002 vf->thumbs_filedata = fd;
1004 thumb_loader_free(vf->thumbs_loader);
1006 vf->thumbs_loader = thumb_loader_new(options->thumbnails.max_width, options->thumbnails.max_height);
1007 thumb_loader_set_callbacks(vf->thumbs_loader,
1008 vflist_thumb_done_cb,
1009 vflist_thumb_error_cb,
1013 if (!thumb_loader_start(vf->thumbs_loader, fd->path))
1015 /* set icon to unknown, continue */
1016 DEBUG_1("thumb loader start failed %s", vf->thumbs_loader->path);
1017 vflist_thumb_do(vf, vf->thumbs_loader, fd);
1025 static void vflist_thumb_update(ViewFile *vf)
1027 vflist_thumb_stop(vf);
1028 if (!VFLIST_INFO(vf, thumbs_enabled)) return;
1030 vflist_thumb_status(vf, 0.0, _("Loading thumbs..."));
1031 vf->thumbs_running = TRUE;
1033 while (vflist_thumb_next(vf));
1037 *-----------------------------------------------------------------------------
1039 *-----------------------------------------------------------------------------
1042 FileData *vflist_index_get_data(ViewFile *vf, gint row)
1044 return g_list_nth_data(vf->list, row);
1047 gint vflist_index_by_path(ViewFile *vf, const gchar *path)
1052 if (!path) return -1;
1057 FileData *fd = work->data;
1058 if (strcmp(path, fd->path) == 0) return p;
1067 guint vflist_count(ViewFile *vf, gint64 *bytes)
1077 FileData *fd = work->data;
1085 return g_list_length(vf->list);
1088 GList *vflist_get_list(ViewFile *vf)
1096 FileData *fd = work->data;
1099 list = g_list_prepend(list, file_data_ref(fd));
1102 return g_list_reverse(list);
1106 *-----------------------------------------------------------------------------
1108 *-----------------------------------------------------------------------------
1111 static gint vflist_row_is_selected(ViewFile *vf, FileData *fd)
1113 GtkTreeModel *store;
1114 GtkTreeSelection *selection;
1119 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1120 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1122 while (!found && work)
1124 GtkTreePath *tpath = work->data;
1128 gtk_tree_model_get_iter(store, &iter, tpath);
1129 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd_n, -1);
1130 if (fd_n == fd) found = TRUE;
1133 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1139 gint vflist_index_is_selected(ViewFile *vf, gint row)
1143 fd = vf_index_get_data(vf, row);
1144 return vflist_row_is_selected(vf, fd);
1147 guint vflist_selection_count(ViewFile *vf, gint64 *bytes)
1149 GtkTreeModel *store;
1150 GtkTreeSelection *selection;
1154 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1155 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1165 GtkTreePath *tpath = work->data;
1169 gtk_tree_model_get_iter(store, &iter, tpath);
1170 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
1179 count = g_list_length(slist);
1180 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1186 GList *vflist_selection_get_list(ViewFile *vf)
1188 GtkTreeModel *store;
1189 GtkTreeSelection *selection;
1194 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1195 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1199 GtkTreePath *tpath = work->data;
1203 gtk_tree_model_get_iter(store, &iter, tpath);
1204 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
1206 list = g_list_prepend(list, file_data_ref(fd));
1210 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1213 return g_list_reverse(list);
1216 GList *vflist_selection_get_list_by_index(ViewFile *vf)
1218 GtkTreeModel *store;
1219 GtkTreeSelection *selection;
1224 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1225 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1229 GtkTreePath *tpath = work->data;
1233 gtk_tree_model_get_iter(store, &iter, tpath);
1234 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
1236 list = g_list_prepend(list, GINT_TO_POINTER(g_list_index(vf->list, fd)));
1240 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1243 return g_list_reverse(list);
1246 void vflist_select_all(ViewFile *vf)
1248 GtkTreeSelection *selection;
1250 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1251 gtk_tree_selection_select_all(selection);
1253 VFLIST_INFO(vf, select_fd) = NULL;
1256 void vflist_select_none(ViewFile *vf)
1258 GtkTreeSelection *selection;
1260 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1261 gtk_tree_selection_unselect_all(selection);
1264 static gboolean tree_model_iter_prev(GtkTreeModel *store, GtkTreeIter *iter)
1269 tpath = gtk_tree_model_get_path(store, iter);
1270 result = gtk_tree_path_prev(tpath);
1272 gtk_tree_model_get_iter(store, iter, tpath);
1274 gtk_tree_path_free(tpath);
1279 static gboolean tree_model_get_iter_last(GtkTreeModel *store, GtkTreeIter *iter)
1281 if (!gtk_tree_model_get_iter_first(store, iter))
1286 GtkTreeIter next = *iter;
1288 if (gtk_tree_model_iter_next(store, &next))
1297 void vflist_select_invert(ViewFile *vf)
1300 GtkTreeSelection *selection;
1301 GtkTreeModel *store;
1304 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
1305 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1307 /* Backward iteration prevents scrolling to the end of the list,
1308 * it scrolls to the first selected row instead. */
1309 valid = tree_model_get_iter_last(store, &iter);
1313 gint selected = gtk_tree_selection_iter_is_selected(selection, &iter);
1316 gtk_tree_selection_unselect_iter(selection, &iter);
1318 gtk_tree_selection_select_iter(selection, &iter);
1320 valid = tree_model_iter_prev(store, &iter);
1324 void vflist_select_by_fd(ViewFile *vf, FileData *fd)
1328 if (vflist_find_row(vf, fd, &iter) < 0) return;
1330 tree_view_row_make_visible(GTK_TREE_VIEW(vf->listview), &iter, TRUE);
1332 if (!vflist_row_is_selected(vf, fd))
1334 GtkTreeSelection *selection;
1335 GtkTreeModel *store;
1338 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1339 gtk_tree_selection_unselect_all(selection);
1340 gtk_tree_selection_select_iter(selection, &iter);
1341 vflist_move_cursor(vf, &iter);
1343 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
1344 tpath = gtk_tree_model_get_path(store, &iter);
1345 gtk_tree_view_set_cursor(GTK_TREE_VIEW(vf->listview), tpath, NULL, FALSE);
1346 gtk_tree_path_free(tpath);
1350 void vflist_mark_to_selection(ViewFile *vf, gint mark, MarkToSelectionMode mode)
1352 GtkTreeModel *store;
1354 GtkTreeSelection *selection;
1358 g_assert(mark >= 1 && mark <= FILEDATA_MARKS_SIZE);
1360 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
1361 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1363 valid = gtk_tree_model_get_iter_first(store, &iter);
1367 gboolean mark_val, selected;
1368 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, FILE_COLUMN_POINTER, &fd, -1);
1370 mark_val = fd->marks[n];
1371 selected = gtk_tree_selection_iter_is_selected(selection, &iter);
1375 case MTS_MODE_SET: selected = mark_val;
1377 case MTS_MODE_OR: selected = mark_val | selected;
1379 case MTS_MODE_AND: selected = mark_val & selected;
1381 case MTS_MODE_MINUS: selected = !mark_val & selected;
1386 gtk_tree_selection_select_iter(selection, &iter);
1388 gtk_tree_selection_unselect_iter(selection, &iter);
1390 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
1394 void vflist_selection_to_mark(ViewFile *vf, gint mark, SelectionToMarkMode mode)
1396 GtkTreeModel *store;
1397 GtkTreeSelection *selection;
1402 g_assert(mark >= 1 && mark <= FILEDATA_MARKS_SIZE);
1404 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1405 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1409 GtkTreePath *tpath = work->data;
1413 gtk_tree_model_get_iter(store, &iter, tpath);
1414 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
1418 case STM_MODE_SET: fd->marks[n] = 1;
1420 case STM_MODE_RESET: fd->marks[n] = 0;
1422 case STM_MODE_TOGGLE: fd->marks[n] = !fd->marks[n];
1426 gtk_tree_store_set(GTK_TREE_STORE(store), &iter, FILE_COLUMN_MARKS + n, fd->marks[n], -1);
1430 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1435 *-----------------------------------------------------------------------------
1437 *-----------------------------------------------------------------------------
1440 static void vflist_listview_set_height(GtkWidget *listview, gint thumb)
1442 GtkTreeViewColumn *column;
1443 GtkCellRenderer *cell;
1446 column = gtk_tree_view_get_column(GTK_TREE_VIEW(listview), FILE_COLUMN_THUMB - 1);
1447 if (!column) return;
1449 gtk_tree_view_column_set_fixed_width(column, ((thumb) ? options->thumbnails.max_width : 4) + 10);
1451 list = gtk_tree_view_column_get_cell_renderers(column);
1456 g_object_set(G_OBJECT(cell), "height", (thumb) ? options->thumbnails.max_height : -1, NULL);
1457 gtk_tree_view_columns_autosize(GTK_TREE_VIEW(listview));
1460 static void vflist_populate_view(ViewFile *vf)
1462 GtkTreeStore *store;
1466 GtkTreeRowReference *visible_row = NULL;
1470 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
1471 thumbs = VFLIST_INFO(vf, thumbs_enabled);
1473 vflist_thumb_stop(vf);
1477 gtk_tree_store_clear(store);
1482 if (GTK_WIDGET_REALIZED(vf->listview) &&
1483 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(vf->listview), 0, 0, &tpath, NULL, NULL, NULL))
1485 visible_row = gtk_tree_row_reference_new(GTK_TREE_MODEL(store), tpath);
1486 gtk_tree_path_free(tpath);
1489 vflist_listview_set_height(vf->listview, thumbs);
1491 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
1497 FileData *fd = work->data;
1502 FileData *old_fd = NULL;
1506 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, FILE_COLUMN_POINTER, &old_fd, -1);
1514 match = filelist_sort_compare_filedata_full(fd, old_fd, vf->sort_method, vf->sort_ascend);
1516 match = -1; /* probably should not happen*/
1531 gtk_tree_store_insert_before(store, &new, NULL, &iter);
1535 gtk_tree_store_append(store, &new, NULL);
1537 vflist_setup_iter_with_sidecars(vf, store, &new, fd);
1543 valid = gtk_tree_store_remove(store, &iter);
1547 vflist_setup_iter_with_sidecars(vf, store, &iter, fd);
1549 if (valid) valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
1559 valid = gtk_tree_store_remove(store, &iter);
1564 if (gtk_tree_row_reference_valid(visible_row))
1566 tpath = gtk_tree_row_reference_get_path(visible_row);
1567 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(vf->listview), tpath, NULL, TRUE, 0.0, 0.0);
1568 gtk_tree_path_free(tpath);
1570 gtk_tree_row_reference_free(visible_row);
1574 vflist_thumb_update(vf);
1577 gint vflist_refresh(ViewFile *vf)
1582 old_list = vf->list;
1587 ret = filelist_read(vf->path, &vf->list, NULL);
1590 vf->list = filelist_sort(vf->list, vf->sort_method, vf->sort_ascend);
1591 vflist_populate_view(vf);
1593 filelist_free(old_list);
1598 /* this overrides the low default of a GtkCellRenderer from 100 to CELL_HEIGHT_OVERRIDE, something sane for our purposes */
1600 #define CELL_HEIGHT_OVERRIDE 512
1602 static void cell_renderer_height_override(GtkCellRenderer *renderer)
1606 spec = g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(renderer)), "height");
1607 if (spec && G_IS_PARAM_SPEC_INT(spec))
1609 GParamSpecInt *spec_int;
1611 spec_int = G_PARAM_SPEC_INT(spec);
1612 if (spec_int->maximum < CELL_HEIGHT_OVERRIDE) spec_int->maximum = CELL_HEIGHT_OVERRIDE;
1616 static GdkColor *vflist_listview_color_shifted(GtkWidget *widget)
1618 static GdkColor color;
1619 static GtkWidget *done = NULL;
1625 style = gtk_widget_get_style(widget);
1626 memcpy(&color, &style->base[GTK_STATE_NORMAL], sizeof(color));
1627 shift_color(&color, -1, 0);
1634 static void vflist_listview_color_cb(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1635 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1637 ViewFile *vf = data;
1640 gtk_tree_model_get(tree_model, iter, FILE_COLUMN_COLOR, &set, -1);
1641 g_object_set(G_OBJECT(cell),
1642 "cell-background-gdk", vflist_listview_color_shifted(vf->listview),
1643 "cell-background-set", set, NULL);
1646 static void vflist_listview_add_column(ViewFile *vf, gint n, const gchar *title, gint image, gint right_justify, gint expand)
1648 GtkTreeViewColumn *column;
1649 GtkCellRenderer *renderer;
1651 column = gtk_tree_view_column_new();
1652 gtk_tree_view_column_set_title(column, title);
1653 gtk_tree_view_column_set_min_width(column, 4);
1657 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_GROW_ONLY);
1658 renderer = gtk_cell_renderer_text_new();
1661 g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
1663 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1664 gtk_tree_view_column_add_attribute(column, renderer, "text", n);
1666 gtk_tree_view_column_set_expand(column, TRUE);
1670 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
1671 renderer = gtk_cell_renderer_pixbuf_new();
1672 cell_renderer_height_override(renderer);
1673 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1674 gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", n);
1677 gtk_tree_view_column_set_cell_data_func(column, renderer, vflist_listview_color_cb, vf, NULL);
1678 g_object_set_data(G_OBJECT(column), "column_store_idx", GUINT_TO_POINTER(n));
1679 g_object_set_data(G_OBJECT(renderer), "column_store_idx", GUINT_TO_POINTER(n));
1681 gtk_tree_view_append_column(GTK_TREE_VIEW(vf->listview), column);
1684 static void vflist_listview_mark_toggled(GtkCellRendererToggle *cell, gchar *path_str, GtkTreeStore *store)
1686 GtkTreePath *path = gtk_tree_path_new_from_string(path_str);
1692 if (!path || !gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, path))
1695 col_idx = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cell), "column_store_idx"));
1697 g_assert(col_idx >= FILE_COLUMN_MARKS && col_idx <= FILE_COLUMN_MARKS_LAST);
1699 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, FILE_COLUMN_POINTER, &fd, col_idx, &mark, -1);
1701 fd->marks[col_idx - FILE_COLUMN_MARKS] = mark;
1703 gtk_tree_store_set(store, &iter, col_idx, mark, -1);
1704 gtk_tree_path_free(path);
1707 static void vflist_listview_add_column_toggle(ViewFile *vf, gint n, const gchar *title)
1709 GtkTreeViewColumn *column;
1710 GtkCellRenderer *renderer;
1711 GtkTreeStore *store;
1714 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
1716 renderer = gtk_cell_renderer_toggle_new();
1717 column = gtk_tree_view_column_new_with_attributes(title, renderer, "active", n, NULL);
1719 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
1720 g_object_set_data(G_OBJECT(column), "column_store_idx", GUINT_TO_POINTER(n));
1721 g_object_set_data(G_OBJECT(renderer), "column_store_idx", GUINT_TO_POINTER(n));
1723 index = gtk_tree_view_append_column(GTK_TREE_VIEW(vf->listview), column);
1724 gtk_tree_view_column_set_fixed_width(column, 16);
1725 gtk_tree_view_column_set_visible(column, vf->marks_enabled);
1728 g_signal_connect(G_OBJECT(renderer), "toggled", G_CALLBACK(vflist_listview_mark_toggled), store);
1732 *-----------------------------------------------------------------------------
1734 *-----------------------------------------------------------------------------
1737 gint vflist_set_path(ViewFile *vf, const gchar *path)
1739 GtkTreeStore *store;
1741 if (!path) return FALSE;
1742 if (vf->path && strcmp(path, vf->path) == 0) return TRUE;
1745 vf->path = g_strdup(path);
1747 /* force complete reload */
1748 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
1749 gtk_tree_store_clear(store);
1751 filelist_free(vf->list);
1754 return vf_refresh(vf);
1757 void vflist_destroy_cb(GtkWidget *widget, gpointer data)
1759 ViewFile *vf = data;
1761 vflist_select_idle_cancel(vf);
1762 vflist_thumb_stop(vf);
1764 filelist_free(vf->list);
1767 ViewFile *vflist_new(ViewFile *vf, const gchar *path)
1769 GtkTreeStore *store;
1770 GtkTreeSelection *selection;
1772 GType flist_types[FILE_COLUMN_COUNT];
1775 vf->info = g_new0(ViewFileInfoList, 1);
1777 VFLIST_INFO(vf, click_fd) = NULL;
1778 VFLIST_INFO(vf, select_fd) = NULL;
1779 VFLIST_INFO(vf, thumbs_enabled) = FALSE;
1781 VFLIST_INFO(vf, select_idle_id) = -1;
1783 flist_types[FILE_COLUMN_POINTER] = G_TYPE_POINTER;
1784 flist_types[FILE_COLUMN_THUMB] = GDK_TYPE_PIXBUF;
1785 flist_types[FILE_COLUMN_NAME] = G_TYPE_STRING;
1786 flist_types[FILE_COLUMN_SIDECARS] = G_TYPE_STRING;
1787 flist_types[FILE_COLUMN_SIZE] = G_TYPE_STRING;
1788 flist_types[FILE_COLUMN_DATE] = G_TYPE_STRING;
1789 flist_types[FILE_COLUMN_COLOR] = G_TYPE_BOOLEAN;
1790 for (i = FILE_COLUMN_MARKS; i < FILE_COLUMN_MARKS + FILEDATA_MARKS_SIZE; i++)
1791 flist_types[i] = G_TYPE_BOOLEAN;
1793 store = gtk_tree_store_newv(FILE_COLUMN_COUNT, flist_types);
1795 vf->listview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
1796 g_object_unref(store);
1798 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1799 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
1800 gtk_tree_selection_set_select_function(selection, vflist_select_cb, vf, NULL);
1802 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(vf->listview), FALSE);
1803 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(vf->listview), FALSE);
1805 vflist_listview_add_column(vf, FILE_COLUMN_THUMB, "", TRUE, FALSE, FALSE);
1807 for (i = 0; i < FILEDATA_MARKS_SIZE; i++)
1808 vflist_listview_add_column_toggle(vf, i + FILE_COLUMN_MARKS, "");
1810 vflist_listview_add_column(vf, FILE_COLUMN_NAME, _("Name"), FALSE, FALSE, FALSE);
1811 vflist_listview_add_column(vf, FILE_COLUMN_SIDECARS, _("SC"), FALSE, FALSE, FALSE);
1813 vflist_listview_add_column(vf, FILE_COLUMN_SIZE, _("Size"), FALSE, TRUE, FALSE);
1814 vflist_listview_add_column(vf, FILE_COLUMN_DATE, _("Date"), FALSE, TRUE, FALSE);
1819 void vflist_thumb_set(ViewFile *vf, gint enable)
1821 if (VFLIST_INFO(vf, thumbs_enabled) == enable) return;
1823 VFLIST_INFO(vf, thumbs_enabled) = enable;
1824 if (vf->layout) vf_refresh(vf);
1827 void vflist_marks_set(ViewFile *vf, gint enable)
1829 GList *columns, *work;
1831 if (vf->marks_enabled == enable) return;
1833 vf->marks_enabled = enable;
1835 columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(vf->listview));
1840 GtkTreeViewColumn *column = work->data;
1841 gint col_idx = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(column), "column_store_idx"));
1844 if (col_idx <= FILE_COLUMN_MARKS_LAST && col_idx >= FILE_COLUMN_MARKS)
1845 gtk_tree_view_column_set_visible(column, enable);
1848 g_list_free(columns);
1853 *-----------------------------------------------------------------------------
1854 * maintenance (for rename, move, remove)
1855 *-----------------------------------------------------------------------------
1858 static gint vflist_maint_find_closest(ViewFile *vf, gint row, gint count, GList *ignore_list)
1868 gint f = vf_index_by_path(vf, work->data);
1869 if (f >= 0) list = g_list_prepend(list, GINT_TO_POINTER(f));
1879 gpointer p = work->data;
1881 if (row == GPOINTER_TO_INT(p))
1886 if (rev == GPOINTER_TO_INT(p))
1891 if (!c) list = g_list_remove(list, p);
1899 if (row > count - 1)
1912 gint vflist_maint_renamed(ViewFile *vf, FileData *fd)
1918 if (g_list_index(vf->list, fd) < 0) return FALSE;
1920 source_base = remove_level_from_path(fd->change->source);
1921 dest_base = remove_level_from_path(fd->change->dest);
1924 if (strcmp(source_base, dest_base) == 0)
1926 GtkTreeStore *store;
1928 GtkTreeIter position;
1932 old_row = g_list_index(vf->list, fd);
1934 vf->list = g_list_remove(vf->list, fd);
1936 vf->list = filelist_insert_sort(vf->list, fd, vf->sort_method, vf->sort_ascend);
1937 n = g_list_index(vf->list, fd);
1939 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
1940 if (vflist_find_row(vf, fd, &iter) >= 0 &&
1941 gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &position, NULL, n))
1945 gtk_tree_store_move_before(store, &iter, &position);
1949 gtk_tree_store_move_after(store, &iter, &position);
1952 gtk_tree_store_set(store, &iter, FILE_COLUMN_NAME, fd->name, -1);
1958 ret = vflist_maint_removed(vf, fd, NULL);
1961 g_free(source_base);
1967 gint vflist_maint_removed(ViewFile *vf, FileData *fd, GList *ignore_list)
1974 row = g_list_index(vf->list, fd);
1975 if (row < 0) return FALSE;
1977 if (vflist_index_is_selected(vf, row) &&
1978 layout_image_get_collection(vf->layout, NULL) == NULL)
1982 n = vf_count(vf, NULL);
1985 new_row = vflist_maint_find_closest(vf, row, n, ignore_list);
1986 DEBUG_1("row = %d, closest is %d", row, new_row);
2002 fd = vf_index_get_data(vf, new_row);
2003 if (vflist_find_row(vf, fd, &iter) >= 0)
2005 GtkTreeSelection *selection;
2007 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
2008 gtk_tree_selection_select_iter(selection, &iter);
2009 vflist_move_cursor(vf, &iter);
2014 fd = vf_index_get_data(vf, row);
2015 if (vflist_find_row(vf, fd, &iter) >= 0)
2017 GtkTreeStore *store;
2018 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
2019 gtk_tree_store_remove(store, &iter);
2021 list = g_list_nth(vf->list, row);
2024 /* thumbnail loader check */
2025 if (fd == vf->thumbs_filedata) vf->thumbs_filedata = NULL;
2026 if (vf->thumbs_count > 0) vf->thumbs_count--;
2028 vf->list = g_list_remove(vf->list, fd);
2029 file_data_unref(fd);
2036 gint vflist_maint_moved(ViewFile *vf, FileData *fd, GList *ignore_list)
2041 if (!fd->change->source || !vf->path) return FALSE;
2043 buf = remove_level_from_path(fd->change->source);
2045 if (strcmp(buf, vf->path) == 0)
2047 ret = vflist_maint_removed(vf, fd, ignore_list);