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;
1581 DEBUG_1("%s vflist_refresh: read dir", get_exec_time());
1584 ret = filelist_read(vf->path, &vf->list, NULL);
1586 DEBUG_1("%s vflist_refresh: sort", get_exec_time());
1588 vf->list = filelist_sort(vf->list, vf->sort_method, vf->sort_ascend);
1590 DEBUG_1("%s vflist_refresh: populate view", get_exec_time());
1592 vflist_populate_view(vf);
1594 filelist_free(old_list);
1595 DEBUG_1("%s vflist_refresh: done", get_exec_time());
1600 /* this overrides the low default of a GtkCellRenderer from 100 to CELL_HEIGHT_OVERRIDE, something sane for our purposes */
1602 #define CELL_HEIGHT_OVERRIDE 512
1604 static void cell_renderer_height_override(GtkCellRenderer *renderer)
1608 spec = g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(renderer)), "height");
1609 if (spec && G_IS_PARAM_SPEC_INT(spec))
1611 GParamSpecInt *spec_int;
1613 spec_int = G_PARAM_SPEC_INT(spec);
1614 if (spec_int->maximum < CELL_HEIGHT_OVERRIDE) spec_int->maximum = CELL_HEIGHT_OVERRIDE;
1618 static GdkColor *vflist_listview_color_shifted(GtkWidget *widget)
1620 static GdkColor color;
1621 static GtkWidget *done = NULL;
1627 style = gtk_widget_get_style(widget);
1628 memcpy(&color, &style->base[GTK_STATE_NORMAL], sizeof(color));
1629 shift_color(&color, -1, 0);
1636 static void vflist_listview_color_cb(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1637 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1639 ViewFile *vf = data;
1642 gtk_tree_model_get(tree_model, iter, FILE_COLUMN_COLOR, &set, -1);
1643 g_object_set(G_OBJECT(cell),
1644 "cell-background-gdk", vflist_listview_color_shifted(vf->listview),
1645 "cell-background-set", set, NULL);
1648 static void vflist_listview_add_column(ViewFile *vf, gint n, const gchar *title, gint image, gint right_justify, gint expand)
1650 GtkTreeViewColumn *column;
1651 GtkCellRenderer *renderer;
1653 column = gtk_tree_view_column_new();
1654 gtk_tree_view_column_set_title(column, title);
1655 gtk_tree_view_column_set_min_width(column, 4);
1659 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_GROW_ONLY);
1660 renderer = gtk_cell_renderer_text_new();
1663 g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
1665 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1666 gtk_tree_view_column_add_attribute(column, renderer, "text", n);
1668 gtk_tree_view_column_set_expand(column, TRUE);
1672 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
1673 renderer = gtk_cell_renderer_pixbuf_new();
1674 cell_renderer_height_override(renderer);
1675 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1676 gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", n);
1679 gtk_tree_view_column_set_cell_data_func(column, renderer, vflist_listview_color_cb, vf, NULL);
1680 g_object_set_data(G_OBJECT(column), "column_store_idx", GUINT_TO_POINTER(n));
1681 g_object_set_data(G_OBJECT(renderer), "column_store_idx", GUINT_TO_POINTER(n));
1683 gtk_tree_view_append_column(GTK_TREE_VIEW(vf->listview), column);
1686 static void vflist_listview_mark_toggled(GtkCellRendererToggle *cell, gchar *path_str, GtkTreeStore *store)
1688 GtkTreePath *path = gtk_tree_path_new_from_string(path_str);
1694 if (!path || !gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, path))
1697 col_idx = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cell), "column_store_idx"));
1699 g_assert(col_idx >= FILE_COLUMN_MARKS && col_idx <= FILE_COLUMN_MARKS_LAST);
1701 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, FILE_COLUMN_POINTER, &fd, col_idx, &mark, -1);
1703 fd->marks[col_idx - FILE_COLUMN_MARKS] = mark;
1705 gtk_tree_store_set(store, &iter, col_idx, mark, -1);
1706 gtk_tree_path_free(path);
1709 static void vflist_listview_add_column_toggle(ViewFile *vf, gint n, const gchar *title)
1711 GtkTreeViewColumn *column;
1712 GtkCellRenderer *renderer;
1713 GtkTreeStore *store;
1716 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
1718 renderer = gtk_cell_renderer_toggle_new();
1719 column = gtk_tree_view_column_new_with_attributes(title, renderer, "active", n, NULL);
1721 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
1722 g_object_set_data(G_OBJECT(column), "column_store_idx", GUINT_TO_POINTER(n));
1723 g_object_set_data(G_OBJECT(renderer), "column_store_idx", GUINT_TO_POINTER(n));
1725 index = gtk_tree_view_append_column(GTK_TREE_VIEW(vf->listview), column);
1726 gtk_tree_view_column_set_fixed_width(column, 16);
1727 gtk_tree_view_column_set_visible(column, vf->marks_enabled);
1730 g_signal_connect(G_OBJECT(renderer), "toggled", G_CALLBACK(vflist_listview_mark_toggled), store);
1734 *-----------------------------------------------------------------------------
1736 *-----------------------------------------------------------------------------
1739 gint vflist_set_path(ViewFile *vf, const gchar *path)
1741 GtkTreeStore *store;
1743 if (!path) return FALSE;
1744 if (vf->path && strcmp(path, vf->path) == 0) return TRUE;
1747 vf->path = g_strdup(path);
1749 /* force complete reload */
1750 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
1751 gtk_tree_store_clear(store);
1753 filelist_free(vf->list);
1756 return vf_refresh(vf);
1759 void vflist_destroy_cb(GtkWidget *widget, gpointer data)
1761 ViewFile *vf = data;
1763 vflist_select_idle_cancel(vf);
1764 vflist_thumb_stop(vf);
1766 filelist_free(vf->list);
1769 ViewFile *vflist_new(ViewFile *vf, const gchar *path)
1771 GtkTreeStore *store;
1772 GtkTreeSelection *selection;
1774 GType flist_types[FILE_COLUMN_COUNT];
1777 vf->info = g_new0(ViewFileInfoList, 1);
1779 VFLIST_INFO(vf, click_fd) = NULL;
1780 VFLIST_INFO(vf, select_fd) = NULL;
1781 VFLIST_INFO(vf, thumbs_enabled) = FALSE;
1783 VFLIST_INFO(vf, select_idle_id) = -1;
1785 flist_types[FILE_COLUMN_POINTER] = G_TYPE_POINTER;
1786 flist_types[FILE_COLUMN_THUMB] = GDK_TYPE_PIXBUF;
1787 flist_types[FILE_COLUMN_NAME] = G_TYPE_STRING;
1788 flist_types[FILE_COLUMN_SIDECARS] = G_TYPE_STRING;
1789 flist_types[FILE_COLUMN_SIZE] = G_TYPE_STRING;
1790 flist_types[FILE_COLUMN_DATE] = G_TYPE_STRING;
1791 flist_types[FILE_COLUMN_COLOR] = G_TYPE_BOOLEAN;
1792 for (i = FILE_COLUMN_MARKS; i < FILE_COLUMN_MARKS + FILEDATA_MARKS_SIZE; i++)
1793 flist_types[i] = G_TYPE_BOOLEAN;
1795 store = gtk_tree_store_newv(FILE_COLUMN_COUNT, flist_types);
1797 vf->listview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
1798 g_object_unref(store);
1800 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1801 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
1802 gtk_tree_selection_set_select_function(selection, vflist_select_cb, vf, NULL);
1804 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(vf->listview), FALSE);
1805 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(vf->listview), FALSE);
1807 vflist_listview_add_column(vf, FILE_COLUMN_THUMB, "", TRUE, FALSE, FALSE);
1809 for (i = 0; i < FILEDATA_MARKS_SIZE; i++)
1810 vflist_listview_add_column_toggle(vf, i + FILE_COLUMN_MARKS, "");
1812 vflist_listview_add_column(vf, FILE_COLUMN_NAME, _("Name"), FALSE, FALSE, FALSE);
1813 vflist_listview_add_column(vf, FILE_COLUMN_SIDECARS, _("SC"), FALSE, FALSE, FALSE);
1815 vflist_listview_add_column(vf, FILE_COLUMN_SIZE, _("Size"), FALSE, TRUE, FALSE);
1816 vflist_listview_add_column(vf, FILE_COLUMN_DATE, _("Date"), FALSE, TRUE, FALSE);
1821 void vflist_thumb_set(ViewFile *vf, gint enable)
1823 if (VFLIST_INFO(vf, thumbs_enabled) == enable) return;
1825 VFLIST_INFO(vf, thumbs_enabled) = enable;
1826 if (vf->layout) vf_refresh(vf);
1829 void vflist_marks_set(ViewFile *vf, gint enable)
1831 GList *columns, *work;
1833 if (vf->marks_enabled == enable) return;
1835 vf->marks_enabled = enable;
1837 columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(vf->listview));
1842 GtkTreeViewColumn *column = work->data;
1843 gint col_idx = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(column), "column_store_idx"));
1846 if (col_idx <= FILE_COLUMN_MARKS_LAST && col_idx >= FILE_COLUMN_MARKS)
1847 gtk_tree_view_column_set_visible(column, enable);
1850 g_list_free(columns);
1855 *-----------------------------------------------------------------------------
1856 * maintenance (for rename, move, remove)
1857 *-----------------------------------------------------------------------------
1860 static gint vflist_maint_find_closest(ViewFile *vf, gint row, gint count, GList *ignore_list)
1870 gint f = vf_index_by_path(vf, work->data);
1871 if (f >= 0) list = g_list_prepend(list, GINT_TO_POINTER(f));
1881 gpointer p = work->data;
1883 if (row == GPOINTER_TO_INT(p))
1888 if (rev == GPOINTER_TO_INT(p))
1893 if (!c) list = g_list_remove(list, p);
1901 if (row > count - 1)
1914 gint vflist_maint_renamed(ViewFile *vf, FileData *fd)
1920 DEBUG_1("%s vflist_maint_renamed: start", get_exec_time());
1922 if (g_list_index(vf->list, fd) < 0) return FALSE;
1924 source_base = remove_level_from_path(fd->change->source);
1925 dest_base = remove_level_from_path(fd->change->dest);
1928 if (strcmp(source_base, dest_base) == 0)
1930 GtkTreeStore *store;
1932 GtkTreeIter position;
1936 old_row = g_list_index(vf->list, fd);
1938 vf->list = g_list_remove(vf->list, fd);
1940 vf->list = filelist_insert_sort(vf->list, fd, vf->sort_method, vf->sort_ascend);
1941 n = g_list_index(vf->list, fd);
1943 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
1944 if (vflist_find_row(vf, fd, &iter) >= 0 &&
1945 gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &position, NULL, n))
1949 gtk_tree_store_move_before(store, &iter, &position);
1953 gtk_tree_store_move_after(store, &iter, &position);
1956 gtk_tree_store_set(store, &iter, FILE_COLUMN_NAME, fd->name, -1);
1962 ret = vflist_maint_removed(vf, fd, NULL);
1965 g_free(source_base);
1968 DEBUG_1("%s vflist_maint_renamed: done", get_exec_time());
1973 gint vflist_maint_removed(ViewFile *vf, FileData *fd, GList *ignore_list)
1980 DEBUG_1("%s vflist_maint_removed: start", get_exec_time());
1982 row = g_list_index(vf->list, fd);
1983 if (row < 0) return FALSE;
1985 if (vflist_index_is_selected(vf, row) &&
1986 layout_image_get_collection(vf->layout, NULL) == NULL)
1990 n = vf_count(vf, NULL);
1993 new_row = vflist_maint_find_closest(vf, row, n, ignore_list);
1994 DEBUG_1("row = %d, closest is %d", row, new_row);
2010 fd = vf_index_get_data(vf, new_row);
2011 if (vflist_find_row(vf, fd, &iter) >= 0)
2013 GtkTreeSelection *selection;
2015 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
2016 gtk_tree_selection_select_iter(selection, &iter);
2017 vflist_move_cursor(vf, &iter);
2022 fd = vf_index_get_data(vf, row);
2023 if (vflist_find_row(vf, fd, &iter) >= 0)
2025 GtkTreeStore *store;
2026 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
2027 gtk_tree_store_remove(store, &iter);
2029 list = g_list_nth(vf->list, row);
2032 /* thumbnail loader check */
2033 if (fd == vf->thumbs_filedata) vf->thumbs_filedata = NULL;
2034 if (vf->thumbs_count > 0) vf->thumbs_count--;
2036 vf->list = g_list_remove(vf->list, fd);
2037 file_data_unref(fd);
2041 DEBUG_1("%s vflist_maint_removed: done", get_exec_time());
2046 gint vflist_maint_moved(ViewFile *vf, FileData *fd, GList *ignore_list)
2051 if (!fd->change->source || !vf->path) return FALSE;
2053 buf = remove_level_from_path(fd->change->source);
2055 if (strcmp(buf, vf->path) == 0)
2057 ret = vflist_maint_removed(vf, fd, ignore_list);