#include "filecluster.h"
+#include "filedata.h"
+
static gboolean check_list_contains_sublist(GList *haystack, GList *needle)
{
// TODO(xsdg): Optimize this! Sort, then scan?
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;
}
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;
+}
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
#include "collect.h"
#include "collect-table.h"
#include "editors.h"
+#include "filecluster.h"
#include "layout.h"
#include "menu.h"
#include "thumb.h"
gtk_widget_destroy(vf->popup);
}
+ fileclusterlist_free(vf->cluster_list);
file_data_unref(vf->dir_fd);
g_free(vf->info);
g_free(vf);
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);
#include "dnd.h"
#include "editors.h"
#include "img-view.h"
+#include "filecluster.h"
#include "filedata.h"
#include "layout.h"
#include "layout_image.h"
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;
{
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)
#include "dnd.h"
#include "editors.h"
#include "img-view.h"
+#include "filecluster.h"
#include "layout.h"
#include "layout_image.h"
#include "menu.h"
}
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());