Add more darktable options
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
@@ -0,0 +1,265 @@
|
|||||||
|
diff --git a/data/darktableconfig.xml.in b/data/darktableconfig.xml.in
|
||||||
|
index 83eadf8a35..39ed8d43d7 100644
|
||||||
|
--- a/data/darktableconfig.xml.in
|
||||||
|
+++ b/data/darktableconfig.xml.in
|
||||||
|
@@ -1524,6 +1524,22 @@
|
||||||
|
<longdescription>file naming pattern used for a import session</longdescription>
|
||||||
|
</dtconfig>
|
||||||
|
|
||||||
|
+ <dtconfig prefs="import" section="session">
|
||||||
|
+ <name>session/conflict_padding</name>
|
||||||
|
+ <type>int</type>
|
||||||
|
+ <default>2</default>
|
||||||
|
+ <shortdescription>burst file name conflict number padding</shortdescription>
|
||||||
|
+ <longdescription>set the padding length for conflict resolution (e.g., 001, 002).</longdescription>
|
||||||
|
+ </dtconfig>
|
||||||
|
+
|
||||||
|
+ <dtconfig prefs="import" section="session">
|
||||||
|
+ <name>session/import_existing_sidecar</name>
|
||||||
|
+ <type>bool</type>
|
||||||
|
+ <default>true</default>
|
||||||
|
+ <shortdescription>import existing sidecar files</shortdescription>
|
||||||
|
+ <longdescription>import existing sidecar files (XMP, IPTC, etc.) when importing images</longdescription>
|
||||||
|
+ </dtconfig>
|
||||||
|
+
|
||||||
|
<dtconfig>
|
||||||
|
<name>plugins/lighttable/layout</name>
|
||||||
|
<type>int</type>
|
||||||
|
diff --git a/src/common/import_session.c b/src/common/import_session.c
|
||||||
|
index e83ef4de62..4d0c4efa0c 100644
|
||||||
|
--- a/src/common/import_session.c
|
||||||
|
+++ b/src/common/import_session.c
|
||||||
|
@@ -266,48 +266,42 @@ const char *dt_import_session_filename(struct dt_import_session_t *self, gboolea
|
||||||
|
char *pattern = _import_session_filename_pattern();
|
||||||
|
if(pattern == NULL)
|
||||||
|
{
|
||||||
|
- dt_print(DT_DEBUG_ALWAYS, "[import_session] Failed to get session filaname pattern.\n");
|
||||||
|
+ dt_print(DT_DEBUG_ALWAYS, "[import_session] Failed to get session filename pattern.\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ self->vp->retry_count = 0;
|
||||||
|
+
|
||||||
|
/* verify that expanded path and filename yields a unique file */
|
||||||
|
const char *path = dt_import_session_path(self, TRUE);
|
||||||
|
|
||||||
|
if(use_filename)
|
||||||
|
result_fname = g_strdup(self->vp->filename);
|
||||||
|
else
|
||||||
|
- result_fname = _import_session_filename_from_pattern(self, pattern);
|
||||||
|
-
|
||||||
|
- char *fname = g_build_path(G_DIR_SEPARATOR_S, path, result_fname, (char *)NULL);
|
||||||
|
- char *previous_fname = fname;
|
||||||
|
- if(g_file_test(fname, G_FILE_TEST_EXISTS) == TRUE)
|
||||||
|
{
|
||||||
|
- dt_print(DT_DEBUG_ALWAYS, "[import_session] File %s exists.\n", fname);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
- /* file exists, yield a new filename */
|
||||||
|
+ /* generate filename based on the current retry_count */
|
||||||
|
g_free(result_fname);
|
||||||
|
result_fname = _import_session_filename_from_pattern(self, pattern);
|
||||||
|
- fname = g_build_path(G_DIR_SEPARATOR_S, path, result_fname, (char *)NULL);
|
||||||
|
|
||||||
|
- dt_print(DT_DEBUG_ALWAYS, "[import_session] Testing %s.\n", fname);
|
||||||
|
- /* check if same filename was yielded as before */
|
||||||
|
- if(strcmp(previous_fname, fname) == 0)
|
||||||
|
+ char *test_path = g_build_path(G_DIR_SEPARATOR_S, path, result_fname, (char *)NULL);
|
||||||
|
+
|
||||||
|
+ if(g_file_test(test_path, G_FILE_TEST_EXISTS) == TRUE)
|
||||||
|
{
|
||||||
|
- g_free(previous_fname);
|
||||||
|
- g_free(fname);
|
||||||
|
- dt_control_log(_(
|
||||||
|
- "couldn't expand to a unique filename for session, please check your import session settings."));
|
||||||
|
- return NULL;
|
||||||
|
+ dt_print(DT_DEBUG_ALWAYS, "[import_session] File %s exists, retrying.\n", test_path);
|
||||||
|
+ self->vp->retry_count++;
|
||||||
|
+ g_free(test_path);
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ g_free(test_path);
|
||||||
|
+ break;
|
||||||
|
}
|
||||||
|
|
||||||
|
- g_free(previous_fname);
|
||||||
|
- previous_fname = fname;
|
||||||
|
-
|
||||||
|
- } while(g_file_test(fname, G_FILE_TEST_EXISTS) == TRUE);
|
||||||
|
+ } while(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
- g_free(previous_fname);
|
||||||
|
g_free(pattern);
|
||||||
|
|
||||||
|
self->current_filename = result_fname;
|
||||||
|
diff --git a/src/common/variables.c b/src/common/variables.c
|
||||||
|
index 1474cc32e8..820f88414b 100644
|
||||||
|
--- a/src/common/variables.c
|
||||||
|
+++ b/src/common/variables.c
|
||||||
|
@@ -914,6 +914,14 @@ static char *_get_base_value(dt_variables_params_t *params, char **variable)
|
||||||
|
else if(_has_prefix(variable, "DARKTABLE.NAME")
|
||||||
|
|| _has_prefix(variable, "DARKTABLE_NAME"))
|
||||||
|
result = g_strdup(PACKAGE_NAME);
|
||||||
|
+
|
||||||
|
+ else if(_has_prefix(variable, "CONFLICT_PADDING"))
|
||||||
|
+ {
|
||||||
|
+ int pad_length = dt_conf_get_int("session/conflict_padding");
|
||||||
|
+ if(pad_length < 0) pad_length = 0;
|
||||||
|
+ result = g_strdup_printf("%0*u", pad_length, params->retry_count);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// go past what looks like an invalid variable. we only expect to
|
||||||
|
diff --git a/src/common/variables.h b/src/common/variables.h
|
||||||
|
index 86052a9a3d..a5d616a94c 100644
|
||||||
|
--- a/src/common/variables.h
|
||||||
|
+++ b/src/common/variables.h
|
||||||
|
@@ -29,6 +29,9 @@ typedef struct dt_variables_params_t
|
||||||
|
/** used for expanding variables that uses filename $(FILE_FOLDER) $(FILE_NAME) and $(FILE_EXTENSION). */
|
||||||
|
const gchar *filename;
|
||||||
|
|
||||||
|
+ /** used for conflict resolution in filename expansion */
|
||||||
|
+ int retry_count;
|
||||||
|
+
|
||||||
|
/** used for expanding variable $(JOBCODE) */
|
||||||
|
const gchar *jobcode;
|
||||||
|
|
||||||
|
diff --git a/src/control/jobs/control_jobs.c b/src/control/jobs/control_jobs.c
|
||||||
|
index a9fab6f0ea..27bceab782 100644
|
||||||
|
--- a/src/control/jobs/control_jobs.c
|
||||||
|
+++ b/src/control/jobs/control_jobs.c
|
||||||
|
@@ -1566,7 +1566,7 @@ static int32_t dt_control_export_job_run(dt_job_t *job)
|
||||||
|
{
|
||||||
|
// IPTC character encoding not set by user, so we set the default utf8 here
|
||||||
|
settings->metadata_export = dt_util_dstrcat(settings->metadata_export,
|
||||||
|
- "\1%s\1%s",
|
||||||
|
+ "\1%s\1%s",
|
||||||
|
iptc_envelope_characterset,
|
||||||
|
"\x1b%G"); // ESC % G
|
||||||
|
}
|
||||||
|
@@ -2265,6 +2265,59 @@ void dt_control_write_sidecar_files()
|
||||||
|
FALSE));
|
||||||
|
}
|
||||||
|
|
||||||
|
+static gboolean _copy_file(const char *source, const char *destination)
|
||||||
|
+{
|
||||||
|
+ gchar *data = NULL;
|
||||||
|
+ gsize size = 0;
|
||||||
|
+
|
||||||
|
+ if(!g_file_get_contents(source, &data, &size, NULL))
|
||||||
|
+ {
|
||||||
|
+ dt_print(DT_DEBUG_CONTROL, "[import_from] failed to read file `%s`", source);
|
||||||
|
+ return FALSE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if(!g_file_set_contents(destination, data, size, NULL))
|
||||||
|
+ {
|
||||||
|
+ dt_print(DT_DEBUG_CONTROL, "[import_from] failed to write file `%s`", destination);
|
||||||
|
+ g_free(data);
|
||||||
|
+ return FALSE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ g_free(data);
|
||||||
|
+ return TRUE;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void _copy_timestamps(const char *source, const char *destination)
|
||||||
|
+{
|
||||||
|
+ struct stat statbuf;
|
||||||
|
+ if(stat(source, &statbuf) == 0)
|
||||||
|
+ {
|
||||||
|
+#ifdef _WIN32
|
||||||
|
+ struct utimbuf times;
|
||||||
|
+ times.actime = statbuf.st_atime;
|
||||||
|
+ times.modtime = statbuf.st_mtime;
|
||||||
|
+ utime(destination, ×);
|
||||||
|
+#else
|
||||||
|
+ struct timeval times[2];
|
||||||
|
+ times[0].tv_sec = statbuf.st_atime;
|
||||||
|
+ times[1].tv_sec = statbuf.st_mtime;
|
||||||
|
+#ifdef __APPLE__
|
||||||
|
+#ifndef _POSIX_SOURCE
|
||||||
|
+ times[0].tv_usec = statbuf.st_atimespec.tv_nsec * 0.001;
|
||||||
|
+ times[1].tv_usec = statbuf.st_mtimespec.tv_nsec * 0.001;
|
||||||
|
+#else
|
||||||
|
+ times[0].tv_usec = statbuf.st_atimensec * 0.001;
|
||||||
|
+ times[1].tv_usec = statbuf.st_mtimensec * 0.001;
|
||||||
|
+#endif
|
||||||
|
+#else
|
||||||
|
+ times[0].tv_usec = statbuf.st_atim.tv_nsec * 0.001;
|
||||||
|
+ times[1].tv_usec = statbuf.st_mtim.tv_nsec * 0.001;
|
||||||
|
+#endif
|
||||||
|
+ utimes(destination, times);
|
||||||
|
+#endif
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int _control_import_image_copy(const char *filename,
|
||||||
|
char **prev_filename,
|
||||||
|
char **prev_output,
|
||||||
|
@@ -2308,37 +2361,37 @@ static int _control_import_image_copy(const char *filename,
|
||||||
|
g_free(basename);
|
||||||
|
}
|
||||||
|
|
||||||
|
- if(!g_file_set_contents(output, data, size, NULL))
|
||||||
|
+ if(!_copy_file(filename, output))
|
||||||
|
{
|
||||||
|
- dt_print(DT_DEBUG_CONTROL, "[import_from] failed to write file %s\n", output);
|
||||||
|
+ dt_print(DT_DEBUG_CONTROL, "[import_from] failed to copy file %s", filename);
|
||||||
|
res = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
-#ifdef _WIN32
|
||||||
|
- struct utimbuf times;
|
||||||
|
- times.actime = statbuf.st_atime;
|
||||||
|
- times.modtime = statbuf.st_mtime;
|
||||||
|
- utime(output, ×); // set origin file timestamps
|
||||||
|
-#else
|
||||||
|
- struct timeval times[2];
|
||||||
|
- times[0].tv_sec = statbuf.st_atime;
|
||||||
|
- times[1].tv_sec = statbuf.st_mtime;
|
||||||
|
-#ifdef __APPLE__
|
||||||
|
-#ifndef _POSIX_SOURCE
|
||||||
|
- times[0].tv_usec = statbuf.st_atimespec.tv_nsec * 0.001;
|
||||||
|
- times[1].tv_usec = statbuf.st_mtimespec.tv_nsec * 0.001;
|
||||||
|
-#else
|
||||||
|
- times[0].tv_usec = statbuf.st_atimensec * 0.001;
|
||||||
|
- times[1].tv_usec = statbuf.st_mtimensec * 0.001;
|
||||||
|
-#endif
|
||||||
|
-#else
|
||||||
|
- times[0].tv_usec = statbuf.st_atim.tv_nsec * 0.001;
|
||||||
|
- times[1].tv_usec = statbuf.st_mtim.tv_nsec * 0.001;
|
||||||
|
-#endif
|
||||||
|
- utimes(output, times); // set origin file timestamps
|
||||||
|
-#endif
|
||||||
|
+ _copy_timestamps(filename, output);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
+ gboolean import_existing_sidecar = dt_conf_get_bool("session/import_existing_sidecar");
|
||||||
|
+ if(import_existing_sidecar)
|
||||||
|
+ {
|
||||||
|
+ char *xml_filename = g_strdup_printf("%s.xmp", filename);
|
||||||
|
+ if(g_file_test(xml_filename, G_FILE_TEST_EXISTS))
|
||||||
|
+ {
|
||||||
|
+ char *xml_output = g_strdup_printf("%s.xmp", output);
|
||||||
|
+ if(_copy_file(xml_filename, xml_output))
|
||||||
|
+ _copy_timestamps(xml_filename, xml_output);
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ dt_print(DT_DEBUG_CONTROL, "[import_from] failed to copy sidecar %s", xml_filename);
|
||||||
|
+ res = FALSE;
|
||||||
|
+ }
|
||||||
|
+ g_free(xml_output);
|
||||||
|
+ }
|
||||||
|
+ g_free(xml_filename);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if(res)
|
||||||
|
+ {
|
||||||
|
const dt_imgid_t imgid = dt_image_import(dt_import_session_film_id(session),
|
||||||
|
output, FALSE, FALSE);
|
||||||
|
if(!imgid) dt_control_log(_("error loading file `%s'"), output);
|
@@ -4,6 +4,14 @@
|
|||||||
}:
|
}:
|
||||||
{ pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
{
|
{
|
||||||
|
nixpkgs.overlays = [
|
||||||
|
(final: prev: {
|
||||||
|
darktable = prev.darktable.overrideAttrs (oldAttrs: {
|
||||||
|
patches = oldAttrs.patches or [ ] ++ [ ./better-copy-and-import.patch ];
|
||||||
|
});
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
environment.persistence = {
|
environment.persistence = {
|
||||||
"/persist"."${home}/.config/darktable" = { };
|
"/persist"."${home}/.config/darktable" = { };
|
||||||
"/cache"."${home}/.cache/darktable" = { };
|
"/cache"."${home}/.cache/darktable" = { };
|
||||||
@@ -28,6 +36,17 @@
|
|||||||
"rating_one_double_tap" = true;
|
"rating_one_double_tap" = true;
|
||||||
"run_crawler_on_start" = true;
|
"run_crawler_on_start" = true;
|
||||||
"ui_last/theme" = "darktable-elegant-darker";
|
"ui_last/theme" = "darktable-elegant-darker";
|
||||||
|
"ui_last/grouping" = true;
|
||||||
|
"plugins/darkroom/lut3d/def_path" = "${home}/.config/darktable/luts";
|
||||||
|
"opencl" = false;
|
||||||
|
"plugins/lighttable/overlays/1/0" = 0;
|
||||||
|
"plugins/lighttable/overlays/1/1" = 3;
|
||||||
|
"plugins/lighttable/overlays/1/2" = 3;
|
||||||
|
"plugins/darkroom/modulegroups/last_preset" = "modules: all";
|
||||||
|
"session/base_directory_pattern" = "${home}/Pictures/Darktable";
|
||||||
|
"session/filename_pattern" = "$(EXIF.YEAR)-$(EXIF.MONTH)-$(EXIF.DAY)_$(EXIF.HOUR)-$(EXIF.MINUTE)-$(EXIF.SECOND)_$(CONFLICT_PADDING).$(FILE_EXTENSION)";
|
||||||
|
"session/sub_directory_pattern" = "";
|
||||||
|
"setup_import_directory" = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
"darktable/luts".source = "${hald-clut}/HaldCLUT";
|
"darktable/luts".source = "${hald-clut}/HaldCLUT";
|
||||||
|
Reference in New Issue
Block a user