4 * Copyright (C) 2008 The Geeqie Team
8 * This software is released under the GNU General Public License (GNU GPL).
9 * Please read the included file COPYING for more information.
10 * This software comes with no warranty of any kind, use at your own risk!
14 #include "view_file_list.h"
16 #include "cache_maint.h"
22 #include "layout_image.h"
26 #include "ui_bookmark.h"
27 #include "ui_fileops.h"
29 #include "ui_tree_edit.h"
30 #include "view_file.h"
32 #include <gdk/gdkkeysyms.h> /* for keyboard values */
36 FILE_COLUMN_POINTER = 0,
45 FILE_COLUMN_MARKS_LAST = FILE_COLUMN_MARKS + FILEDATA_MARKS_SIZE - 1,
50 static gint vflist_row_is_selected(ViewFile *vf, FileData *fd);
51 static gint vflist_row_rename_cb(TreeEditData *td, const gchar *old, const gchar *new, gpointer data);
52 static void vflist_populate_view(ViewFile *vf);
56 *-----------------------------------------------------------------------------
58 *-----------------------------------------------------------------------------
65 } ViewFileFindRowData;
67 static gboolean vflist_find_row_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
69 ViewFileFindRowData *find = data;
71 gtk_tree_model_get(model, iter, FILE_COLUMN_POINTER, &fd, -1);
82 static gint vflist_find_row(ViewFile *vf, FileData *fd, GtkTreeIter *iter)
85 ViewFileFindRowData data = {fd, iter, 0, 0};
87 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
88 gtk_tree_model_foreach(store, vflist_find_row_cb, &data);
100 static gint vflist_find_sidecar_list_idx(GList *work, FileData *fd)
105 FileData *fd_p = work->data;
106 if (fd == fd_p) return i;
110 GList *work2 = fd_p->sidecar_files;
114 if (fd == fd_p) return i;
125 static gint vflist_sidecar_list_count(GList *work)
130 FileData *fd = work->data;
133 GList *work2 = fd->sidecar_files;
145 void vflist_color_set(ViewFile *vf, FileData *fd, gint color_set)
150 if (vflist_find_row(vf, fd, &iter) < 0) return;
151 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
152 gtk_tree_store_set(GTK_TREE_STORE(store), &iter, FILE_COLUMN_COLOR, color_set, -1);
155 static void vflist_move_cursor(ViewFile *vf, GtkTreeIter *iter)
160 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
162 tpath = gtk_tree_model_get_path(store, iter);
163 gtk_tree_view_set_cursor(GTK_TREE_VIEW(vf->listview), tpath, NULL, FALSE);
164 gtk_tree_path_free(tpath);
168 static gint vflist_column_idx(ViewFile *vf, gint store_idx)
170 GList *columns, *work;
173 columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(vf->listview));
177 GtkTreeViewColumn *column = work->data;
178 if (store_idx == GPOINTER_TO_INT(g_object_get_data (G_OBJECT(column), "column_store_idx")))
184 g_list_free(columns);
190 *-----------------------------------------------------------------------------
192 *-----------------------------------------------------------------------------
195 static void vflist_dnd_get(GtkWidget *widget, GdkDragContext *context,
196 GtkSelectionData *selection_data, guint info,
197 guint time, gpointer data)
201 gchar *uri_text = NULL;
204 if (!VFLIST_INFO(vf, click_fd)) return;
206 if (vflist_row_is_selected(vf, VFLIST_INFO(vf, click_fd)))
208 list = vf_selection_get_list(vf);
212 list = g_list_append(NULL, file_data_ref(VFLIST_INFO(vf, click_fd)));
217 uri_text = uri_text_from_filelist(list, &total, (info == TARGET_TEXT_PLAIN));
222 gtk_selection_data_set(selection_data, selection_data->target,
223 8, (guchar *)uri_text, total);
227 static void vflist_dnd_begin(GtkWidget *widget, GdkDragContext *context, gpointer data)
231 vflist_color_set(vf, VFLIST_INFO(vf, click_fd), TRUE);
233 if (VFLIST_INFO(vf, thumbs_enabled) &&
234 VFLIST_INFO(vf, click_fd) && VFLIST_INFO(vf, click_fd)->pixbuf)
238 if (vflist_row_is_selected(vf, VFLIST_INFO(vf, click_fd)))
239 items = vf_selection_count(vf, NULL);
243 dnd_set_drag_icon(widget, context, VFLIST_INFO(vf, click_fd)->pixbuf, items);
247 static void vflist_dnd_end(GtkWidget *widget, GdkDragContext *context, gpointer data)
251 vflist_color_set(vf, VFLIST_INFO(vf, click_fd), FALSE);
253 if (context->action == GDK_ACTION_MOVE)
259 void vflist_dnd_init(ViewFile *vf)
261 gtk_drag_source_set(vf->listview, GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
262 dnd_file_drag_types, dnd_file_drag_types_count,
263 GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK);
264 g_signal_connect(G_OBJECT(vf->listview), "drag_data_get",
265 G_CALLBACK(vflist_dnd_get), vf);
266 g_signal_connect(G_OBJECT(vf->listview), "drag_begin",
267 G_CALLBACK(vflist_dnd_begin), vf);
268 g_signal_connect(G_OBJECT(vf->listview), "drag_end",
269 G_CALLBACK(vflist_dnd_end), vf);
273 *-----------------------------------------------------------------------------
275 *-----------------------------------------------------------------------------
278 GList *vflist_pop_menu_file_list(ViewFile *vf)
280 if (!VFLIST_INFO(vf, click_fd)) return NULL;
282 if (vflist_row_is_selected(vf, VFLIST_INFO(vf, click_fd)))
284 return vf_selection_get_list(vf);
287 return g_list_append(NULL, file_data_ref(VFLIST_INFO(vf, click_fd)));
290 void vflist_pop_menu_view_cb(GtkWidget *widget, gpointer data)
294 if (vflist_row_is_selected(vf, VFLIST_INFO(vf, click_fd)))
298 list = vf_selection_get_list(vf);
299 view_window_new_from_list(list);
304 view_window_new(VFLIST_INFO(vf, click_fd));
308 void vflist_pop_menu_rename_cb(GtkWidget *widget, gpointer data)
313 list = vf_pop_menu_file_list(vf);
314 if (options->file_ops.enable_in_place_rename &&
315 list && !list->next && VFLIST_INFO(vf, click_fd))
322 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
323 if (vflist_find_row(vf, VFLIST_INFO(vf, click_fd), &iter) >= 0)
327 tpath = gtk_tree_model_get_path(store, &iter);
328 tree_edit_by_path(GTK_TREE_VIEW(vf->listview), tpath,
329 vflist_column_idx(vf, FILE_COLUMN_NAME), VFLIST_INFO(vf, click_fd)->name,
330 vflist_row_rename_cb, vf);
331 gtk_tree_path_free(tpath);
336 file_util_rename(NULL, list, vf->listview);
339 void vflist_pop_menu_thumbs_cb(GtkWidget *widget, gpointer data)
343 vflist_color_set(vf, VFLIST_INFO(vf, click_fd), FALSE);
346 layout_thumb_set(vf->layout, !VFLIST_INFO(vf, thumbs_enabled));
350 vflist_thumb_set(vf, !VFLIST_INFO(vf, thumbs_enabled));
354 void vflist_pop_menu_refresh_cb(GtkWidget *widget, gpointer data)
358 vflist_color_set(vf, VFLIST_INFO(vf, click_fd), FALSE);
362 void vflist_popup_destroy_cb(GtkWidget *widget, gpointer data)
365 vflist_color_set(vf, VFLIST_INFO(vf, click_fd), FALSE);
366 VFLIST_INFO(vf, click_fd) = NULL;
372 *-----------------------------------------------------------------------------
374 *-----------------------------------------------------------------------------
377 static gint vflist_row_rename_cb(TreeEditData *td, const gchar *old, const gchar *new, gpointer data)
383 if (strlen(new) == 0) return FALSE;
385 old_path = g_build_filename(vf->path, old, NULL);
386 new_path = g_build_filename(vf->path, new, NULL);
388 if (strchr(new, G_DIR_SEPARATOR) != NULL)
390 gchar *text = g_strdup_printf(_("Invalid file name:\n%s"), new);
391 file_util_warning_dialog(_("Error renaming file"), text, GTK_STOCK_DIALOG_ERROR, vf->listview);
394 else if (isfile(new_path))
396 gchar *text = g_strdup_printf(_("A file with name %s already exists."), new);
397 file_util_warning_dialog(_("Error renaming file"), text, GTK_STOCK_DIALOG_ERROR, vf->listview);
402 gint row = vf_index_by_path(vf, old_path);
405 GList *work = g_list_nth(vf->list, row);
406 FileData *fd = work->data;
408 file_util_rename_simple(fd, new_path, vf->listview);
419 static void vflist_menu_position_cb(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer data)
427 if (vflist_find_row(vf, VFLIST_INFO(vf, click_fd), &iter) < 0) return;
428 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
429 tpath = gtk_tree_model_get_path(store, &iter);
430 tree_view_get_cell_clamped(GTK_TREE_VIEW(vf->listview), tpath, FILE_COLUMN_NAME - 1, TRUE, x, y, &cw, &ch);
431 gtk_tree_path_free(tpath);
433 popup_menu_position_clamp(menu, x, y, 0);
436 gint vflist_press_key_cb(GtkWidget *widget, GdkEventKey *event, gpointer data)
441 if (event->keyval != GDK_Menu) return FALSE;
443 gtk_tree_view_get_cursor(GTK_TREE_VIEW(vf->listview), &tpath, NULL);
449 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
450 gtk_tree_model_get_iter(store, &iter, tpath);
451 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &VFLIST_INFO(vf, click_fd), -1);
452 gtk_tree_path_free(tpath);
456 VFLIST_INFO(vf, click_fd) = NULL;
459 vf->popup = vf_pop_menu(vf);
460 gtk_menu_popup(GTK_MENU(vf->popup), NULL, NULL, vflist_menu_position_cb, vf, 0, GDK_CURRENT_TIME);
465 gint vflist_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
471 GtkTreeViewColumn *column;
473 vf->clicked_mark = 0;
475 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), bevent->x, bevent->y,
476 &tpath, &column, NULL, NULL))
479 gint col_idx = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(column), "column_store_idx"));
481 if (bevent->button == MOUSE_BUTTON_LEFT &&
482 col_idx >= FILE_COLUMN_MARKS && col_idx <= FILE_COLUMN_MARKS_LAST)
485 if (col_idx >= FILE_COLUMN_MARKS && col_idx <= FILE_COLUMN_MARKS_LAST)
486 vf->clicked_mark = 1 + (col_idx - FILE_COLUMN_MARKS);
488 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
490 gtk_tree_model_get_iter(store, &iter, tpath);
491 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
493 gtk_tree_view_set_cursor(GTK_TREE_VIEW(widget), tpath, NULL, FALSE);
495 gtk_tree_path_free(tpath);
498 VFLIST_INFO(vf, click_fd) = fd;
500 if (bevent->button == MOUSE_BUTTON_RIGHT)
502 vf->popup = vf_pop_menu(vf);
503 gtk_menu_popup(GTK_MENU(vf->popup), NULL, NULL, NULL, NULL,
504 bevent->button, bevent->time);
508 if (!fd) return FALSE;
510 if (bevent->button == MOUSE_BUTTON_MIDDLE)
512 if (!vflist_row_is_selected(vf, fd))
514 vflist_color_set(vf, fd, TRUE);
520 if (bevent->button == MOUSE_BUTTON_LEFT && bevent->type == GDK_BUTTON_PRESS &&
521 !(bevent->state & GDK_SHIFT_MASK ) &&
522 !(bevent->state & GDK_CONTROL_MASK ) &&
523 vflist_row_is_selected(vf, fd))
525 GtkTreeSelection *selection;
527 gtk_widget_grab_focus(widget);
530 /* returning FALSE and further processing of the event is needed for
531 correct operation of the expander, to show the sidecar files.
532 It however resets the selection of multiple files. With this condition
533 it should work for both cases */
534 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
535 return (gtk_tree_selection_count_selected_rows(selection) > 1);
539 if (bevent->button == MOUSE_BUTTON_LEFT && bevent->type == GDK_2BUTTON_PRESS)
541 if (vf->layout) layout_image_full_screen_start(vf->layout);
548 gint vflist_release_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
555 if (bevent->button == MOUSE_BUTTON_MIDDLE)
557 vflist_color_set(vf, VFLIST_INFO(vf, click_fd), FALSE);
560 if (bevent->button != MOUSE_BUTTON_LEFT && bevent->button != MOUSE_BUTTON_MIDDLE)
565 if ((bevent->x != 0 || bevent->y != 0) &&
566 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), bevent->x, bevent->y,
567 &tpath, NULL, NULL, NULL))
571 store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
572 gtk_tree_model_get_iter(store, &iter, tpath);
573 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
574 gtk_tree_path_free(tpath);
577 if (bevent->button == MOUSE_BUTTON_MIDDLE)
579 if (fd && VFLIST_INFO(vf, click_fd) == fd)
581 GtkTreeSelection *selection;
583 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
584 if (vflist_row_is_selected(vf, fd))
586 gtk_tree_selection_unselect_iter(selection, &iter);
590 gtk_tree_selection_select_iter(selection, &iter);
596 if (fd && VFLIST_INFO(vf, click_fd) == fd &&
597 !(bevent->state & GDK_SHIFT_MASK ) &&
598 !(bevent->state & GDK_CONTROL_MASK ) &&
599 vflist_row_is_selected(vf, fd))
601 GtkTreeSelection *selection;
603 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
604 gtk_tree_selection_unselect_all(selection);
605 gtk_tree_selection_select_iter(selection, &iter);
606 vflist_move_cursor(vf, &iter);
607 // return TRUE;// FIXME - expand
613 static void vflist_select_image(ViewFile *vf, FileData *sel_fd)
615 FileData *read_ahead_fd = NULL;
620 cur_fd = layout_image_get_fd(vf->layout);
621 if (sel_fd == cur_fd) return; /* no change */
623 row = g_list_index(vf->list, sel_fd);
624 // FIXME sidecar data
626 if (sel_fd && options->image.enable_read_ahead && row >= 0)
628 if (row > g_list_index(vf->list, cur_fd) &&
629 (guint) (row + 1) < vf_count(vf, NULL))
631 read_ahead_fd = vf_index_get_data(vf, row + 1);
635 read_ahead_fd = vf_index_get_data(vf, row - 1);
639 layout_image_set_with_ahead(vf->layout, sel_fd, read_ahead_fd);
642 static gint vflist_select_idle_cb(gpointer data)
648 VFLIST_INFO(vf, select_idle_id) = -1;
654 if (VFLIST_INFO(vf, select_fd))
656 vflist_select_image(vf, VFLIST_INFO(vf, select_fd));
657 VFLIST_INFO(vf, select_fd) = NULL;
660 VFLIST_INFO(vf, select_idle_id) = -1;
664 static void vflist_select_idle_cancel(ViewFile *vf)
666 if (VFLIST_INFO(vf, select_idle_id) != -1) g_source_remove(VFLIST_INFO(vf, select_idle_id));
667 VFLIST_INFO(vf, select_idle_id) = -1;
670 static gboolean vflist_select_cb(GtkTreeSelection *selection, GtkTreeModel *store, GtkTreePath *tpath,
671 gboolean path_currently_selected, gpointer data)
676 if (!path_currently_selected &&
677 gtk_tree_model_get_iter(store, &iter, tpath))
679 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &VFLIST_INFO(vf, select_fd), -1);
683 VFLIST_INFO(vf, select_fd) = NULL;
687 VFLIST_INFO(vf, select_idle_id) == -1)
689 VFLIST_INFO(vf, select_idle_id) = g_idle_add(vflist_select_idle_cb, vf);
696 *-----------------------------------------------------------------------------
698 *-----------------------------------------------------------------------------
702 static gboolean vflist_dummy_select_cb(GtkTreeSelection *selection, GtkTreeModel *store, GtkTreePath *tpath,
703 gboolean path_currently_selected, gpointer data)
710 static void vflist_setup_iter(ViewFile *vf, GtkTreeStore *store, GtkTreeIter *iter, FileData *fd)
714 gchar *sidecars = NULL;
716 if (fd->sidecar_files)
717 sidecars = file_data_sc_list_to_string(fd);
718 size = text_from_size(fd->size);
720 gtk_tree_store_set(store, iter, FILE_COLUMN_POINTER, fd,
721 FILE_COLUMN_VERSION, fd->version,
722 FILE_COLUMN_THUMB, (VFLIST_INFO(vf, thumbs_enabled)) ? fd->pixbuf : NULL,
723 FILE_COLUMN_NAME, fd->name,
724 FILE_COLUMN_SIDECARS, sidecars,
725 FILE_COLUMN_SIZE, size,
726 FILE_COLUMN_DATE, text_from_time(fd->date),
727 FILE_COLUMN_COLOR, FALSE, -1);
728 for (i = 0; i < FILEDATA_MARKS_SIZE; i++)
729 gtk_tree_store_set(store, iter, FILE_COLUMN_MARKS + i, fd->marks[i], -1);
736 static void vflist_setup_iter_with_sidecars(ViewFile *vf, GtkTreeStore *store, GtkTreeIter *iter, FileData *fd)
742 vflist_setup_iter(vf, store, iter, fd);
745 /* this is almost the same code as in vflist_populate_view
746 maybe it should be made more generic and used in both places */
749 valid = gtk_tree_model_iter_children(GTK_TREE_MODEL(store), &s_iter, iter);
751 work = fd->sidecar_files;
755 FileData *sfd = work->data;
760 FileData *old_sfd = NULL;
764 gtk_tree_model_get(GTK_TREE_MODEL(store), &s_iter, FILE_COLUMN_POINTER, &old_sfd, -1);
772 match = filelist_sort_compare_filedata_full(sfd, old_sfd, SORT_NAME, TRUE);
787 gtk_tree_store_insert_before(store, &new, iter, &s_iter);
791 gtk_tree_store_append(store, &new, iter);
794 vflist_setup_iter(vf, store, &new, sfd);
800 valid = gtk_tree_store_remove(store, &s_iter);
804 vflist_setup_iter(vf, store, &s_iter, sfd);
806 if (valid) valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &s_iter);
816 valid = gtk_tree_store_remove(store, &s_iter);
820 void vflist_sort_set(ViewFile *vf, SortType type, gint ascend)
823 GHashTable *fd_idx_hash = g_hash_table_new(NULL, NULL);
828 if (vf->sort_method == type && vf->sort_ascend == ascend) return;
829 if (!vf->list) return;
835 FileData *fd = work->data;
836 g_hash_table_insert(fd_idx_hash, fd, GINT_TO_POINTER(i));
841 vf->sort_method = type;
842 vf->sort_ascend = ascend;
844 vf->list = filelist_sort(vf->list, vf->sort_method, vf->sort_ascend);
846 new_order = g_malloc(i * sizeof(gint));
852 FileData *fd = work->data;
853 new_order[i] = GPOINTER_TO_INT(g_hash_table_lookup(fd_idx_hash, fd));
858 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
859 gtk_tree_store_reorder(store, NULL, new_order);
862 g_hash_table_destroy(fd_idx_hash);
866 *-----------------------------------------------------------------------------
868 *-----------------------------------------------------------------------------
871 static gint vflist_thumb_next(ViewFile *vf);
873 static void vflist_thumb_status(ViewFile *vf, gdouble val, const gchar *text)
875 if (vf->func_thumb_status)
877 vf->func_thumb_status(vf, val, text, vf->data_thumb_status);
881 static void vflist_thumb_cleanup(ViewFile *vf)
883 vflist_thumb_status(vf, 0.0, NULL);
885 vf->thumbs_count = 0;
886 vf->thumbs_running = FALSE;
888 thumb_loader_free(vf->thumbs_loader);
889 vf->thumbs_loader = NULL;
891 vf->thumbs_filedata = NULL;
894 static void vflist_thumb_stop(ViewFile *vf)
896 if (vf->thumbs_running) vflist_thumb_cleanup(vf);
899 static void vflist_thumb_do(ViewFile *vf, ThumbLoader *tl, FileData *fd)
904 if (!fd || vflist_find_row(vf, fd, &iter) < 0) return;
906 if (fd->pixbuf) g_object_unref(fd->pixbuf);
907 fd->pixbuf = thumb_loader_get_pixbuf(tl, TRUE);
909 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
910 gtk_tree_store_set(store, &iter, FILE_COLUMN_THUMB, fd->pixbuf, -1);
912 vflist_thumb_status(vf, (gdouble)(vf->thumbs_count) / vflist_sidecar_list_count(vf->list), _("Loading thumbs..."));
915 static void vflist_thumb_error_cb(ThumbLoader *tl, gpointer data)
919 if (vf->thumbs_filedata && vf->thumbs_loader == tl)
921 vflist_thumb_do(vf, tl, vf->thumbs_filedata);
924 while (vflist_thumb_next(vf));
927 static void vflist_thumb_done_cb(ThumbLoader *tl, gpointer data)
931 if (vf->thumbs_filedata && vf->thumbs_loader == tl)
933 vflist_thumb_do(vf, tl, vf->thumbs_filedata);
936 while (vflist_thumb_next(vf));
939 static gint vflist_thumb_next(ViewFile *vf)
944 /* first check the visible files */
946 if (GTK_WIDGET_REALIZED(vf->listview) &&
947 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(vf->listview), 0, 0, &tpath, NULL, NULL, NULL))
953 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
954 gtk_tree_model_get_iter(store, &iter, tpath);
955 gtk_tree_path_free(tpath);
957 while (!fd && valid && tree_view_row_get_visibility(GTK_TREE_VIEW(vf->listview), &iter, FALSE) == 0)
959 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
960 if (fd->pixbuf) fd = NULL;
962 valid = gtk_tree_model_iter_next(store, &iter);
966 /* then find first undone */
970 GList *work = vf->list;
973 FileData *fd_p = work->data;
978 GList *work2 = fd_p->sidecar_files;
983 if (!fd_p->pixbuf) fd = fd_p;
994 vflist_thumb_cleanup(vf);
1000 vf->thumbs_filedata = fd;
1002 thumb_loader_free(vf->thumbs_loader);
1004 vf->thumbs_loader = thumb_loader_new(options->thumbnails.max_width, options->thumbnails.max_height);
1005 thumb_loader_set_callbacks(vf->thumbs_loader,
1006 vflist_thumb_done_cb,
1007 vflist_thumb_error_cb,
1011 if (!thumb_loader_start(vf->thumbs_loader, fd->path))
1013 /* set icon to unknown, continue */
1014 DEBUG_1("thumb loader start failed %s", vf->thumbs_loader->path);
1015 vflist_thumb_do(vf, vf->thumbs_loader, fd);
1023 static void vflist_thumb_update(ViewFile *vf)
1025 vflist_thumb_stop(vf);
1026 if (!VFLIST_INFO(vf, thumbs_enabled)) return;
1028 vflist_thumb_status(vf, 0.0, _("Loading thumbs..."));
1029 vf->thumbs_running = TRUE;
1031 while (vflist_thumb_next(vf));
1035 *-----------------------------------------------------------------------------
1037 *-----------------------------------------------------------------------------
1040 FileData *vflist_index_get_data(ViewFile *vf, gint row)
1042 return g_list_nth_data(vf->list, row);
1045 gint vflist_index_by_path(ViewFile *vf, const gchar *path)
1050 if (!path) return -1;
1055 FileData *fd = work->data;
1056 if (strcmp(path, fd->path) == 0) return p;
1065 guint vflist_count(ViewFile *vf, gint64 *bytes)
1075 FileData *fd = work->data;
1083 return g_list_length(vf->list);
1086 GList *vflist_get_list(ViewFile *vf)
1094 FileData *fd = work->data;
1097 list = g_list_prepend(list, file_data_ref(fd));
1100 return g_list_reverse(list);
1104 *-----------------------------------------------------------------------------
1106 *-----------------------------------------------------------------------------
1109 static gint vflist_row_is_selected(ViewFile *vf, FileData *fd)
1111 GtkTreeModel *store;
1112 GtkTreeSelection *selection;
1117 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1118 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1120 while (!found && work)
1122 GtkTreePath *tpath = work->data;
1126 gtk_tree_model_get_iter(store, &iter, tpath);
1127 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd_n, -1);
1128 if (fd_n == fd) found = TRUE;
1131 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1137 gint vflist_index_is_selected(ViewFile *vf, gint row)
1141 fd = vf_index_get_data(vf, row);
1142 return vflist_row_is_selected(vf, fd);
1145 guint vflist_selection_count(ViewFile *vf, gint64 *bytes)
1147 GtkTreeModel *store;
1148 GtkTreeSelection *selection;
1152 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1153 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1163 GtkTreePath *tpath = work->data;
1167 gtk_tree_model_get_iter(store, &iter, tpath);
1168 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
1177 count = g_list_length(slist);
1178 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1184 GList *vflist_selection_get_list(ViewFile *vf)
1186 GtkTreeModel *store;
1187 GtkTreeSelection *selection;
1192 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1193 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1197 GtkTreePath *tpath = work->data;
1201 gtk_tree_model_get_iter(store, &iter, tpath);
1202 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
1204 list = g_list_prepend(list, file_data_ref(fd));
1208 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1211 return g_list_reverse(list);
1214 GList *vflist_selection_get_list_by_index(ViewFile *vf)
1216 GtkTreeModel *store;
1217 GtkTreeSelection *selection;
1222 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1223 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1227 GtkTreePath *tpath = work->data;
1231 gtk_tree_model_get_iter(store, &iter, tpath);
1232 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
1234 list = g_list_prepend(list, GINT_TO_POINTER(g_list_index(vf->list, fd)));
1238 g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
1241 return g_list_reverse(list);
1244 void vflist_select_all(ViewFile *vf)
1246 GtkTreeSelection *selection;
1248 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1249 gtk_tree_selection_select_all(selection);
1251 VFLIST_INFO(vf, select_fd) = NULL;
1254 void vflist_select_none(ViewFile *vf)
1256 GtkTreeSelection *selection;
1258 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1259 gtk_tree_selection_unselect_all(selection);
1262 static gboolean tree_model_iter_prev(GtkTreeModel *store, GtkTreeIter *iter)
1267 tpath = gtk_tree_model_get_path(store, iter);
1268 result = gtk_tree_path_prev(tpath);
1270 gtk_tree_model_get_iter(store, iter, tpath);
1272 gtk_tree_path_free(tpath);
1277 static gboolean tree_model_get_iter_last(GtkTreeModel *store, GtkTreeIter *iter)
1279 if (!gtk_tree_model_get_iter_first(store, iter))
1284 GtkTreeIter next = *iter;
1286 if (gtk_tree_model_iter_next(store, &next))
1295 void vflist_select_invert(ViewFile *vf)
1298 GtkTreeSelection *selection;
1299 GtkTreeModel *store;
1302 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
1303 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1305 /* Backward iteration prevents scrolling to the end of the list,
1306 * it scrolls to the first selected row instead. */
1307 valid = tree_model_get_iter_last(store, &iter);
1311 gint selected = gtk_tree_selection_iter_is_selected(selection, &iter);
1314 gtk_tree_selection_unselect_iter(selection, &iter);
1316 gtk_tree_selection_select_iter(selection, &iter);
1318 valid = tree_model_iter_prev(store, &iter);
1322 void vflist_select_by_fd(ViewFile *vf, FileData *fd)
1326 if (vflist_find_row(vf, fd, &iter) < 0) return;
1328 tree_view_row_make_visible(GTK_TREE_VIEW(vf->listview), &iter, TRUE);
1330 if (!vflist_row_is_selected(vf, fd))
1332 GtkTreeSelection *selection;
1333 GtkTreeModel *store;
1336 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1337 gtk_tree_selection_unselect_all(selection);
1338 gtk_tree_selection_select_iter(selection, &iter);
1339 vflist_move_cursor(vf, &iter);
1341 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
1342 tpath = gtk_tree_model_get_path(store, &iter);
1343 gtk_tree_view_set_cursor(GTK_TREE_VIEW(vf->listview), tpath, NULL, FALSE);
1344 gtk_tree_path_free(tpath);
1348 void vflist_mark_to_selection(ViewFile *vf, gint mark, MarkToSelectionMode mode)
1350 GtkTreeModel *store;
1352 GtkTreeSelection *selection;
1356 g_assert(mark >= 1 && mark <= FILEDATA_MARKS_SIZE);
1358 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
1359 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1361 valid = gtk_tree_model_get_iter_first(store, &iter);
1365 gboolean mark_val, selected;
1366 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, FILE_COLUMN_POINTER, &fd, -1);
1368 mark_val = fd->marks[n];
1369 selected = gtk_tree_selection_iter_is_selected(selection, &iter);
1373 case MTS_MODE_SET: selected = mark_val;
1375 case MTS_MODE_OR: selected = mark_val | selected;
1377 case MTS_MODE_AND: selected = mark_val & selected;
1379 case MTS_MODE_MINUS: selected = !mark_val & selected;
1384 gtk_tree_selection_select_iter(selection, &iter);
1386 gtk_tree_selection_unselect_iter(selection, &iter);
1388 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
1392 void vflist_selection_to_mark(ViewFile *vf, gint mark, SelectionToMarkMode mode)
1394 GtkTreeModel *store;
1395 GtkTreeSelection *selection;
1400 g_assert(mark >= 1 && mark <= FILEDATA_MARKS_SIZE);
1402 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1403 slist = gtk_tree_selection_get_selected_rows(selection, &store);
1407 GtkTreePath *tpath = work->data;
1411 gtk_tree_model_get_iter(store, &iter, tpath);
1412 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
1416 case STM_MODE_SET: fd->marks[n] = 1;
1418 case STM_MODE_RESET: fd->marks[n] = 0;
1420 case STM_MODE_TOGGLE: fd->marks[n] = !fd->marks[n];
1424 file_data_increment_version(fd);
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;
1503 gint old_version = 0;
1507 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
1508 FILE_COLUMN_POINTER, &old_fd,
1509 FILE_COLUMN_VERSION, &old_version,
1518 match = filelist_sort_compare_filedata_full(fd, old_fd, vf->sort_method, vf->sort_ascend);
1520 match = -1; /* probably should not happen*/
1535 gtk_tree_store_insert_before(store, &new, NULL, &iter);
1539 gtk_tree_store_append(store, &new, NULL);
1541 vflist_setup_iter_with_sidecars(vf, store, &new, fd);
1547 valid = gtk_tree_store_remove(store, &iter);
1551 if (old_version != fd->version)
1552 vflist_setup_iter_with_sidecars(vf, store, &iter, fd);
1554 if (valid) valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
1564 valid = gtk_tree_store_remove(store, &iter);
1569 if (gtk_tree_row_reference_valid(visible_row))
1571 tpath = gtk_tree_row_reference_get_path(visible_row);
1572 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(vf->listview), tpath, NULL, TRUE, 0.0, 0.0);
1573 gtk_tree_path_free(tpath);
1575 gtk_tree_row_reference_free(visible_row);
1579 vflist_thumb_update(vf);
1582 gint vflist_refresh(ViewFile *vf)
1587 old_list = vf->list;
1590 DEBUG_1("%s vflist_refresh: read dir", get_exec_time());
1593 ret = filelist_read(vf->path, &vf->list, NULL);
1595 DEBUG_1("%s vflist_refresh: sort", get_exec_time());
1597 vf->list = filelist_sort(vf->list, vf->sort_method, vf->sort_ascend);
1599 DEBUG_1("%s vflist_refresh: populate view", get_exec_time());
1601 vflist_populate_view(vf);
1603 filelist_free(old_list);
1604 DEBUG_1("%s vflist_refresh: done", get_exec_time());
1609 /* this overrides the low default of a GtkCellRenderer from 100 to CELL_HEIGHT_OVERRIDE, something sane for our purposes */
1611 #define CELL_HEIGHT_OVERRIDE 512
1613 static void cell_renderer_height_override(GtkCellRenderer *renderer)
1617 spec = g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(renderer)), "height");
1618 if (spec && G_IS_PARAM_SPEC_INT(spec))
1620 GParamSpecInt *spec_int;
1622 spec_int = G_PARAM_SPEC_INT(spec);
1623 if (spec_int->maximum < CELL_HEIGHT_OVERRIDE) spec_int->maximum = CELL_HEIGHT_OVERRIDE;
1627 static GdkColor *vflist_listview_color_shifted(GtkWidget *widget)
1629 static GdkColor color;
1630 static GtkWidget *done = NULL;
1636 style = gtk_widget_get_style(widget);
1637 memcpy(&color, &style->base[GTK_STATE_NORMAL], sizeof(color));
1638 shift_color(&color, -1, 0);
1645 static void vflist_listview_color_cb(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1646 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1648 ViewFile *vf = data;
1651 gtk_tree_model_get(tree_model, iter, FILE_COLUMN_COLOR, &set, -1);
1652 g_object_set(G_OBJECT(cell),
1653 "cell-background-gdk", vflist_listview_color_shifted(vf->listview),
1654 "cell-background-set", set, NULL);
1657 static void vflist_listview_add_column(ViewFile *vf, gint n, const gchar *title, gint image, gint right_justify, gint expand)
1659 GtkTreeViewColumn *column;
1660 GtkCellRenderer *renderer;
1662 column = gtk_tree_view_column_new();
1663 gtk_tree_view_column_set_title(column, title);
1664 gtk_tree_view_column_set_min_width(column, 4);
1668 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_GROW_ONLY);
1669 renderer = gtk_cell_renderer_text_new();
1672 g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
1674 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1675 gtk_tree_view_column_add_attribute(column, renderer, "text", n);
1677 gtk_tree_view_column_set_expand(column, TRUE);
1681 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
1682 renderer = gtk_cell_renderer_pixbuf_new();
1683 cell_renderer_height_override(renderer);
1684 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1685 gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", n);
1688 gtk_tree_view_column_set_cell_data_func(column, renderer, vflist_listview_color_cb, vf, NULL);
1689 g_object_set_data(G_OBJECT(column), "column_store_idx", GUINT_TO_POINTER(n));
1690 g_object_set_data(G_OBJECT(renderer), "column_store_idx", GUINT_TO_POINTER(n));
1692 gtk_tree_view_append_column(GTK_TREE_VIEW(vf->listview), column);
1695 static void vflist_listview_mark_toggled(GtkCellRendererToggle *cell, gchar *path_str, GtkTreeStore *store)
1697 GtkTreePath *path = gtk_tree_path_new_from_string(path_str);
1703 if (!path || !gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, path))
1706 col_idx = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cell), "column_store_idx"));
1708 g_assert(col_idx >= FILE_COLUMN_MARKS && col_idx <= FILE_COLUMN_MARKS_LAST);
1710 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, FILE_COLUMN_POINTER, &fd, col_idx, &mark, -1);
1712 fd->marks[col_idx - FILE_COLUMN_MARKS] = mark;
1713 file_data_increment_version(fd);
1715 gtk_tree_store_set(store, &iter, col_idx, mark, -1);
1716 gtk_tree_path_free(path);
1719 static void vflist_listview_add_column_toggle(ViewFile *vf, gint n, const gchar *title)
1721 GtkTreeViewColumn *column;
1722 GtkCellRenderer *renderer;
1723 GtkTreeStore *store;
1726 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
1728 renderer = gtk_cell_renderer_toggle_new();
1729 column = gtk_tree_view_column_new_with_attributes(title, renderer, "active", n, NULL);
1731 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
1732 g_object_set_data(G_OBJECT(column), "column_store_idx", GUINT_TO_POINTER(n));
1733 g_object_set_data(G_OBJECT(renderer), "column_store_idx", GUINT_TO_POINTER(n));
1735 index = gtk_tree_view_append_column(GTK_TREE_VIEW(vf->listview), column);
1736 gtk_tree_view_column_set_fixed_width(column, 16);
1737 gtk_tree_view_column_set_visible(column, vf->marks_enabled);
1740 g_signal_connect(G_OBJECT(renderer), "toggled", G_CALLBACK(vflist_listview_mark_toggled), store);
1744 *-----------------------------------------------------------------------------
1746 *-----------------------------------------------------------------------------
1749 gint vflist_set_path(ViewFile *vf, const gchar *path)
1751 GtkTreeStore *store;
1753 if (!path) return FALSE;
1754 if (vf->path && strcmp(path, vf->path) == 0) return TRUE;
1757 vf->path = g_strdup(path);
1759 /* force complete reload */
1760 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
1761 gtk_tree_store_clear(store);
1763 filelist_free(vf->list);
1766 return vf_refresh(vf);
1769 void vflist_destroy_cb(GtkWidget *widget, gpointer data)
1771 ViewFile *vf = data;
1773 vflist_select_idle_cancel(vf);
1774 vflist_thumb_stop(vf);
1776 filelist_free(vf->list);
1779 ViewFile *vflist_new(ViewFile *vf, const gchar *path)
1781 GtkTreeStore *store;
1782 GtkTreeSelection *selection;
1784 GType flist_types[FILE_COLUMN_COUNT];
1787 vf->info = g_new0(ViewFileInfoList, 1);
1789 VFLIST_INFO(vf, click_fd) = NULL;
1790 VFLIST_INFO(vf, select_fd) = NULL;
1791 VFLIST_INFO(vf, thumbs_enabled) = FALSE;
1793 VFLIST_INFO(vf, select_idle_id) = -1;
1795 flist_types[FILE_COLUMN_POINTER] = G_TYPE_POINTER;
1796 flist_types[FILE_COLUMN_VERSION] = G_TYPE_INT;
1797 flist_types[FILE_COLUMN_THUMB] = GDK_TYPE_PIXBUF;
1798 flist_types[FILE_COLUMN_NAME] = G_TYPE_STRING;
1799 flist_types[FILE_COLUMN_SIDECARS] = G_TYPE_STRING;
1800 flist_types[FILE_COLUMN_SIZE] = G_TYPE_STRING;
1801 flist_types[FILE_COLUMN_DATE] = G_TYPE_STRING;
1802 flist_types[FILE_COLUMN_COLOR] = G_TYPE_BOOLEAN;
1803 for (i = FILE_COLUMN_MARKS; i < FILE_COLUMN_MARKS + FILEDATA_MARKS_SIZE; i++)
1804 flist_types[i] = G_TYPE_BOOLEAN;
1806 store = gtk_tree_store_newv(FILE_COLUMN_COUNT, flist_types);
1808 vf->listview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
1809 g_object_unref(store);
1811 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
1812 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
1813 gtk_tree_selection_set_select_function(selection, vflist_select_cb, vf, NULL);
1815 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(vf->listview), FALSE);
1816 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(vf->listview), FALSE);
1818 vflist_listview_add_column(vf, FILE_COLUMN_THUMB, "", TRUE, FALSE, FALSE);
1820 for (i = 0; i < FILEDATA_MARKS_SIZE; i++)
1821 vflist_listview_add_column_toggle(vf, i + FILE_COLUMN_MARKS, "");
1823 vflist_listview_add_column(vf, FILE_COLUMN_NAME, _("Name"), FALSE, FALSE, FALSE);
1824 vflist_listview_add_column(vf, FILE_COLUMN_SIDECARS, _("SC"), FALSE, FALSE, FALSE);
1826 vflist_listview_add_column(vf, FILE_COLUMN_SIZE, _("Size"), FALSE, TRUE, FALSE);
1827 vflist_listview_add_column(vf, FILE_COLUMN_DATE, _("Date"), FALSE, TRUE, FALSE);
1832 void vflist_thumb_set(ViewFile *vf, gint enable)
1834 if (VFLIST_INFO(vf, thumbs_enabled) == enable) return;
1836 VFLIST_INFO(vf, thumbs_enabled) = enable;
1837 if (vf->layout) vf_refresh(vf);
1840 void vflist_marks_set(ViewFile *vf, gint enable)
1842 GList *columns, *work;
1844 if (vf->marks_enabled == enable) return;
1846 vf->marks_enabled = enable;
1848 columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(vf->listview));
1853 GtkTreeViewColumn *column = work->data;
1854 gint col_idx = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(column), "column_store_idx"));
1857 if (col_idx <= FILE_COLUMN_MARKS_LAST && col_idx >= FILE_COLUMN_MARKS)
1858 gtk_tree_view_column_set_visible(column, enable);
1861 g_list_free(columns);
1866 *-----------------------------------------------------------------------------
1867 * maintenance (for rename, move, remove)
1868 *-----------------------------------------------------------------------------
1871 static gint vflist_maint_find_closest(ViewFile *vf, gint row, gint count, GList *ignore_list)
1881 gint f = vf_index_by_path(vf, work->data);
1882 if (f >= 0) list = g_list_prepend(list, GINT_TO_POINTER(f));
1892 gpointer p = work->data;
1894 if (row == GPOINTER_TO_INT(p))
1899 if (rev == GPOINTER_TO_INT(p))
1904 if (!c) list = g_list_remove(list, p);
1912 if (row > count - 1)
1925 gint vflist_maint_renamed(ViewFile *vf, FileData *fd)
1931 DEBUG_1("%s vflist_maint_renamed: start", get_exec_time());
1933 if (g_list_index(vf->list, fd) < 0) return FALSE;
1935 source_base = remove_level_from_path(fd->change->source);
1936 dest_base = remove_level_from_path(fd->change->dest);
1939 if (strcmp(source_base, dest_base) == 0)
1941 GtkTreeStore *store;
1943 GtkTreeIter position;
1947 old_row = g_list_index(vf->list, fd);
1949 vf->list = g_list_remove(vf->list, fd);
1951 vf->list = filelist_insert_sort(vf->list, fd, vf->sort_method, vf->sort_ascend);
1952 n = g_list_index(vf->list, fd);
1954 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
1955 if (vflist_find_row(vf, fd, &iter) >= 0 &&
1956 gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &position, NULL, n))
1960 gtk_tree_store_move_before(store, &iter, &position);
1964 gtk_tree_store_move_after(store, &iter, &position);
1967 gtk_tree_store_set(store, &iter, FILE_COLUMN_NAME, fd->name, -1);
1973 ret = vflist_maint_removed(vf, fd, NULL);
1976 g_free(source_base);
1979 DEBUG_1("%s vflist_maint_renamed: done", get_exec_time());
1984 gint vflist_maint_removed(ViewFile *vf, FileData *fd, GList *ignore_list)
1991 DEBUG_1("%s vflist_maint_removed: start", get_exec_time());
1993 row = g_list_index(vf->list, fd);
1994 if (row < 0) return FALSE;
1996 if (vflist_index_is_selected(vf, row) &&
1997 layout_image_get_collection(vf->layout, NULL) == NULL)
2001 n = vf_count(vf, NULL);
2004 new_row = vflist_maint_find_closest(vf, row, n, ignore_list);
2005 DEBUG_1("row = %d, closest is %d", row, new_row);
2021 fd = vf_index_get_data(vf, new_row);
2022 if (vflist_find_row(vf, fd, &iter) >= 0)
2024 GtkTreeSelection *selection;
2026 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
2027 gtk_tree_selection_select_iter(selection, &iter);
2028 vflist_move_cursor(vf, &iter);
2033 fd = vf_index_get_data(vf, row);
2034 if (vflist_find_row(vf, fd, &iter) >= 0)
2036 GtkTreeStore *store;
2037 store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview)));
2038 gtk_tree_store_remove(store, &iter);
2040 list = g_list_nth(vf->list, row);
2043 /* thumbnail loader check */
2044 if (fd == vf->thumbs_filedata) vf->thumbs_filedata = NULL;
2045 if (vf->thumbs_count > 0) vf->thumbs_count--;
2047 vf->list = g_list_remove(vf->list, fd);
2048 file_data_unref(fd);
2052 DEBUG_1("%s vflist_maint_removed: done", get_exec_time());
2057 gint vflist_maint_moved(ViewFile *vf, FileData *fd, GList *ignore_list)
2062 if (!fd->change->source || !vf->path) return FALSE;
2064 buf = remove_level_from_path(fd->change->source);
2066 if (strcmp(buf, vf->path) == 0)
2068 ret = vflist_maint_removed(vf, fd, ignore_list);