/*
- * Geeqie
- * (C) 2004 John Ellis
- * Copyright (C) 2008 - 2009 The Geeqie Team
+ * Copyright (C) 2004 John Ellis
+ * Copyright (C) 2008 - 2016 The Geeqie Team
*
* Author: John Ellis
*
- * This software is released under the GNU General Public License (GNU GPL).
- * Please read the included file COPYING for more information.
- * This software comes with no warranty of any kind, use at your own risk!
+ * 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 "main.h"
#include "collect-io.h"
typedef struct _CollectManagerEntry CollectManagerEntry;
static void collection_load_thumb_step(CollectionData *cd);
-static gint collection_save_private(CollectionData *cd, const gchar *path);
+static gboolean collection_save_private(CollectionData *cd, const gchar *path);
static CollectManagerEntry *collect_manager_get_entry(const gchar *path);
static void collect_manager_entry_reset(CollectManagerEntry *entry);
guint flush = !!(flags & COLLECTION_LOAD_FLUSH);
guint append = !!(flags & COLLECTION_LOAD_APPEND);
guint only_geometry = !!(flags & COLLECTION_LOAD_GEOMETRY);
+ gboolean reading_extended_filename = FALSE;
+ GString *extended_filename_buffer = g_string_new(NULL);
+ gchar *buffer2;
if (!only_geometry)
{
if (!path) path = cd->path;
+ pathl = path_from_utf8(path);
+
DEBUG_1("collection load: append=%d flush=%d only_geometry=%d path=%s",
- append, flush, only_geometry, path);
+ append, flush, only_geometry, pathl);
/* load it */
- pathl = path_from_utf8(path);
f = fopen(pathl, "r");
g_free(pathl);
if (!f)
gchar *buf;
gchar *p = s_buf;
- /* Skip whitespaces and empty lines */
- while (*p && g_ascii_isspace(*p)) p++;
- if (*p == '\n' || *p == '\r') continue;
+ if (!reading_extended_filename)
+ {
+ /* Skip whitespaces and empty lines */
+ while (*p && g_ascii_isspace(*p)) p++;
+ if (*p == '\n' || *p == '\r') continue;
- /* Parse comments */
- if (*p == '#')
+ /* Parse comments */
+ if (*p == '#')
+ {
+ if (!need_header) continue;
+ if (g_ascii_strncasecmp(p, GQ_COLLECTION_MARKER, strlen(GQ_COLLECTION_MARKER)) == 0)
+ {
+ /* Looks like an official collection, allow unchecked input.
+ * All this does is allow adding files that may not exist,
+ * which is needed for the collection manager to work.
+ * Also unofficial files abort after too many invalid entries.
+ */
+ has_official_header = TRUE;
+ limit_failures = FALSE;
+ }
+ else if (strncmp(p, "#geometry:", 10 ) == 0 &&
+ scan_geometry(p + 10, &cd->window_x, &cd->window_y, &cd->window_w, &cd->window_h))
+ {
+ has_geometry_header = TRUE;
+ cd->window_read = TRUE;
+ if (only_geometry) break;
+ }
+ else if (g_ascii_strncasecmp(p, "#GQview collection", strlen("#GQview collection")) == 0)
+ {
+ /* As 2008/04/15 there is no difference between our collection file format
+ * and GQview 2.1.5 collection file format so ignore failures as well. */
+ has_gqview_header = TRUE;
+ limit_failures = FALSE;
+ }
+ need_header = (!has_official_header && !has_gqview_header) || !has_geometry_header;
+ continue;
+ }
+
+ if (only_geometry) continue;
+ }
+
+ /* Read filenames */
+ /** @todo This is not safe! */
+ /* Updated: anything within double quotes is considered a filename */
+ if (!reading_extended_filename)
{
- if (!need_header) continue;
- if (g_ascii_strncasecmp(p, GQ_COLLECTION_MARKER, strlen(GQ_COLLECTION_MARKER)) == 0)
+ /* not yet reading filename */
+ while (*p && *p != '"') p++;
+ if (*p) p++;
+ /* start of filename read */
+ buf = p;
+ while (*p && *p != '"') p++;
+ if (p[0] != '"')
{
- /* Looks like an official collection, allow unchecked input.
- * All this does is allow adding files that may not exist,
- * which is needed for the collection manager to work.
- * Also unofficial files abort after too many invalid entries.
- */
- has_official_header = TRUE;
- limit_failures = FALSE;
+ /* first part of extended filename */
+ g_string_append(extended_filename_buffer, buf);
+ reading_extended_filename = TRUE;
+ continue;
}
- else if (strncmp(p, "#geometry:", 10 ) == 0 &&
- scan_geometry(p + 10, &cd->window_x, &cd->window_y, &cd->window_w, &cd->window_h))
+ }
+ else
+ {
+ buf = p;
+ while (*p && *p != '"') p++;
+ if (p[0] != '"')
{
- has_geometry_header = TRUE;
- cd->window_read = TRUE;
- if (only_geometry) break;
+ /* end of extended filename still not found */
+ g_string_append(extended_filename_buffer, buf);
+ continue;
}
- else if (g_ascii_strncasecmp(p, "#GQview collection", strlen("#GQview collection")) == 0)
+ else
{
- /* As 2008/04/15 there is no difference between our collection file format
- * and GQview 2.1.5 collection file format so ignore failures as well. */
- has_gqview_header = TRUE;
- limit_failures = FALSE;
+ /* end of extended filename found */
+ g_string_append_len(extended_filename_buffer, buf, p - buf);
+ reading_extended_filename = FALSE;
}
- need_header = (!has_official_header && !has_gqview_header) || !has_geometry_header;
- continue;
}
- if (only_geometry) continue;
+ if (strlen(extended_filename_buffer->str) > 0)
+ {
+ buffer2 = g_strdup(extended_filename_buffer->str);
+ g_string_erase(extended_filename_buffer, 0, -1);
+ }
+ else
+ {
+ *p = 0;
+ buffer2 = g_strdup(buf);
+ }
- /* Read filenames */
- while (*p && *p != '"') p++;
- if (*p) p++;
- buf = p;
- while (*p && *p != '"') p++;
- *p = 0;
- if (*buf)
+ if (*buffer2)
{
gboolean valid;
if (!flush)
- changed |= collect_manager_process_action(entry, &buf);
+ changed |= collect_manager_process_action(entry, &buffer2);
- valid = (buf[0] == G_DIR_SEPARATOR && collection_add_check(cd, file_data_new_simple(buf), FALSE, TRUE));
- if (!valid) DEBUG_1("collection invalid file: %s", buf);
+ valid = (buffer2[0] == G_DIR_SEPARATOR && collection_add_check(cd, file_data_new_simple(buffer2), FALSE, TRUE));
+ if (!valid) DEBUG_1("collection invalid file: %s", buffer2);
total++;
if (!valid)
}
}
}
+ g_free(buffer2);
}
+ g_string_free(extended_filename_buffer, TRUE);
+
DEBUG_1("collection files: total = %d fail = %d official=%d gqview=%d geometry=%d",
total, fail, has_official_header, has_gqview_header, has_geometry_header);
gchar *buf = NULL;
while (collect_manager_process_action(entry, &buf))
{
- collection_add_check(cd, file_data_new_simple(buf), FALSE, TRUE);
+ collection_add_check(cd, file_data_new_group(buf), FALSE, TRUE);
changed = TRUE;
g_free(buf);
buf = NULL;
collect_manager_action_unref(action);
}
g_list_free(entry->add_list);
- g_hash_table_destroy(entry->oldpath_hash);
- g_hash_table_destroy(entry->newpath_hash);
+ if (g_hash_table_size(entry->oldpath_hash) > 0)
+ g_hash_table_destroy(entry->oldpath_hash);
+ else
+ g_hash_table_unref(entry->oldpath_hash);
+ if (g_hash_table_size(entry->newpath_hash) > 0)
+ g_hash_table_destroy(entry->newpath_hash);
+ else
+ g_hash_table_unref(entry->newpath_hash);
}
static void collect_manager_entry_init_data(CollectManagerEntry *entry)
if (action)
{
- g_free(path);
- path = g_strdup(action->newpath);
- *path_ptr = path;
+ strcpy(*path_ptr, action->newpath);
return TRUE;
}
GList *work;
FileData *dir_fd;
- dir_fd = file_data_new_simple(get_collections_dir());
+ dir_fd = file_data_new_dir(get_collections_dir());
filelist_read(dir_fd, &list, NULL);
file_data_unref(dir_fd);
else
{
collect_manager_entry_free(entry);
+
+ entry = NULL;
}
}
}
static void collect_manager_process_actions(gint max)
{
if (collection_manager_action_list) DEBUG_1("collection manager processing actions");
-
+
while (collection_manager_action_list != NULL && max > 0)
{
CollectManagerAction *action;
static gboolean collect_manager_process_entry(CollectManagerEntry *entry)
{
CollectionData *cd;
- gboolean success;
if (entry->empty) return FALSE;
cd = collection_new(entry->path);
- success = collection_load_private(cd, entry->path, COLLECTION_LOAD_NONE);
+ (void) collection_load_private(cd, entry->path, COLLECTION_LOAD_NONE);
collection_unref(cd);
void collect_manager_notify_cb(FileData *fd, NotifyType type, gpointer data)
{
if (!(type & NOTIFY_CHANGE) || !fd->change) return;
-
+
DEBUG_1("Notify collect_manager: %s %04x", fd->path, type);
switch (fd->change->type)
{
case FILEDATA_CHANGE_WRITE_METADATA:
break;
}
+}
+
+static gint collection_manager_sort_cb(gconstpointer a, gconstpointer b)
+{
+ const gchar *char_a = a;
+ const gchar *char_b = b;
+
+ return g_strcmp0(char_a, char_b);
+}
+
+/**
+ * @brief Creates sorted list of collections
+ * @param[out] names_exc sorted list of collections names excluding extension
+ * @param[out] names_inc sorted list of collections names including extension
+ * @param[out] paths sorted list of collection paths
+ *
+ * Lists of type gchar.
+ * Used lists must be freed with string_list_free()
+ */
+void collect_manager_list(GList **names_exc, GList **names_inc, GList **paths)
+{
+ FileData *dir_fd;
+ GList *list = NULL;
+ gchar *name;
+ FileData *fd;
+ gchar *filename;
+
+ if (names_exc == NULL && names_inc == NULL && paths == NULL)
+ {
+ return;
+ }
+
+ dir_fd = file_data_new_dir((get_collections_dir()));
+ filelist_read(dir_fd, &list, NULL);
+
+ while (list)
+ {
+ fd = list->data;
+ filename = g_strdup(filename_from_path((gchar *)fd->path));
+
+ if (file_extension_match(filename, GQ_COLLECTION_EXT))
+ {
+ name = remove_extension_from_path(filename);
+
+ if (names_exc != NULL)
+ {
+ *names_exc = g_list_insert_sorted(*names_exc, g_strdup(name),
+ collection_manager_sort_cb);
+ *names_exc = g_list_first(*names_exc);
+ }
+ if (names_inc != NULL)
+ {
+ *names_inc = g_list_insert_sorted(*names_inc,filename,
+ collection_manager_sort_cb);
+ *names_inc = g_list_first(*names_inc);
+ }
+ if (paths != NULL)
+ {
+ *paths = g_list_insert_sorted(*paths,fd->path,
+ collection_manager_sort_cb);
+ *paths = g_list_first(*paths);
+ }
+ g_free(name);
+ }
+ list = list->next;
+ g_free(filename);
+ }
+
+ filelist_free(list);
}
/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */