Example #1
0
gboolean metadata_write_perform(FileData *fd)
{
	gboolean success;
	ExifData *exif;
	guint lf;

	g_assert(fd->change);

	lf = strlen(GQ_CACHE_EXT_METADATA);
	if (fd->change->dest &&
	    g_ascii_strncasecmp(fd->change->dest + strlen(fd->change->dest) - lf, GQ_CACHE_EXT_METADATA, lf) == 0)
		{
		success = metadata_legacy_write(fd);
		if (success) metadata_legacy_delete(fd, fd->change->dest);
		return success;
		}

	/* write via exiv2 */
	/*  we can either use cached metadata which have fd->modified_xmp already applied
	                             or read metadata from file and apply fd->modified_xmp
	    metadata are read also if the file was modified meanwhile */
	exif = exif_read_fd(fd);
	if (!exif) return FALSE;

	success = (fd->change->dest) ? exif_write_sidecar(exif, fd->change->dest) : exif_write(exif); /* write modified metadata */
	exif_free_fd(fd, exif);

	if (fd->change->dest)
		/* this will create a FileData for the sidecar and link it to the main file
		   (we can't wait until the sidecar is discovered by directory scanning because
		    exif_read_fd is called before that and it would read the main file only and
		    store the metadata in the cache)
		    FIXME: this does not catch new sidecars created by independent external programs
		*/
		file_data_unref(file_data_new_group(fd->change->dest));

	if (success) metadata_legacy_delete(fd, fd->change->dest);
	return success;
}
Example #2
0
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_group(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_group(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;
}