#include "cache.h"
#include "thumb_standard.h"
#include "ui_fileops.h"
+#include "metadata.h"
static GHashTable *file_data_pool = NULL;
static GHashTable *file_data_planned_change_hash = NULL;
static gint sidecar_file_priority(const gchar *path);
-static void file_data_apply_ci(FileData *fd);
/*
return TRUE;
}
+gboolean file_data_add_ci_write_metadata(FileData *fd)
+{
+ return file_data_add_ci(fd, FILEDATA_CHANGE_WRITE_METADATA, NULL, NULL);
+}
+
void file_data_sc_free_ci(FileData *fd)
{
GList *work;
return file_data_sc_add_ci_list_call_func(fd_list, dest, file_data_sc_add_ci_unspecified);
}
+gboolean file_data_add_ci_write_metadata_list(GList *fd_list)
+{
+ GList *work;
+ gboolean ret = TRUE;
+
+ work = fd_list;
+ while (work)
+ {
+ FileData *fd = work->data;
+
+ if (!file_data_add_ci_write_metadata(fd)) ret = FALSE;
+ work = work->next;
+ }
+
+ return ret;
+}
+
+void file_data_free_ci_list(GList *fd_list)
+{
+ GList *work;
+
+ work = fd_list;
+ while (work)
+ {
+ FileData *fd = work->data;
+
+ file_data_free_ci(fd);
+ work = work->next;
+ }
+}
+
void file_data_sc_free_ci_list(GList *fd_list)
{
GList *work;
return g_string_free(result, FALSE);
}
-gint file_data_sc_verify_ci_list(GList *list, gchar **desc)
+gint file_data_verify_ci_list(GList *list, gchar **desc, gboolean with_sidecars)
{
GList *work;
gint all_errors = 0;
fd = work->data;
work = work->next;
- error = file_data_sc_verify_ci(fd);
+ error = with_sidecars ? file_data_sc_verify_ci(fd) : file_data_verify_ci(fd);
all_errors |= error;
common_errors &= error;
return unlink_file(fd->path);
}
-static gboolean file_data_perform_ci(FileData *fd)
+gboolean file_data_perform_ci(FileData *fd)
{
FileDataChangeType type = fd->change->type;
switch (type)
return file_data_perform_move(fd); /* the same as move */
case FILEDATA_CHANGE_DELETE:
return file_data_perform_delete(fd);
+ case FILEDATA_CHANGE_WRITE_METADATA:
+ return metadata_write_perform(fd);
case FILEDATA_CHANGE_UNSPECIFIED:
/* nothing to do here */
break;
* updates FileData structure according to FileDataChangeInfo
*/
-static void file_data_apply_ci(FileData *fd)
+gint file_data_apply_ci(FileData *fd)
{
FileDataChangeType type = fd->change->type;
-
+
/* FIXME delete ?*/
if (type == FILEDATA_CHANGE_MOVE || type == FILEDATA_CHANGE_RENAME)
{
}
file_data_increment_version(fd);
file_data_send_notification(fd, NOTIFY_TYPE_CHANGE);
+
+ return TRUE;
}
gint file_data_sc_apply_ci(FileData *fd)
#include "ui_misc.h"
#include "ui_tabcomp.h"
#include "editors.h"
+#include "metadata.h"
static GdkPixbuf *file_util_get_error_icon(FileData *fd, GtkWidget *widget);
UTILITY_TYPE_DELETE,
UTILITY_TYPE_DELETE_LINK,
UTILITY_TYPE_DELETE_FOLDER,
- UTILITY_TYPE_CREATE_FOLDER
+ UTILITY_TYPE_CREATE_FOLDER,
+ UTILITY_TYPE_WRITE_METADATA
} UtilityType;
typedef enum {
FileDialog *fdlg;
gint update_idle_id;
+
+ gboolean with_sidecars; /* operate on grouped or single files; TRUE = use file_data_sc_, FALSE = use file_data_ functions */
/* alternative dialog parts */
GtkWidget *notebook;
if (!(flags & EDITOR_ERROR_MASK)) /* files were successfully deleted, call the maint functions */
{
- file_data_sc_apply_ci(fd);
+ if (ud->with_sidecars)
+ file_data_sc_apply_ci(fd);
+ else
+ file_data_apply_ci(fd);
}
ud->flist = g_list_remove(ud->flist, fd);
- file_data_sc_free_ci(fd);
+
+ /* FIXME: put it here for now */
+ if (ud->type == UTILITY_TYPE_WRITE_METADATA)
+ {
+ metadata_write_queue_remove(fd);
+ }
+
+ if (ud->with_sidecars)
+ file_data_sc_free_ci(fd);
+ else
+ file_data_free_ci(fd);
file_data_unref(fd);
}
gboolean last = !ud->flist->next;
gint status = EDITOR_ERROR_STATUS;
- if (file_data_sc_perform_ci(single_entry->data))
+ if (ud->with_sidecars ? file_data_sc_perform_ci(single_entry->data)
+ : file_data_perform_ci(single_entry->data))
status = 0; /* OK */
ret = file_util_perform_ci_cb(GINT_TO_POINTER(!last), status, single_entry, ud);
{
case UTILITY_TYPE_DELETE_LINK:
{
- if ((internal && file_data_sc_perform_ci(ud->dir_fd)) ||
+ g_assert(ud->dir_fd->sidecar_files == NULL); // directories should not have sidecars
+ if ((internal && file_data_perform_ci(ud->dir_fd)) ||
(!internal && ext_result))
{
- file_data_sc_apply_ci(ud->dir_fd);
+ file_data_apply_ci(ud->dir_fd);
}
else
{
file_util_warning_dialog(ud->messages.fail, text, GTK_STOCK_DIALOG_ERROR, NULL);
g_free(text);
}
- file_data_sc_free_ci(ud->dir_fd);
+ file_data_free_ci(ud->dir_fd);
break;
}
case UTILITY_TYPE_DELETE_FOLDER:
if (!fail)
{
+ g_assert(ud->dir_fd->sidecar_files == NULL); // directories should not have sidecars
if ((internal && file_data_sc_perform_ci(ud->dir_fd)) ||
(!internal && ext_result))
{
- file_data_sc_apply_ci(ud->dir_fd);
+ file_data_apply_ci(ud->dir_fd);
}
else
{
{
FileData *fail = NULL;
GList *work;
+ g_assert(ud->dir_fd->sidecar_files == NULL); // directories should not have sidecars
+
if ((internal && file_data_sc_perform_ci(ud->dir_fd)) ||
(!internal && ext_result))
{
case UTILITY_TYPE_EDITOR:
g_assert(ud->external_command != -1); /* it should be already set */
break;
+ case UTILITY_TYPE_WRITE_METADATA:
+ ud->external_command = -1;
}
if (is_valid_editor_command(ud->external_command))
}
else if (ud->dir_fd)
{
- error = file_data_sc_verify_ci(ud->dir_fd);
+ g_assert(ud->dir_fd->sidecar_files == NULL); // directories should not have sidecars
+ error = file_data_verify_ci(ud->dir_fd);
if (error) desc = file_data_get_error_string(error);
}
else
{
- error = file_data_sc_verify_ci_list(ud->flist, &desc);
+ error = file_data_verify_ci_list(ud->flist, &desc, ud->with_sidecars);
}
}
{
case UTILITY_TYPE_COPY:
file_data_sc_update_ci_copy_list(ud->flist, ud->dest_path);
- break;
case UTILITY_TYPE_MOVE:
file_data_sc_update_ci_move_list(ud->flist, ud->dest_path);
break;
case UTILITY_TYPE_DELETE_FOLDER:
case UTILITY_TYPE_RENAME:
case UTILITY_TYPE_RENAME_FOLDER:
+ case UTILITY_TYPE_WRITE_METADATA:
g_warning("unhandled operation");
}
}
const gchar *dest = gtk_entry_get_text(GTK_ENTRY(ud->rename_entry));
gtk_tree_model_get(store, &iter, UTILITY_COLUMN_FD, &fd, -1);
+ g_assert(ud->with_sidecars); /* sidecars must be renamed too, it would break the pairing otherwise */
file_data_sc_update_ci_rename(fd, dest);
gtk_list_store_set(GTK_LIST_STORE(store), &iter,
UTILITY_COLUMN_PIXBUF, file_util_get_error_icon(fd, ud->listview),
dest = g_strdup_printf("%s%0*d%s", front, padding, n, end);
}
+ g_assert(ud->with_sidecars); /* sidecars must be renamed too, it would break the pairing otherwise */
file_data_sc_update_ci_rename(fd, dest);
gtk_list_store_set(GTK_LIST_STORE(store), &iter,
UTILITY_COLUMN_PIXBUF, file_util_get_error_icon(fd, ud->listview),
GtkTreeSelection *selection;
gchar *dir_msg;
+ const gchar *stock_id;
+
+ if (ud->type == UTILITY_TYPE_DELETE ||
+ ud->type == UTILITY_TYPE_DELETE_LINK ||
+ ud->type == UTILITY_TYPE_DELETE_FOLDER)
+ {
+ stock_id = GTK_STOCK_DELETE;
+ }
+ else
+ {
+ stock_id = GTK_STOCK_OK;
+ }
+
ud->gd = file_util_gen_dlg(ud->messages.title, "dlg_confirm",
ud->parent, FALSE, file_util_cancel_cb, ud);
- generic_dialog_add_button(ud->gd, GTK_STOCK_DELETE, NULL, file_util_ok_cb, TRUE);
+ generic_dialog_add_button(ud->gd, stock_id, NULL, file_util_ok_cb, TRUE);
if (ud->dir_fd)
generic_dialog_add_image(ud->gd, box, NULL, NULL, NULL, NULL, FALSE);
- box_append_safe_delete_status(ud->gd);
+ if (ud->type == UTILITY_TYPE_DELETE ||
+ ud->type == UTILITY_TYPE_DELETE_LINK ||
+ ud->type == UTILITY_TYPE_DELETE_FOLDER)
+ box_append_safe_delete_status(ud->gd);
gtk_widget_show(ud->gd->dialog);
case UTILITY_TYPE_DELETE_LINK:
case UTILITY_TYPE_DELETE_FOLDER:
case UTILITY_TYPE_EDITOR:
+ case UTILITY_TYPE_WRITE_METADATA:
file_util_dialog_init_simple_list(ud);
break;
case UTILITY_TYPE_RENAME:
break;
case UTILITY_PHASE_CANCEL:
case UTILITY_PHASE_DONE:
- file_data_sc_free_ci_list(ud->flist);
+ if (ud->with_sidecars)
+ file_data_sc_free_ci_list(ud->flist);
+ else
+ file_data_free_ci_list(ud->flist);
+
+ /* directory content is always handled including sidecars */
file_data_sc_free_ci_list(ud->content_list);
- if (ud->dir_fd) file_data_sc_free_ci(ud->dir_fd);
+
+ if (ud->dir_fd) file_data_free_ci(ud->dir_fd);
file_util_data_free(ud);
break;
}
ud = file_util_data_new(UTILITY_TYPE_DELETE);
ud->phase = phase;
+
+ ud->with_sidecars = TRUE;
ud->dir_fd = NULL;
ud->flist = flist;
file_util_dialog_run(ud);
}
+static void file_util_write_metadata_full(FileData *source_fd, GList *source_list, GtkWidget *parent, UtilityPhase phase)
+{
+ UtilityData *ud;
+ GList *flist = filelist_copy(source_list);
+
+ if (source_fd)
+ flist = g_list_append(flist, file_data_ref(source_fd));
+
+ if (!flist) return;
+
+ if (!file_data_add_ci_write_metadata_list(flist))
+ {
+ file_util_warn_op_in_progress(_("Can't write metadata"));
+ filelist_free(flist);
+ return;
+ }
+
+ ud = file_util_data_new(UTILITY_TYPE_WRITE_METADATA);
+
+ ud->phase = phase;
+
+ ud->with_sidecars = FALSE; /* operate on individual files, not groups */
+
+ ud->dir_fd = NULL;
+ ud->flist = flist;
+ ud->content_list = NULL;
+ ud->parent = parent;
+
+ ud->messages.title = _("Write metadata");
+ ud->messages.question = _("Write metadata?");
+ ud->messages.desc_flist = _("This will write the changed metadata into the following files");
+ ud->messages.desc_source_fd = "";
+ ud->messages.fail = _("Metadata writting failed");
+
+ file_util_dialog_run(ud);
+}
+
+
static void file_util_move_full(FileData *source_fd, GList *source_list, const gchar *dest_path, GtkWidget *parent, UtilityPhase phase)
{
UtilityData *ud;
ud->phase = phase;
+ ud->with_sidecars = TRUE;
+
ud->dir_fd = NULL;
ud->flist = flist;
ud->content_list = NULL;
ud->phase = phase;
+ ud->with_sidecars = TRUE;
+
ud->dir_fd = NULL;
ud->flist = flist;
ud->content_list = NULL;
ud->phase = phase;
+ ud->with_sidecars = TRUE;
+
ud->dir_fd = NULL;
ud->flist = flist;
ud->content_list = NULL;
if (ud->type == UTILITY_TYPE_FILTER && dest_path == NULL) phase = UTILITY_PHASE_START;
ud->phase = phase;
+
+ ud->with_sidecars = TRUE;
ud->external_command = n;
ud = file_util_data_new(UTILITY_TYPE_DELETE_LINK);
ud->phase = phase;
+ ud->with_sidecars = TRUE;
ud->dir_fd = file_data_ref(fd);
ud->content_list = NULL;
ud->flist = NULL;
ud = file_util_data_new(UTILITY_TYPE_DELETE_FOLDER);
ud->phase = phase;
+ ud->with_sidecars = TRUE;
ud->dir_fd = file_data_ref(fd);
ud->content_list = NULL; /* will be filled by file_util_delete_dir_prepare */
ud->flist = flist = filelist_sort_path(flist);
ud = file_util_data_new(UTILITY_TYPE_RENAME_FOLDER);
ud->phase = phase;
+ ud->with_sidecars = TRUE; /* does not matter, the directory should not have sidecars
+ and the content must be handled including sidecars */
ud->dir_fd = file_data_ref(fd);
ud->flist = NULL;
static void file_util_create_dir_full(FileData *fd, const gchar *dest_path, GtkWidget *parent, UtilityPhase phase)
{
- UtilityData *ud;
+ UtilityData *ud;
ud = file_util_data_new(UTILITY_TYPE_CREATE_FOLDER);
ud->phase = phase;
+ ud->with_sidecars = TRUE;
ud->dir_fd = NULL;
ud->flist = NULL;
file_util_delete_full(source_fd, source_list, parent, options->file_ops.confirm_delete ? UTILITY_PHASE_START : UTILITY_PHASE_ENTERING);
}
+void file_util_write_metadata(FileData *source_fd, GList *source_list, GtkWidget *parent)
+{
+ file_util_write_metadata_full(source_fd, source_list, parent, UTILITY_PHASE_START);
+}
+
void file_util_copy(FileData *source_fd, GList *source_list, const gchar *dest_path, GtkWidget *parent)
{
file_util_copy_full(source_fd, source_list, dest_path, parent, UTILITY_PHASE_START);