changeset 590:2b7b966f61cf

started implementation of API for sidecar files
author nadvornik
date Mon, 05 May 2008 20:51:51 +0000
parents 46ddfaf13235
children 5c4c6f370d09
files src/filedata.c src/filedata.h src/typedefs.h
diffstat 3 files changed, 378 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/filedata.c	Mon May 05 20:51:50 2008 +0000
+++ b/src/filedata.c	Mon May 05 20:51:51 2008 +0000
@@ -887,3 +887,365 @@
 
 	return list;
 }
+
+
+
+/*
+ * file_data    - operates on the given fd
+ * file_data_sc - operates on the given fd + sidecars - all fds linked via fd->sidecar_files or fd->parent
+ */
+
+
+/* return list of sidecar file extensions in a string */
+gchar *file_data_sc_list_to_string(FileData *fd); // now gchar *sidecar_file_data_list_to_string(FileData *fd)
+
+
+/* disables / enables grouping for particular file, sends UPDATE notification */
+void file_data_disable_grouping(FileData *fd); // now file_data_disconnect_sidecar_file, broken
+void file_data_disable_grouping(FileData *fd);
+
+/* runs stat on a file and sends UPDATE notification if it has been changed */
+void file_data_sc_update(FileData *fd);
+
+
+
+
+/* 
+ * add FileDataChangeInfo (see typedefs.h) for the given operation 
+ * uses file_data_add_change_info
+ *
+ * fails if the fd->change already exists - change operations can't run in parallel
+ * fd->change_info works as a lock
+ *
+ * dest can be NULL - in this case the current name is used for now, it will
+ * be changed later 
+ */
+
+/*
+   FileDataChangeInfo types:
+   COPY
+   MOVE - patch is changed, name may be changed too
+   RENAME - path remains unchanged, name is changed
+            extension should remain (FIXME should we allow editing extension? it will make problems wth grouping)
+	    sidecar names are changed too, extensions are not changed
+   DELETE
+   UPDATE - file size, date or grouping has been changed 
+*/
+
+gboolean file_data_add_ci(FileData *fd, FileDataChangeType type, const gchar *src, const gchar *dest)
+{
+
+	FileDataChangeInfo *fdci;
+
+	if (fd->change) return FALSE;
+
+	fdci = g_new0(FileDataChangeInfo, 1);
+
+	fdci->type = type;
+
+	if (src)
+		fdci->source = g_strdup(src);
+	else
+		fdci->source = g_strdup(fd->path);
+
+	if (dest)
+		fdci->dest = g_strdup(dest);
+
+	fd->change = fdci;
+	
+	return TRUE;
+}
+
+void file_data_free_ci(FileData *fd)
+{
+	FileDataChangeInfo *fdci = fd->change;
+
+	if (!fdci)
+		return;
+
+	g_free(fdci->source);
+	g_free(fdci->dest);
+
+	g_free(fdci);
+
+	fd->change = NULL;
+}
+
+ 
+static gboolean file_data_sc_add_ci(FileData *fd, FileDataChangeType type)
+{
+	GList *work;
+	if (fd->parent) fd = fd->parent;
+	
+	if (fd->change) return FALSE;
+	work = fd->sidecar_files;
+	while (work)
+		{
+		FileData *sfd = work->data;
+		if (sfd->change) return FALSE;
+		work = work->next;
+		}
+
+	file_data_add_ci(fd, type, NULL, NULL);
+	
+	work = fd->sidecar_files;
+	while (work)
+		{
+		FileData *sfd = work->data;
+		file_data_add_ci(sfd, type, NULL, NULL);
+		work = work->next;
+		}
+		
+	return TRUE;	
+}
+
+static gboolean file_data_sc_check_ci(FileData *fd, FileDataChangeType type)
+{
+	GList *work;
+	if (fd->parent) fd = fd->parent;
+	
+	if (!fd->change) return FALSE;
+	if (fd->change->type != type) return FALSE;
+	work = fd->sidecar_files;
+	while (work)
+		{
+		FileData *sfd = work->data;
+		if (!sfd->change) return FALSE;
+		if (sfd->change->type != type) return FALSE;
+		work = work->next;
+		}
+	return TRUE;
+}
+
+
+gboolean file_data_sc_add_ci_copy(FileData *fd, gchar *dest_path)
+{
+	if (!file_data_sc_add_ci(fd, FILEDATA_CHANGE_COPY)) return FALSE;
+	file_data_sc_update_ci_copy(fd, dest_path);
+	return TRUE;
+}
+
+gboolean file_data_sc_add_ci_move(FileData *fd, gchar *dest_path)
+{
+	if (!file_data_sc_add_ci(fd, FILEDATA_CHANGE_MOVE)) return FALSE;
+	file_data_sc_update_ci_move(fd, dest_path);
+	return TRUE;
+}
+
+gboolean file_data_sc_add_ci_rename(FileData *fd, gchar *dest_path)
+{
+	if (!file_data_sc_add_ci(fd, FILEDATA_CHANGE_RENAME)) return FALSE;
+	file_data_sc_update_ci_rename(fd, dest_path);
+	return TRUE;
+}
+
+gboolean file_data_sc_add_ci_delete(FileData *fd)
+{
+	return file_data_sc_add_ci(fd, FILEDATA_CHANGE_DELETE);
+}
+
+gboolean file_data_sc_add_ci_update(FileData *fd)
+{
+	return file_data_sc_add_ci(fd, FILEDATA_CHANGE_UPDATE);
+}
+
+void file_data_sc_free_ci(FileData *fd)
+{
+	GList *work;
+	if (fd->parent) fd = fd->parent;
+	
+	file_data_free_ci(fd);
+	
+	work = fd->sidecar_files;
+	while (work)
+		{
+		FileData *sfd = work->data;
+		file_data_free_ci(sfd);
+		work = work->next;
+		}
+}
+
+
+/* 
+ * update existing fd->change, it will be used from dialog callbacks for interactive editing
+ * fails if fd->change does not exist or the change type does not match
+ */
+
+static void file_data_update_ci_dest(FileData *fd, gchar *dest_path)
+{
+	g_free(fd->change->dest);
+	fd->change->dest = g_strdup(dest_path);
+}
+
+static void file_data_update_ci_dest_preserve_ext(FileData *fd, gchar *dest_path)
+{
+	const char *extension = extension_from_path(fd->change->source);
+	g_free(fd->change->dest);
+	fd->change->dest = g_strdup_printf("%*s%s", (int)(extension_from_path(dest_path) - dest_path), dest_path, extension);
+}
+
+static void file_data_sc_update_ci(FileData *fd, gchar *dest_path)
+{
+	GList *work;
+	if (fd->parent) fd = fd->parent;
+	
+	file_data_update_ci_dest(fd, dest_path);
+	work = fd->sidecar_files;
+	while (work)
+		{
+		FileData *sfd = work->data;
+		file_data_update_ci_dest_preserve_ext(sfd, dest_path);
+		work = work->next;
+		}
+}
+
+gint file_data_sc_update_ci_copy(FileData *fd, gchar *dest_path)
+{
+	if (!file_data_sc_check_ci(fd, FILEDATA_CHANGE_COPY)) return FALSE;
+	file_data_sc_update_ci(fd, dest_path);
+	return TRUE;
+}
+	
+gint file_data_sc_update_ci_move(FileData *fd, gchar *dest_path)
+{
+	if (!file_data_sc_check_ci(fd, FILEDATA_CHANGE_MOVE)) return FALSE;
+	file_data_sc_update_ci(fd, dest_path);
+	return TRUE;
+}
+
+gint file_data_sc_update_ci_rename(FileData *fd, gchar *dest_path)
+{
+	if (!file_data_sc_check_ci(fd, FILEDATA_CHANGE_RENAME)) return FALSE;
+	file_data_sc_update_ci(fd, dest_path);
+	return TRUE;
+}
+
+
+
+/*
+ * check dest paths - dest image exists, etc.
+ * returns FIXME
+ * it should detect all possible problems with the planned operation
+ */
+ 
+gint file_data_sc_check_ci_dest(FileData *fd)
+{
+}
+
+
+
+
+/*
+ * perform the change described by FileFataChangeInfo
+ * it is used for internal operations, 
+ * this function actually operates with files on the filesystem
+ * it should implement safe delete
+ */
+ 
+static gboolean file_data_perform_move(FileData *fd)
+{
+	g_assert(!strcmp(fd->change->source, fd->path));
+	return move_file(fd->change->source, fd->change->dest);
+}
+
+static gboolean file_data_perform_copy(FileData *fd)
+{
+	g_assert(!strcmp(fd->change->source, fd->path));
+	return copy_file(fd->change->source, fd->change->dest);
+}
+
+static gboolean file_data_perform_delete(FileData *fd)
+{
+	return unlink_file(fd->path);
+}
+
+static gboolean file_data_perform_ci(FileData *fd)
+{
+	FileDataChangeType type = fd->change->type;
+	switch (type)
+		{
+		case FILEDATA_CHANGE_MOVE:
+			return file_data_perform_move(fd);
+		case FILEDATA_CHANGE_COPY:
+			return file_data_perform_copy(fd);
+		case FILEDATA_CHANGE_RENAME:
+			return file_data_perform_move(fd); /* the same as move */
+		case FILEDATA_CHANGE_DELETE:
+			return file_data_perform_delete(fd);
+		case FILEDATA_CHANGE_UPDATE:
+			/* notring to do here */
+			break;
+		}
+	return TRUE;
+}
+
+
+
+gboolean file_data_sc_perform_ci(FileData *fd)
+{
+	GList *work;
+	gboolean ret = TRUE;
+	FileDataChangeType type = fd->change->type;
+	if (!file_data_sc_check_ci(fd, type)) return FALSE;
+
+	work = fd->sidecar_files;
+	while (work)
+		{
+		FileData *sfd = work->data;
+		if (!file_data_perform_ci(sfd)) ret = FALSE;
+		work = work->next;
+		}
+	if (!file_data_perform_ci(fd)) ret = FALSE;
+	return ret;
+}
+
+/*
+ * updates FileData structure according to FileDataChangeInfo
+ */
+ 
+static void file_data_apply_ci(FileData *fd)
+{
+	FileDataChangeType type = fd->change->type;
+	/* FIXME delete ?*/
+	if (type == FILEDATA_CHANGE_MOVE || type == FILEDATA_CHANGE_COPY || type == FILEDATA_CHANGE_RENAME)
+		{
+		g_free(fd->path);
+		g_hash_table_remove(file_data_pool, fd->original_path);
+		g_free(fd->original_path);
+		file_data_set_path(fd, fd->change->dest);
+		fd->original_path = g_strdup(fd->change->dest);
+		g_hash_table_insert(file_data_pool, fd->original_path, fd);
+		}
+}
+
+gint file_data_sc_apply_ci(FileData *fd) // now file_data_do_change
+{
+	GList *work;
+	FileDataChangeType type = fd->change->type;
+	if (!file_data_sc_check_ci(fd, type)) return FALSE;
+
+	work = fd->sidecar_files;
+	while (work)
+		{
+		FileData *sfd = work->data;
+		file_data_apply_ci(sfd);
+		work = work->next;
+		}
+	file_data_apply_ci(fd);
+	return TRUE;
+}
+
+
+/*
+ * notify other modules about the change described by FileFataChangeInfo
+ */
+ 
+/* might use file_maint_ functions for now, later it should be changed to a system of callbacks
+   FIXME do we need the ignore_list? It looks like a workaround for ineffective
+   implementation in view_file_list.c */
+
+void file_data_sc_send_notification(FileData *fd)
+{
+}
+
+
--- a/src/filedata.h	Mon May 05 20:51:50 2008 +0000
+++ b/src/filedata.h	Mon May 05 20:51:51 2008 +0000
@@ -49,4 +49,18 @@
 GList *filelist_sort_path(GList *list);
 GList *filelist_recursive(const gchar *path);
 
+gchar *file_data_sc_list_to_string(FileData *fd);
+gboolean file_data_add_ci(FileData *fd, FileDataChangeType type, const gchar *src, const gchar *dest);
+gboolean file_data_sc_add_ci_copy(FileData *fd, gchar *dest_path);
+gboolean file_data_sc_add_ci_move(FileData *fd, gchar *dest_path);
+gboolean file_data_sc_add_ci_rename(FileData *fd, gchar *dest_path);
+gboolean file_data_sc_add_ci_delete(FileData *fd);
+gboolean file_data_sc_add_ci_update(FileData *fd);
+gint file_data_sc_update_ci_copy(FileData *fd, gchar *dest_path);
+gint file_data_sc_update_ci_move(FileData *fd, gchar *dest_path);
+gint file_data_sc_update_ci_rename(FileData *fd, gchar *dest_path);
+gint file_data_sc_check_ci_dest(FileData *fd);
+gboolean file_data_sc_perform_ci(FileData *fd);
+gint file_data_sc_apply_ci(FileData *fd);
+
 #endif
--- a/src/typedefs.h	Mon May 05 20:51:50 2008 +0000
+++ b/src/typedefs.h	Mon May 05 20:51:51 2008 +0000
@@ -91,7 +91,8 @@
 	FILEDATA_CHANGE_DELETE,
 	FILEDATA_CHANGE_MOVE,
 	FILEDATA_CHANGE_RENAME,
-	FILEDATA_CHANGE_COPY
+	FILEDATA_CHANGE_COPY,
+	FILEDATA_CHANGE_UPDATE
 } FileDataChangeType;
 
 typedef enum {