diff src/metadata.c @ 1211:e2bbe90b0dcd

most of the metadata options now works
author nadvornik
date Sun, 21 Dec 2008 21:20:36 +0000
parents c45cc5cf3c4d
children 31402ecb2aed
line wrap: on
line diff
--- a/src/metadata.c	Sun Dec 21 16:26:03 2008 +0000
+++ b/src/metadata.c	Sun Dec 21 21:20:36 2008 +0000
@@ -22,6 +22,7 @@
 #include "ui_fileops.h"
 #include "ui_misc.h"
 #include "utilops.h"
+#include "filefilter.h"
 
 typedef enum {
 	MK_NONE,
@@ -37,6 +38,20 @@
 static gint metadata_legacy_delete(FileData *fd);
 
 
+
+gboolean metadata_can_write_directly(FileData *fd)
+{
+	return (filter_file_class(fd->extension, FORMAT_CLASS_IMAGE));
+/* FIXME: detect what exiv2 really supports */
+}
+
+gboolean metadata_can_write_sidecar(FileData *fd)
+{
+	return (filter_file_class(fd->extension, FORMAT_CLASS_RAWIMAGE));
+/* FIXME: detect what exiv2 really supports */
+}
+
+
 /*
  *-------------------------------------------------------------------
  * write queue
@@ -46,6 +61,60 @@
 static GList *metadata_write_queue = NULL;
 static gint metadata_write_idle_id = -1;
 
+static FileData *metadata_xmp_sidecar_fd(FileData *fd)
+{
+	GList *work;
+	gchar *base, *new_name;
+	FileData *ret;
+	
+	if (!metadata_can_write_sidecar(fd)) return NULL;
+		
+	
+	if (fd->parent) fd = fd->parent;
+	
+	if (filter_file_class(fd->extension, FORMAT_CLASS_META))
+		return file_data_ref(fd);
+	
+	work = fd->sidecar_files;
+	while (work)
+		{
+		FileData *sfd = work->data;
+		work = work->next;
+		if (filter_file_class(sfd->extension, FORMAT_CLASS_META))
+			return file_data_ref(sfd);
+		}
+	
+	/* sidecar does not exist yet */
+	base = remove_extension_from_path(fd->path);
+	new_name = g_strconcat(base, ".xmp", NULL);
+	g_free(base);
+	ret = file_data_new_simple(new_name);
+	g_free(new_name);
+	return ret;
+}
+
+static FileData *metadata_xmp_main_fd(FileData *fd)
+{
+	if (filter_file_class(fd->extension, FORMAT_CLASS_META) && !g_list_find(metadata_write_queue, fd))
+		{
+		/* fd is a sidecar, we have to find the original file */
+		
+		GList *work = metadata_write_queue;
+		while (work)
+			{
+			FileData *ofd = work->data;
+			FileData *osfd = metadata_xmp_sidecar_fd(ofd);
+			work = work->next;
+			file_data_unref(osfd);
+			if (fd == osfd)
+				{
+				return ofd; /* this is the main file */
+				}
+			}
+		}
+	return NULL;
+}
+
 
 static void metadata_write_queue_add(FileData *fd)
 {
@@ -60,39 +129,102 @@
 
 gboolean metadata_write_queue_remove(FileData *fd)
 {
+	FileData *main_fd = metadata_xmp_main_fd(fd);
+
+	if (main_fd) fd = main_fd;
+
 	g_hash_table_destroy(fd->modified_xmp);
 	fd->modified_xmp = NULL;
 
 	metadata_write_queue = g_list_remove(metadata_write_queue, fd);
+	
+	file_data_increment_version(fd);
+	file_data_send_notification(fd, NOTIFY_TYPE_REREAD);
+
 	file_data_unref(fd);
 	return TRUE;
 }
 
+gboolean metadata_write_queue_remove_list(GList *list)
+{
+	GList *work;
+	gboolean ret = TRUE;
+	
+	work = list;
+	while (work)
+		{
+		FileData *fd = work->data;
+		work = work->next;
+		ret = ret && metadata_write_queue_remove(fd);
+		}
+	return ret;
+}
+
 
 static gboolean metadata_write_queue_idle_cb(gpointer data)
 {
-	/* TODO:  the queue should not be passed to file_util_write_metadata directly:
-		  metatata under .geeqie/ can be written immediately, 
-	          for others we can decide if we write to the image file or to sidecar */
+	GList *work;
+	GList *to_approve = NULL;
 	
+	work = metadata_write_queue;
+	while (work)
+		{
+		FileData *fd = work->data;
+		work = work->next;
+		
+		if (fd->change) continue; /* another operation in progress, skip this file for now */
+		
+		FileData *to_approve_fd = metadata_xmp_sidecar_fd(fd);
+		
+		if (!to_approve_fd) to_approve_fd = file_data_ref(fd); /* this is not a sidecar */
 
-//	if (metadata_write_queue) return TRUE;
+		to_approve = g_list_prepend(to_approve, to_approve_fd);
+		}
 
-	/* confirm writting */
-	file_util_write_metadata(NULL, metadata_write_queue, NULL);
+	file_util_write_metadata(NULL, to_approve, NULL);
+	
+	filelist_free(to_approve);
 
 	metadata_write_idle_id = -1;
 	return FALSE;
 }
 
+gboolean metadata_write_exif(FileData *fd, FileData *sfd)
+{
+	gboolean success;
+	ExifData *exif;
+	
+	/*  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 = sfd ? exif_write_sidecar(exif, sfd->path) : exif_write(exif); /* write modified metadata */
+	exif_free_fd(fd, exif);
+	return success;
+}
+
 gboolean metadata_write_perform(FileData *fd)
 {
+	FileData *sfd = NULL;
+	FileData *main_fd = metadata_xmp_main_fd(fd);
+
+	if (main_fd)
+		{
+		sfd = fd;
+		fd = main_fd;
+		}
+
 	if (options->metadata.save_in_image_file &&
-	    exif_write_fd(fd))
+	    metadata_write_exif(fd, sfd))
 		{
 		metadata_legacy_delete(fd);
+		if (sfd) metadata_legacy_delete(sfd);
 		}
-	else metadata_legacy_write(fd);
+	else
+		{
+		metadata_legacy_write(fd);
+		}
 	return TRUE;
 }
 
@@ -435,8 +567,23 @@
 	if (!fd) return FALSE;
 
 	if (write_comment) success = success && metadata_write_string(fd, COMMENT_KEY, comment);
+	if (keywords) success = success && metadata_write_list(fd, KEYWORD_KEY, string_list_copy(keywords));
 	
-	if (keywords) success = success && metadata_write_list(fd, KEYWORD_KEY, string_list_copy(keywords));
+	if (options->metadata.sync_grouped_files)
+		{
+		GList *work = fd->sidecar_files;
+		
+		while (work)
+			{
+			FileData *sfd = work->data;
+			work = work->next;
+			
+			if (filter_file_class(sfd->extension, FORMAT_CLASS_META)) continue; 
+
+			if (write_comment) success = success && metadata_write_string(sfd, COMMENT_KEY, comment);
+			if (keywords) success = success && metadata_write_list(sfd, KEYWORD_KEY, string_list_copy(keywords));
+			}
+		}
 
 	return success;
 }