gint collection_save(CollectionData *cd, const gchar *path) { if (collection_save_private(cd, path)) { layout_recent_add_path(cd->path); return TRUE; } return FALSE; }
static gint collect_manager_process_entry(CollectManagerEntry *entry) { CollectionData *cd; gint success; GList *work; if (!entry->action_list) return FALSE; cd = collection_new(entry->path); success = collection_load_private(cd, entry->path, FALSE, FALSE); work = g_list_last(entry->action_list); while (work) { CollectManagerAction *action; action = work->data; work = work->prev; if (!action->oldpath) { /* add image */ if (collection_list_find(cd->list, action->newpath) == NULL) { collection_add_check(cd, action->newpath, FALSE, FALSE); } } else if (action->newpath) { /* rename image */ while (collection_rename(cd, action->oldpath, action->newpath)); } else { /* remove image */ while (collection_remove(cd, action->oldpath)); } collect_manager_action_unref(action); } if (success && cd->changed) { collection_save_private(cd, entry->path); if (debug) printf("collection manager updated: %s\n", entry->path); } collection_unref(cd); g_list_free(entry->action_list); entry->action_list = NULL; return TRUE; }
static gboolean collection_load_private(CollectionData *cd, const gchar *path, CollectionLoadFlags flags) { gchar s_buf[GQ_COLLECTION_READ_BUFSIZE]; FILE *f; gchar *pathl; gboolean limit_failures = TRUE; gboolean success = TRUE; gboolean has_official_header = FALSE; gboolean has_geometry_header = FALSE; gboolean has_gqview_header = FALSE; gboolean need_header = TRUE; guint total = 0; guint fail = 0; gboolean changed = FALSE; CollectManagerEntry *entry = NULL; guint flush = !!(flags & COLLECTION_LOAD_FLUSH); guint append = !!(flags & COLLECTION_LOAD_APPEND); guint only_geometry = !!(flags & COLLECTION_LOAD_GEOMETRY); if (!only_geometry) { collection_load_stop(cd); if (flush) collect_manager_flush(); else entry = collect_manager_get_entry(path); if (!append) { collection_list_free(cd->list); cd->list = NULL; } } if (!path && !cd->path) return FALSE; if (!path) path = cd->path; DEBUG_1("collection load: append=%d flush=%d only_geometry=%d path=%s", append, flush, only_geometry, path); /* load it */ pathl = path_from_utf8(path); f = fopen(pathl, "r"); g_free(pathl); if (!f) { log_printf("Failed to open collection file: \"%s\"\n", path); return FALSE; } while (fgets(s_buf, sizeof(s_buf), 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; /* 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 */ while (*p && *p != '"') p++; if (*p) p++; buf = p; while (*p && *p != '"') p++; *p = 0; if (*buf) { gboolean valid; if (!flush) changed |= collect_manager_process_action(entry, &buf); 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); total++; if (!valid) { fail++; if (limit_failures && fail > GQ_COLLECTION_FAIL_MIN && fail * 100 / total > GQ_COLLECTION_FAIL_PERCENT) { log_printf("%d invalid filenames in unofficial collection file, closing: %s\n", fail, path); success = FALSE; break; } } } } 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); fclose(f); if (only_geometry) return has_geometry_header; if (!flush) { gchar *buf = NULL; while (collect_manager_process_action(entry, &buf)) { collection_add_check(cd, file_data_new_simple(buf), FALSE, TRUE); changed = TRUE; g_free(buf); buf = NULL; } } cd->list = collection_list_sort(cd->list, cd->sort_method); if (!flush && changed && success) collection_save_private(cd, path); if (!flush) collect_manager_entry_reset(entry); if (!append) cd->changed = FALSE; return success; }