Uses custom hash/equals functions so that we can actually fetch equivalent FileDatas...
[geeqie.git] / src / view_file / view_file_icon.c
index e8f5c56..c2a423b 100644 (file)
@@ -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"
@@ -80,14 +81,14 @@ GList *vficon_selection_get_one(ViewFile *vf, FileData *fd)
 
 GList *vficon_pop_menu_file_list(ViewFile *vf)
 {
-       if (!VFICON(vf)->click_id) return NULL;
+       if (!VFICON(vf)->click_fd) return NULL;
 
-       if (VFICON(vf)->click_id->selected & SELECTION_SELECTED)
+       if (VFICON(vf)->click_fd->selected & SELECTION_SELECTED)
                {
                return vf_selection_get_list(vf);
                }
 
-       return vficon_selection_get_one(vf, VFICON(vf)->click_id->fd);
+       return vficon_selection_get_one(vf, VFICON(vf)->click_fd);
 }
 
 void vficon_pop_menu_view_cb(GtkWidget *widget, gpointer data)
@@ -883,8 +884,7 @@ GList *vficon_selection_get_list_by_index(ViewFile *vf)
 void vficon_select_by_fd(ViewFile *vf, FileData *fd)
 {
        if (!fd) return;
-       FileData *found_fd = g_list_find(vf->list, fd);
-       if (!found_fd) return;
+       if (!g_list_find(vf->list, fd)) return;
 
        if (!(fd->selected & SELECTION_SELECTED))
                {
@@ -1251,6 +1251,53 @@ 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)
+                                       {
+                                       FileCluster *fc;
+                                       // At least two items selected; go for it.
+                                       g_warning("Had requisite number of selection items; going for it!");
+                                       fc = fileclusterlist_create_cluster(vf->cluster_list, VFICON(vf)->selection);
+                                       if (fc)
+                                               {
+                                               // TODO(xsdg): set CLUSTER_CHILD
+                                               vficon_selection_add(vf, VFICON(vf)->selection->data, SELECTION_CLUSTER_HEAD, NULL);
+                                               vf_refresh(vf);
+                                               }
+                                       }
+                               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;
+               case GDK_KEY_F2:
+                       g_warning("Flipping show_children!");
+                       fd = vficon_find_data(vf, VFICON(vf)->focus_row, VFICON(vf)->focus_column, NULL);
+                       if (fd)
+                               {
+                               FileCluster *fc = g_hash_table_lookup(vf->cluster_list->clusters, fd);
+                               if (fc)
+                                       {
+                                       filecluster_toggle_show_children(fc);
+                                       vf_refresh(vf);
+                                       }
+                               }
+                       break;
                default:
                        stop_signal = FALSE;
                        break;
@@ -1271,13 +1318,13 @@ gboolean vficon_press_key_cb(GtkWidget *widget, GdkEventKey *event, gpointer dat
                                {
                                if (!options->collections.rectangular_selection)
                                        {
-                                       vficon_select_region_util(vf, old_id, new_fd, FALSE);
+                                       vficon_select_region_util(vf, old_fd, new_fd, FALSE);
                                        }
                                else
                                        {
                                        vficon_select_region_util(vf, VFICON(vf)->click_fd, old_fd, FALSE);
                                        }
-                               vficon_select_region_util(vf, VFICON(vf)->click_fd, new_id, TRUE);
+                               vficon_select_region_util(vf, VFICON(vf)->click_fd, new_fd, TRUE);
                                vficon_send_layout_select(vf, new_fd);
                                }
                        else if (event->state & GDK_CONTROL_MASK)
@@ -1695,7 +1742,8 @@ void vficon_set_thumb_fd(ViewFile *vf, FileData *fd)
        GtkTreeIter iter;
        GList *list;
 
-       if (!vficon_find_iter(vf, g_list_find(vf->list, fd), &iter, NULL)) return;
+       if (!g_list_find(vf->list, fd)) return;
+       if (!vficon_find_iter(vf, fd, &iter, NULL)) return;
 
        store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
 
@@ -1703,14 +1751,12 @@ void vficon_set_thumb_fd(ViewFile *vf, FileData *fd)
        gtk_list_store_set(GTK_LIST_STORE(store), &iter, FILE_COLUMN_POINTER, list, -1);
 }
 
-// TOOD(xsdg): This could be broken
+/* Returns the next fd without a loaded pixbuf, so the thumb-loader can load the pixbuf for it. */
 FileData *vficon_thumb_next_fd(ViewFile *vf)
 {
        GtkTreePath *tpath;
-       FileData *fd = NULL;
-
-       /* first check the visible files */
 
+       /* First see if there are visible files that don't have a loaded thumb... */
        if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(vf->listview), 0, 0, &tpath, NULL, NULL, NULL))
                {
                GtkTreeModel *store;
@@ -1722,74 +1768,42 @@ FileData *vficon_thumb_next_fd(ViewFile *vf)
                gtk_tree_path_free(tpath);
                tpath = NULL;
 
-               while (!fd && valid && tree_view_row_get_visibility(GTK_TREE_VIEW(vf->listview), &iter, FALSE) == 0)
+               while (valid && tree_view_row_get_visibility(GTK_TREE_VIEW(vf->listview), &iter, FALSE) == 0)
                        {
                        GList *list;
-
                        gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &list, -1);
 
-                       while (!fd && list)
+                       // TODO(xsdg): for loop here.
+                       for (; list; list = list->next)
                                {
-                               FileData *new_fd = list->data;
-                               if (new_fd && !fd->thumb_pixbuf) fd = new_fd;
-                               list = list->next;
+                               FileData *fd = list->data;
+                               if (fd && !fd->thumb_pixbuf) return fd;
                                }
 
                        valid = gtk_tree_model_iter_next(store, &iter);
                        }
                }
 
-       /* then find first undone */
-
-       if (!fd)
+       /* Then iterate through the entire list to load all of them. */
+       GList *work;
+       for (work = vf->list; work; work = work->next)
                {
-               GList *work = vf->list;
-               while (work && !fd)
-                       {
-                       FileData *fd_p = work->data;
-                       work = work->next;
+               FileData *fd = work->data;
 
-                       // Note: This implementation differs from view_file_list.c because sidecar files are not
-                       // distinct list elements here, as they are in the list view.
-                       if (!fd_p->thumb_pixbuf) fd = fd_p;
-                       }
+               // Note: This implementation differs from view_file_list.c because sidecar files are not
+               // distinct list elements here, as they are in the list view.
+               if (!fd->thumb_pixbuf) return fd;
                }
 
-       return fd;
-}
-
-void vficon_thumb_reset_all(ViewFile *vf)
-{
-       GList *work = vf->list;
-
-       while (work)
-               {
-               FileData *fd = work->data;
-               if (fd->thumb_pixbuf)
-                       {
-                       g_object_unref(fd->thumb_pixbuf);
-                       fd->thumb_pixbuf = NULL;
-                       }
-               work = work->next;
-               }
+       return NULL;
 }
 
-
 /*
  *-----------------------------------------------------------------------------
  * row stuff
  *-----------------------------------------------------------------------------
  */
 
-FileData *vficon_index_get_data(ViewFile *vf, gint row)
-{
-       FileData *fd;
-
-       fd = g_list_nth_data(vf->list, row);
-       return fd ? fd : NULL;
-}
-
-
 gint vficon_index_by_fd(ViewFile *vf, FileData *in_fd)
 {
        gint p = 0;
@@ -1809,45 +1823,6 @@ gint vficon_index_by_fd(ViewFile *vf, FileData *in_fd)
        return -1;
 }
 
-guint vficon_count(ViewFile *vf, gint64 *bytes)
-{
-       if (bytes)
-               {
-               gint64 b = 0;
-               GList *work;
-
-               work = vf->list;
-               while (work)
-                       {
-                       FileData *fd = work->data;
-                       work = work->next;
-
-                       b += fd->size;
-                       }
-
-               *bytes = b;
-               }
-
-       return g_list_length(vf->list);
-}
-
-GList *vficon_get_list(ViewFile *vf)
-{
-       GList *list = NULL;
-       GList *work;
-
-       work = vf->list;
-       while (work)
-               {
-               FileData *fd = work->data;
-               work = work->next;
-
-               list = g_list_prepend(list, file_data_ref(fd));
-               }
-
-       return g_list_reverse(list);
-}
-
 /*
  *-----------------------------------------------------------------------------
  *
@@ -1859,9 +1834,9 @@ static gboolean vficon_refresh_real(ViewFile *vf, gboolean keep_position)
        gboolean ret = TRUE;
        GList *work, *new_work;
        FileData *focus_fd;
-       GList *new_filelist = NULL;
        FileData *first_selected = NULL;
-       GList *new_iconlist = NULL;  // TODO(xsdg): figure out what this should be named.
+       GList *new_filelist = NULL;
+       GList *new_fd_list = NULL;
 
        focus_fd = VFICON(vf)->focus_fd;
 
@@ -1869,9 +1844,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 = fileclusterlist_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)
@@ -1882,7 +1859,7 @@ static gboolean vficon_refresh_real(ViewFile *vf, gboolean keep_position)
                VFICON(vf)->selection = NULL;
                }
 
-       /* check for same files from old_list */
+       /* iterate old list and new list, looking for differences */
        work = vf->list;
        new_work = new_filelist;
        while (work || new_work)
@@ -1913,11 +1890,13 @@ static gboolean vficon_refresh_real(ViewFile *vf, gboolean keep_position)
                        }
                else if (work)
                        {
+                       /* old item was deleted */
                        fd = work->data;
                        match = -1;
                        }
-               else /* new_work */
+               else
                        {
+                       /* new item was added */
                        new_fd = new_work->data;
                        match = 1;
                        }
@@ -1943,16 +1922,17 @@ static gboolean vficon_refresh_real(ViewFile *vf, gboolean keep_position)
                                }
                        else
                                {
-                               new_iconlist = g_list_prepend(new_iconlist, fd); /* it is faster to append all new entries together later */
+                               /* it is faster to append all new entries together later */
+                               new_fd_list = g_list_prepend(new_fd_list, new_fd);
                                }
 
                        new_work = new_work->next;
                        }
                }
 
-       if (new_iconlist)
+       if (new_fd_list)
                {
-               vf->list = g_list_concat(vf->list, g_list_reverse(new_iconlist));
+               vf->list = g_list_concat(vf->list, g_list_reverse(new_fd_list));
                }
 
        VFICON(vf)->selection = g_list_reverse(VFICON(vf)->selection);
@@ -2042,6 +2022,21 @@ static void vficon_cell_data_cb(GtkTreeViewColumn *tree_column, GtkCellRenderer
                memcpy(&color_fg, &style->text[state], sizeof(color_fg));
                memcpy(&color_bg, &style->base[state], sizeof(color_bg));
 
+               if (fd->selected & SELECTION_CLUSTER_HEAD)
+                       {
+                       // TODO(xsdg): Cluster coloration should be part of the style.
+                       color_bg.blue = 0x4000;
+                       color_bg.green = 0x4000;
+                       color_bg.red = 0xFFFF;
+                       }
+               else if (fd->selected & SELECTION_CLUSTER_CHILD)
+                       {
+                       // TODO(xsdg): Cluster coloration should be part of the style.
+                       color_bg.blue = 0x8000;
+                       color_bg.green = 0x8000;
+                       color_bg.red = 0xFFFF;
+                       }
+
                if (fd->selected & SELECTION_PRELIGHT)
                        {
                        shift_color(&color_bg, -1, 0);