Start building a class to enable clustering of files.
authorOmari Stephens <xsdg@google.com>
Fri, 7 Jul 2017 21:44:05 +0000 (21:44 +0000)
committerOmari Stephens <xsdg@google.com>
Mon, 10 Jul 2017 08:00:55 +0000 (08:00 +0000)
src/Makefile.am
src/filecluster.c [new file with mode: 0644]
src/filecluster.h [new file with mode: 0644]

index f01fb19..f4f2f4c 100644 (file)
@@ -144,6 +144,8 @@ geeqie_SOURCES = \
        exiv2.cc        \
        filecache.c     \
        filecache.h     \
        exiv2.cc        \
        filecache.c     \
        filecache.h     \
+       filecluster.c   \
+       filecluster.h   \
        filedata.c      \
        filedata.h      \
        filefilter.c    \
        filedata.c      \
        filedata.h      \
        filefilter.c    \
diff --git a/src/filecluster.c b/src/filecluster.c
new file mode 100644 (file)
index 0000000..f2fbc3e
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2008 - 2016 The Geeqie Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "filecluster.h"
+
+static gboolean check_list_contains_sublist(GList *haystack, GList *needle)
+{
+       // TODO(xsdg): Optimize this!  Sort, then scan?
+       GList *h_work, *n_work;
+       for (n_work = needle; n_work; n_work = n_work->next)
+       {
+               gboolean found = FALSE;
+               for (h_work = haystack; h_work; h_work = h_work->next)
+               {
+                       if (n_work == h_work)
+                               {
+                               found = TRUE;
+                               break;
+                               }
+               }
+
+               if (!found) return FALSE;
+       }
+
+       return TRUE;
+}
+
+FileClusterList *fileclusterlist_new()
+{
+       FileClusterList *fcl = g_new0(FileClusterList, 1);
+       fcl->clusters = g_hash_table_new(&g_direct_hash, &g_direct_equal);
+}
+
+FileCluster *filecluster_new()
+{
+       FileCluster *fc = g_new0(FileCluster, 1);
+}
+
+void fileclusterlist_free(FileClusterList *fcl)
+{
+       if (fcl->fd_list) g_list_free_full(fcl->fd_list, (GDestroyNotify)&filecluster_free);
+       g_hash_table_destroy(fcl->clusters);
+       g_free(fcl);
+}
+
+void filecluster_free(FileCluster *fc)
+{
+       g_free(fc);
+}
+
+FileCluster *fileclusterlist_create_cluster(FileClusterList *fcl, GList *fd_items)
+{
+       GList *work;
+       if (!fd_items) return NULL;
+       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;
+       }
+
+       FileCluster *new_fc = filecluster_new();
+       new_fc->items = g_list_copy(fd_items);
+       new_fc->head = new_fc->items;
+
+       return new_fc;
+}
+
+gboolean fileclusterlist_has_head(FileClusterList *fcl, FileData *fd)
+{
+       FileCluster *fc = g_hash_table_lookup(fcl->clusters, fd);
+       if (!fc) return FALSE;
+       return fc->head->data == fd;
+}
+
+gboolean fileclusterlist_has_child(FileClusterList *fcl, FileData *fd)
+{
+       FileCluster *fc = g_hash_table_lookup(fcl->clusters, fd);
+       if (!fc) return FALSE;
+       return fc->head->data != fd;
+}
diff --git a/src/filecluster.h b/src/filecluster.h
new file mode 100644 (file)
index 0000000..07d3be1
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2008 - 2016 The Geeqie Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef FILECLUSTER_H
+#define FILECLUSTER_H
+
+#include "main.h"
+
+typedef struct _FileCluster FileCluster;
+typedef struct _FileClusterList FileClusterList;
+
+// A FileCluster is a GList with HashTable access to each node (to perform contains() checks quickly).
+struct _FileCluster
+{
+       GList *head;
+       GList *items;
+};
+
+struct _FileClusterList
+{
+       // All of the elements in the list, regardless of whether they're part of a cluster or not.
+       GList *fd_list;
+
+       // A map from any clustered FileData to the FileCluster object that describes the cluster.
+       GHashTable *clusters;
+};
+
+FileClusterList *fileclusterlist_new();
+FileCluster *filecluster_new();  // internal?
+void fileclusterlist_free(FileClusterList *fcl);
+void filecluster_free(FileCluster *fc);
+
+// Creates a cluster with items that must already be in the cluster list.  Will fail (and make no
+// changes) if any of the specified items isn't in the list, or if any of the items is already
+// part of a different cluster.
+FileCluster *fileclusterlist_create_cluster(FileClusterList *fcl, GList *fd_items);
+
+gboolean fileclusterlist_has_head(FileClusterList *fcl, FileData *fd);
+gboolean fileclusterlist_has_child(FileClusterList *fcl, FileData *fd);
+
+
+#endif  // FILECLUSTER_H