From 6701147fd21f1c30f28132da89a5bb4d3009e15a Mon Sep 17 00:00:00 2001 From: Omari Stephens Date: Sat, 8 Jul 2017 21:56:55 +0000 Subject: [PATCH] Use FileCluster from view_file_icon to enable clustering of images. (Also adds minimal support to view_file_list, but it's not usable yet) --- src/filecluster.c | 46 +++++++++++++++++++++++++++++++--- src/filecluster.h | 1 + src/view_file/view_file.c | 3 +++ src/view_file/view_file_icon.c | 32 ++++++++++++++++++++++- src/view_file/view_file_list.c | 2 ++ 5 files changed, 79 insertions(+), 5 deletions(-) diff --git a/src/filecluster.c b/src/filecluster.c index f2fbc3ee..a8cb22dd 100644 --- a/src/filecluster.c +++ b/src/filecluster.c @@ -18,6 +18,8 @@ #include "filecluster.h" +#include "filedata.h" + static gboolean check_list_contains_sublist(GList *haystack, GList *needle) { // TODO(xsdg): Optimize this! Sort, then scan? @@ -66,18 +68,32 @@ void filecluster_free(FileCluster *fc) FileCluster *fileclusterlist_create_cluster(FileClusterList *fcl, GList *fd_items) { GList *work; + + // Check preconditions. if (!fd_items) return NULL; - if (!check_list_contains_sublist(fcl->fd_list, fd_items)) return NULL; + // TODO(xsdg): Is this actually necessary? + // if (!check_list_contains_sublist(fcl->fd_list, fd_items)) return NULL; for (work = fd_items; work; work = work->next) - { + { FileData *fd = work->data; - if (g_hash_table_contains(fcl->clusters, fd)) return NULL; - } + if (g_hash_table_contains(fcl->clusters, fd)) + { + // TODO(xsdg): Show this warning in the UI. + g_warning("Tried to create a cluster with a file that is already clustered."); + return NULL; + } + } FileCluster *new_fc = filecluster_new(); new_fc->items = g_list_copy(fd_items); new_fc->head = new_fc->items; + for (GList *item = new_fc->items; item; item = item->next) + { + FileData *fd = item->data; + g_hash_table_insert(fcl->clusters, fd, new_fc); + } + return new_fc; } @@ -94,3 +110,25 @@ gboolean fileclusterlist_has_child(FileClusterList *fcl, FileData *fd) if (!fc) return FALSE; return fc->head->data != fd; } + +GList *filecluster_remove_children_from_list(FileClusterList *fcl, GList *list) +{ + GList *work = list; + + while (work) + { + FileData *fd = work->data; + GList *link = work; + // Advance early in case link needs to be removed/freed. + work = work->next; + + if (fileclusterlist_has_child(fcl, fd)) + { + list = g_list_remove_link(list, link); + file_data_unref(fd); + g_list_free(link); + } + } + + return list; +} diff --git a/src/filecluster.h b/src/filecluster.h index 3b002dc1..3b2956d5 100644 --- a/src/filecluster.h +++ b/src/filecluster.h @@ -34,5 +34,6 @@ FileCluster *fileclusterlist_create_cluster(FileClusterList *fcl, GList *fd_item gboolean fileclusterlist_has_head(FileClusterList *fcl, FileData *fd); gboolean fileclusterlist_has_child(FileClusterList *fcl, FileData *fd); +GList *filecluster_remove_children_from_list(FileClusterList *fcl, GList *list); #endif // FILECLUSTER_H diff --git a/src/view_file/view_file.c b/src/view_file/view_file.c index c9dbdef8..97fafae1 100644 --- a/src/view_file/view_file.c +++ b/src/view_file/view_file.c @@ -25,6 +25,7 @@ #include "collect.h" #include "collect-table.h" #include "editors.h" +#include "filecluster.h" #include "layout.h" #include "menu.h" #include "thumb.h" @@ -673,6 +674,7 @@ static void vf_destroy_cb(GtkWidget *widget, gpointer data) gtk_widget_destroy(vf->popup); } + fileclusterlist_free(vf->cluster_list); file_data_unref(vf->dir_fd); g_free(vf->info); g_free(vf); @@ -729,6 +731,7 @@ ViewFile *vf_new(FileViewType type, FileData *dir_fd) gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(vf->scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + vf->cluster_list = fileclusterlist_new(); vf->filter = vf_marks_filter_init(vf); vf->widget = gtk_vbox_new(FALSE, 0); diff --git a/src/view_file/view_file_icon.c b/src/view_file/view_file_icon.c index b60074c5..e3ab038e 100644 --- a/src/view_file/view_file_icon.c +++ b/src/view_file/view_file_icon.c @@ -30,6 +30,7 @@ #include "dnd.h" #include "editors.h" #include "img-view.h" +#include "filecluster.h" #include "filedata.h" #include "layout.h" #include "layout_image.h" @@ -1250,6 +1251,33 @@ gboolean vficon_press_key_cb(GtkWidget *widget, GdkEventKey *event, gpointer dat vf->popup = vf_pop_menu(vf); gtk_menu_popup(GTK_MENU(vf->popup), NULL, NULL, vfi_menu_position_cb, vf, 0, GDK_CURRENT_TIME); break; + case GDK_KEY_Insert: + // DO NOT SUBMIT + // TODO(xsdg): make an actual UX for this. + g_warning("Starting a cluster!"); + fd = vficon_find_data(vf, VFICON(vf)->focus_row, VFICON(vf)->focus_column, NULL); + if (fd) + { + // Make a cluster out of the entire selection + if (VFICON(vf)->selection && VFICON(vf)->selection->next) + { + // At least two items selected; go for it. + g_warning("Had requisite number of selection items; going for it!"); + fileclusterlist_create_cluster(vf->cluster_list, VFICON(vf)->selection); + } + else + { + if (VFICON(vf)->selection) + { + g_warning("Only one item selected; need at least two."); + } + else + { + g_warning("No items selected; need at least two."); + } + } + } + break; default: stop_signal = FALSE; break; @@ -1796,9 +1824,11 @@ static gboolean vficon_refresh_real(ViewFile *vf, gboolean keep_position) { ret = filelist_read(vf->dir_fd, &new_filelist, NULL); new_filelist = file_data_filter_marks_list(new_filelist, vf_marks_get_filter(vf)); + new_filelist = filecluster_remove_children_from_list(vf->cluster_list, new_filelist); } - vf->list = filelist_sort(vf->list, vf->sort_method, vf->sort_ascend); /* the list might not be sorted if there were renames */ + /* the list might not be sorted if there were renames */ + vf->list = filelist_sort(vf->list, vf->sort_method, vf->sort_ascend); new_filelist = filelist_sort(new_filelist, vf->sort_method, vf->sort_ascend); if (VFICON(vf)->selection) diff --git a/src/view_file/view_file_list.c b/src/view_file/view_file_list.c index b56a025c..15a71c55 100644 --- a/src/view_file/view_file_list.c +++ b/src/view_file/view_file_list.c @@ -27,6 +27,7 @@ #include "dnd.h" #include "editors.h" #include "img-view.h" +#include "filecluster.h" #include "layout.h" #include "layout_image.h" #include "menu.h" @@ -1668,6 +1669,7 @@ gboolean vflist_refresh(ViewFile *vf) } vf->list = file_data_filter_marks_list(vf->list, vf_marks_get_filter(vf)); + vf->list = filecluster_remove_children_from_list(vf->cluster_list, vf->list); file_data_register_notify_func(vf_notify_cb, vf, NOTIFY_PRIORITY_MEDIUM); DEBUG_1("%s vflist_refresh: sort", get_exec_time()); -- 2.20.1