From 2d695364898ae18134be6224dbd7542607f4fa48 Mon Sep 17 00:00:00 2001 From: "U-DESKTOP-HQME86J\\marco" Date: Sun, 22 Mar 2020 17:50:51 +0100 Subject: [PATCH 01/70] fixes and code cleaning --- contrib/ext_editor.lua | 121 ++++++++++++++++++----------------------- 1 file changed, 54 insertions(+), 67 deletions(-) diff --git a/contrib/ext_editor.lua b/contrib/ext_editor.lua index 4575542..8cbd55f 100644 --- a/contrib/ext_editor.lua +++ b/contrib/ext_editor.lua @@ -3,61 +3,60 @@ DESCRIPTION ext_editor.lua - edit images with external editors - This script provides helpers to edit image files with programs external to darktable. - It adds: - - a new target storage "collection". Image exported will be reimported to collection for - further edit with external programs - - a new lighttable module "external editors", to select a program from a list of up to - - 9 external editors and run it on a selected image (adjust this limit by changing MAX_EDITORS) - - a set of lua preferences in order to configure name and path of up to 9 external editors - - a set of lua shortcuts in order to quick launch the external editors + This script provides helpers to edit image files with programs external to darktable. It adds: + - a new target storage "collection". Image exported will be reimported to collection for + further edit with external programs + - a new lighttable module "external editors", to select a program from a list of up to + - 9 external editors and run it on a selected image (adjust this limit by changing MAX_EDITORS) + - a set of lua preferences in order to configure name and path of up to 9 external editors + - a set of lua shortcuts in order to quick launch the external editors USAGE * require this script from main lua file - -- setup -- - * in "preferences/lua options" configure name and path/command of external programs - * note that if a program name is left empty, that and all following entries will be ignored - * in "preferences/shortcuts/lua" configure shortcuts for external programs (optional) - * whenever programs preferences are changed, in lighttable/external editors, press "update list" + -- setup -- + * in "preferences/lua options" configure name and path/command of external programs + * note that if a program name is left empty, that and all following entries will be ignored + * in "preferences/shortcuts/lua" configure shortcuts for external programs (optional) + * whenever programs preferences are changed, in lighttable/external editors, press "update list" - -- use -- - * in the export dialog choose "collection" and select the format and bit depth for the - exported image - * press "export" - * the exported image will be imported into collection and grouped with the original image + -- use -- + * in the export dialog choose "collection" and select the format and bit depth for the + exported image + * press "export" + * the exported image will be imported into collection and grouped with the original image + + * select an image for editing with en external program, and: + * in lighttable/external editors, select program and press "edit" + * edit the image with the external editor, overwite the file, quit the external program + * the selected image will be updated + or + * in lighttable/external editors, select program and press "edit a copy" + * edit the image with the external editor, overwite the file, quit the external program + * a copy of the selected image will be created and updated + or + * in lighttable select target storage "collection" + * enter in darkroom + * to create an export or a copy press CRTL+E + * use the shortcut to edit the current image with the corresponding external editor + * overwite the file, quit the external program + * the darkroom view will be updated - * select an image for editing with en external program, and: - * in lighttable/external editors, select program and press "edit" - * edit the image with the external editor, overwite the file, quit the external program - * the selected image will be updated - or - * in lighttable/external editors, select program and press "edit a copy" - * edit the image with the external editor, overwite the file, quit the external program - * a copy of the selected image will be created and updated - or - * in lighttable select target storage "collection" - * enter in darkroom - * to create an export or a copy press CRTL+E - * use the shortcut to edit the current image with the corresponding external editor - * overwite the file, quit the external program - * the darkroom view will be updated - - * warning: mouseover on lighttable/filmstrip will prevail on current image - * this is the default DT behavior, not a bug of this script + * warning: mouseover on lighttable/filmstrip will prevail on current image + * this is the default DT behavior, not a bug of this script - CAVEATS - * MAC compatibility not tested + CAVEATS + * MAC compatibility not tested TODO - * send multiple images to the same program, maybe + * send multiple images to the same program, maybe - BUGS, COMMENTS, SUGGESTIONS + BUGS, COMMENTS, SUGGESTIONS * send to Marco Carrarini, marco.carrarini@gmail.com - CHANGES + CHANGES * 20191224 - initial version - * 20191227 - added button "update list", better error handling, fixed bug with groups/tags in "edit" + * 20191227 - added button "update list", better error handling, fixed bug with groups/tags in "edit" ]] @@ -73,7 +72,7 @@ local MODULE_NAME = "ext_editor" -- check API version -du.check_min_api_version("5.0.2", MODULE_NAME) -- darktable 3.0 +du.check_min_api_version("5.0.2", MODULE_NAME) -- darktable 3.x -- OS compatibility @@ -88,7 +87,7 @@ local function _(msgid) end -- maximum number of external programs, can be increased to necessity -local MAX_EDITORS = 9 +local MAX_EDITORS = 11 -- number of valid entries in the list of external programs local n_entries @@ -98,6 +97,7 @@ local n_entries local allowed_file_types = {"JPG", "jpg", "JPEG", "jpeg", "TIF", "tif", "TIFF", "tiff", "EXR", "exr", "PNG", "png"} +-- last used editor initialization if not dt.preferences.read(MODULE_NAME, "initialized", "bool") then dt.preferences.write(MODULE_NAME, "lastchoice", "integer", 0) dt.preferences.write(MODULE_NAME, "initialized", "bool", true) @@ -163,11 +163,7 @@ local function OpenWith(images, choice, copy) local bin = program_paths[choice] local friendly_name = program_names[choice] - -- check if external program executable exists, return if not - if not df.check_if_bin_exists(bin) then - dt.print(friendly_name.._(" not found")) - return - end + if dt.configuration.running_os == "macos" then bin = "open -W -a "..bin end -- image to be edited local image @@ -175,7 +171,7 @@ local function OpenWith(images, choice, copy) local name = image.path..PS..image.filename -- check if image format is allowed - local file_ext = df.get_filetype (image.filename) + local file_ext = df.get_filetype(image.filename) local allowed = false for i,v in pairs(allowed_file_types) do if v == file_ext then @@ -207,11 +203,7 @@ local function OpenWith(images, choice, copy) if copy then -- create unique filename - while df.check_if_file_exists(df.sanitize_filename(new_name)) do - new_name = df.filename_increment(new_name) - -- limit to 50 more exports of the original export - if string.match(df.get_basename(new_name), "_%d%d$") == "_50" then break end - end + new_name = df.create_unique_filename(new_name) -- physical copy, check result, return if error local copy_success = df.file_copy(name, new_name) @@ -306,7 +298,7 @@ local function program_shortcut(event, shortcut) -- export images and reimport in collection ----------------------------------- local function export2collection(storage, image_table, extra_data) - local new_name, new_image, result + local temp_name, new_name, new_image, move_success for image, temp_name in pairs(image_table) do @@ -314,11 +306,7 @@ local function export2collection(storage, image_table, extra_data) -- create unique filename new_name = image.path..PS..df.get_filename(temp_name) - while df.check_if_file_exists(df.sanitize_filename(new_name)) do - new_name = df.filename_increment(new_name) - -- limit to 50 more exports of the original export - if string.match(df.get_basename(new_name), "_%d%d$") == "_50" then break end - end + new_name = df.create_unique_filename(new_name) -- move image to collection folder, check result, return if error move_success = df.file_move(temp_name, new_name) @@ -336,12 +324,6 @@ local function export2collection(storage, image_table, extra_data) end --- register new storage ------------------------------------------------------- --- note that placing this declaration later makes the export selected module --- not to remember the choice "collection" when restarting DT, don't know why -dt.register_storage("exp2coll", _("collection"), null, export2collection) - - -- combobox, with variable number of entries ---------------------------------- local combobox = dt.new_widget("combobox") { label = _("choose program"), @@ -415,11 +397,16 @@ dt.register_lib( UpdateProgramList(combobox, button_edit, button_edit_copy, false) +-- register new storage ------------------------------------------------------- +dt.register_storage("exp2coll", _("collection"), nil, export2collection) + + -- register the new preferences ----------------------------------------------- for i = MAX_EDITORS, 1, -1 do dt.preferences.register(MODULE_NAME, "program_path_"..i, "file", _("executable for external editor ")..i, _("select executable for external editor") , _("(None)")) + dt.preferences.register(MODULE_NAME, "program_name_"..i, "string", _("name of external editor ")..i, _("friendly name of external editor"), "") From a8e5a9b45341a141843614fcb80fba8e168cf953 Mon Sep 17 00:00:00 2001 From: "U-DESKTOP-HQME86J\\marco" Date: Sun, 22 Mar 2020 17:55:15 +0100 Subject: [PATCH 02/70] default no. of editors --- contrib/ext_editor.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/ext_editor.lua b/contrib/ext_editor.lua index 8cbd55f..19e711c 100644 --- a/contrib/ext_editor.lua +++ b/contrib/ext_editor.lua @@ -87,7 +87,7 @@ local function _(msgid) end -- maximum number of external programs, can be increased to necessity -local MAX_EDITORS = 11 +local MAX_EDITORS = 9 -- number of valid entries in the list of external programs local n_entries From 33b99a97e4af3d6ae13b43f420c6d9a1d75a1702 Mon Sep 17 00:00:00 2001 From: Noah Date: Thu, 16 Apr 2020 17:51:09 -0700 Subject: [PATCH 03/70] initial module minus style picker --- contrib/exportLUT.lua | 131 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 contrib/exportLUT.lua diff --git a/contrib/exportLUT.lua b/contrib/exportLUT.lua new file mode 100644 index 0000000..c2688ed --- /dev/null +++ b/contrib/exportLUT.lua @@ -0,0 +1,131 @@ +--[[ + This file is part of darktable, + copyright (c) 2016 Tobias Jakobs + + darktable is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + darktable is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with darktable. If not, see . +]] +--[[ + +USAGE +* require this script from your main lua file + To do this add this line to the file .config/darktable/luarc: +require "moduleExample" + +* it creates a new example lighttable module + +More informations about building user interface elements: +https://www.darktable.org/usermanual/ch09.html.php#lua_gui_example +And about new_widget here: +https://www.darktable.org/lua-api/index.html.php#darktable_new_widget +]] + +local dt = require "darktable" +local du = require "lib/dtutils" + +du.check_min_api_version("3.0.0", "moduleExample") + +-- add a new lib + +local combobox = dt.new_widget("combobox"){label = "on conflict", value = 1, "skip", "overwrite"} + +--https://www.darktable.org/lua-api/ar01s02s54.html.php + +local file_chooser_button = dt.new_widget("file_chooser_button") +{ + title = "Identity_file_chooser", -- The title of the window when choosing a file + value = "", -- The currently selected file + is_directory = false -- True if the file chooser button only allows directories to be selecte +} + +local export_chooser_button = dt.new_widget("file_chooser_button") +{ + title = "Export_location_chooser", -- The title of the window when choosing a file + value = "", -- The currently selected file + is_directory = true -- True if the file chooser button only allows directories to be selecte +} + +local identity_label = dt.new_widget("label"){ + label = "choose the identity haldclut file" +} + +local output_label = dt.new_widget("label"){ + label = "choose the output location" +} + +local separator = dt.new_widget("separator"){} + +if (dt.configuration.api_version_major >= 6) then + local section_label = dt.new_widget("section_label") + { + label = "MySectionLabel" + } + + dt.register_lib( + "export haldclut", -- Module name + "export haldclut", -- name + true, -- expandable + false, -- resetable + {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, -- containers + identity_label, + file_chooser_button, + output_label, + export_chooser_button, + combobox, + separator, + dt.new_widget("box") -- widget + { + orientation = "vertical", + dt.new_widget("button") + { + label = "export", + clicked_callback = function (_) + dt.print("Button clicked") + end + }, + section_label + }, + nil,-- view_enter + nil -- view_leave + ) +else + dt.register_lib( + "export haldclut", -- Module name + "export haldclut", -- name + true, -- expandable + false, -- resetable + {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, -- containers + dt.new_widget("box") -- widget + { + orientation = "vertical", + identity_label, + file_chooser_button, + output_label, + export_chooser_button, + combobox, + separator, + dt.new_widget("button") + { + label = "export", + clicked_callback = function (_) + dt.print("Button clicked") + end + } + }, + nil,-- view_enter + nil -- view_leave + ) +end + +-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua +-- kate: hl Lua; From 792e782e8c101f7a333b583674feb4aaa81e8b37 Mon Sep 17 00:00:00 2001 From: Noah Date: Thu, 16 Apr 2020 22:27:57 -0700 Subject: [PATCH 04/70] basic frontend --- contrib/exportLUT.lua | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/contrib/exportLUT.lua b/contrib/exportLUT.lua index c2688ed..adb0534 100644 --- a/contrib/exportLUT.lua +++ b/contrib/exportLUT.lua @@ -33,7 +33,7 @@ https://www.darktable.org/lua-api/index.html.php#darktable_new_widget local dt = require "darktable" local du = require "lib/dtutils" -du.check_min_api_version("3.0.0", "moduleExample") +du.check_min_api_version("3.0.0", "exportLUT") -- add a new lib @@ -63,7 +63,27 @@ local output_label = dt.new_widget("label"){ label = "choose the output location" } -local separator = dt.new_widget("separator"){} +local separator = dt.new_widget("separator"){ + +} + +local function create_lut(style, haldclut) + haldclut.reset + dt.styles.apply(style, haldclut) +end + +local function export_lut(haldclut) + +end + +local function export_luts() + identity = dt.database.import(file_chooser_button) + for style_num, style in ipairs(dt.styles) do + identity = create_lut(style, identity) + export_lut(identity) + dt.print(style.name) + end +end if (dt.configuration.api_version_major >= 6) then local section_label = dt.new_widget("section_label") @@ -117,9 +137,7 @@ else dt.new_widget("button") { label = "export", - clicked_callback = function (_) - dt.print("Button clicked") - end + clicked_callback = export_luts } }, nil,-- view_enter From fe97e2965484384122bbdd8931918ff432b27d63 Mon Sep 17 00:00:00 2001 From: Noah Date: Thu, 16 Apr 2020 22:59:33 -0700 Subject: [PATCH 05/70] Working? version --- contrib/exportLUT.lua | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/contrib/exportLUT.lua b/contrib/exportLUT.lua index adb0534..35981ab 100644 --- a/contrib/exportLUT.lua +++ b/contrib/exportLUT.lua @@ -35,12 +35,12 @@ local du = require "lib/dtutils" du.check_min_api_version("3.0.0", "exportLUT") --- add a new lib +-- Thanks Kevin Ertel for this trick +local os_path_seperator = '/' +if dt.configuration.running_os == 'windows' then os_path_seperator = '\\' end local combobox = dt.new_widget("combobox"){label = "on conflict", value = 1, "skip", "overwrite"} ---https://www.darktable.org/lua-api/ar01s02s54.html.php - local file_chooser_button = dt.new_widget("file_chooser_button") { title = "Identity_file_chooser", -- The title of the window when choosing a file @@ -64,24 +64,20 @@ local output_label = dt.new_widget("label"){ } local separator = dt.new_widget("separator"){ - } -local function create_lut(style, haldclut) - haldclut.reset - dt.styles.apply(style, haldclut) -end - -local function export_lut(haldclut) - -end - local function export_luts() - identity = dt.database.import(file_chooser_button) + identity = dt.database.import(file_chooser_button.value) for style_num, style in ipairs(dt.styles) do - identity = create_lut(style, identity) - export_lut(identity) - dt.print(style.name) + + identity:reset() + dt.styles.apply(style, identity) + + io_lut = dt.new_format("png") + dt.print(export_chooser_button.value .. os_path_seperator .. style.name) + io_lut:write_image(identity, export_chooser_button.value .. os_path_seperator .. style.name) + + dt.print(export_chooser_button.value .. os_path_seperator .. style.name) end end From 28b9073010eb5cf26281a18ed057d10467ab0994 Mon Sep 17 00:00:00 2001 From: Noah Date: Thu, 16 Apr 2020 23:42:51 -0700 Subject: [PATCH 06/70] Code and UI cleanup --- contrib/exportLUT.lua | 111 ++++++++++++++++-------------------------- 1 file changed, 41 insertions(+), 70 deletions(-) diff --git a/contrib/exportLUT.lua b/contrib/exportLUT.lua index 35981ab..ab63fce 100644 --- a/contrib/exportLUT.lua +++ b/contrib/exportLUT.lua @@ -1,6 +1,6 @@ --[[ This file is part of darktable, - copyright (c) 2016 Tobias Jakobs + copyright (c) 2020 Noah Clarke darktable is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,18 +16,14 @@ along with darktable. If not, see . ]] --[[ +Add the following line to .config/darktable/luarc to enable this lightable module: + require "exportLut" -USAGE -* require this script from your main lua file - To do this add this line to the file .config/darktable/luarc: -require "moduleExample" +Given a haldCLUT identity file this script generates haldCLUTS from all the user's +styles and exports them to a location of their choosing. -* it creates a new example lighttable module - -More informations about building user interface elements: -https://www.darktable.org/usermanual/ch09.html.php#lua_gui_example -And about new_widget here: -https://www.darktable.org/lua-api/index.html.php#darktable_new_widget +Warning: during export if a naming collision occurs the older file is automatically +overwritten silently. ]] local dt = require "darktable" @@ -35,24 +31,20 @@ local du = require "lib/dtutils" du.check_min_api_version("3.0.0", "exportLUT") --- Thanks Kevin Ertel for this trick +-- Thanks Kevin Ertel for this bit local os_path_seperator = '/' if dt.configuration.running_os == 'windows' then os_path_seperator = '\\' end -local combobox = dt.new_widget("combobox"){label = "on conflict", value = 1, "skip", "overwrite"} - -local file_chooser_button = dt.new_widget("file_chooser_button") -{ - title = "Identity_file_chooser", -- The title of the window when choosing a file - value = "", -- The currently selected file - is_directory = false -- True if the file chooser button only allows directories to be selecte +local file_chooser_button = dt.new_widget("file_chooser_button"){ + title = "Identity_file_chooser", + value = "", + is_directory = false } -local export_chooser_button = dt.new_widget("file_chooser_button") -{ - title = "Export_location_chooser", -- The title of the window when choosing a file - value = "", -- The currently selected file - is_directory = true -- True if the file chooser button only allows directories to be selecte +local export_chooser_button = dt.new_widget("file_chooser_button"){ + title = "Export_location_chooser", + value = "", + is_directory = true } local identity_label = dt.new_widget("label"){ @@ -63,7 +55,9 @@ local output_label = dt.new_widget("label"){ label = "choose the output location" } -local separator = dt.new_widget("separator"){ +local export_button = dt.new_widget("button"){ + label = "export", + clicked_callback = export_luts } local function export_luts() @@ -74,72 +68,49 @@ local function export_luts() dt.styles.apply(style, identity) io_lut = dt.new_format("png") - dt.print(export_chooser_button.value .. os_path_seperator .. style.name) - io_lut:write_image(identity, export_chooser_button.value .. os_path_seperator .. style.name) - - dt.print(export_chooser_button.value .. os_path_seperator .. style.name) + dt.print("Exporting: " .. export_chooser_button.value .. os_path_seperator .. style.name .. ".png") + io_lut:write_image(identity, export_chooser_button.value .. os_path_seperator .. style.name .. ".png") end + identity:reset() end if (dt.configuration.api_version_major >= 6) then - local section_label = dt.new_widget("section_label") - { - label = "MySectionLabel" - } dt.register_lib( - "export haldclut", -- Module name - "export haldclut", -- name - true, -- expandable - false, -- resetable - {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, -- containers + "export haldclut", + "export haldclut", + true, + false, + {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, identity_label, file_chooser_button, output_label, export_chooser_button, - combobox, - separator, - dt.new_widget("box") -- widget + dt.new_widget("box") { orientation = "vertical", - dt.new_widget("button") - { - label = "export", - clicked_callback = function (_) - dt.print("Button clicked") - end - }, - section_label + export_button }, - nil,-- view_enter - nil -- view_leave + nil, + nil ) else dt.register_lib( - "export haldclut", -- Module name - "export haldclut", -- name - true, -- expandable - false, -- resetable - {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, -- containers - dt.new_widget("box") -- widget + "export haldclut", + "export haldclut", + true, + false, + {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, + dt.new_widget("box") { orientation = "vertical", identity_label, file_chooser_button, output_label, export_chooser_button, - combobox, - separator, - dt.new_widget("button") - { - label = "export", - clicked_callback = export_luts - } + export_button }, - nil,-- view_enter - nil -- view_leave + nil, + nil ) -end - --- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua --- kate: hl Lua; +end \ No newline at end of file From 286ef7766302819b90b6d892afe462d110cefbf3 Mon Sep 17 00:00:00 2001 From: Noah Date: Sun, 19 Apr 2020 00:36:47 -0700 Subject: [PATCH 07/70] Some error checking and warnings --- contrib/exportLUT.lua | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/contrib/exportLUT.lua b/contrib/exportLUT.lua index ab63fce..65a4f57 100644 --- a/contrib/exportLUT.lua +++ b/contrib/exportLUT.lua @@ -55,25 +55,33 @@ local output_label = dt.new_widget("label"){ label = "choose the output location" } -local export_button = dt.new_widget("button"){ - label = "export", - clicked_callback = export_luts +local warning_label = dt.new_widget("label"){ + label = "WARNING: files may be silently overwritten" } local function export_luts() identity = dt.database.import(file_chooser_button.value) - for style_num, style in ipairs(dt.styles) do - + if(type(identity) ~= "userdata") then + dt.print("Invalid identity lut file") + else + for style_num, style in ipairs(dt.styles) do + + identity:reset() + dt.styles.apply(style, identity) + + io_lut = dt.new_format("png") + dt.print("Exporting: " .. export_chooser_button.value .. os_path_seperator .. style.name .. ".png") + io_lut:write_image(identity, export_chooser_button.value .. os_path_seperator .. style.name .. ".png") + end identity:reset() - dt.styles.apply(style, identity) - - io_lut = dt.new_format("png") - dt.print("Exporting: " .. export_chooser_button.value .. os_path_seperator .. style.name .. ".png") - io_lut:write_image(identity, export_chooser_button.value .. os_path_seperator .. style.name .. ".png") end - identity:reset() end +local export_button = dt.new_widget("button"){ + label = "export", + clicked_callback = export_luts +} + if (dt.configuration.api_version_major >= 6) then dt.register_lib( @@ -86,6 +94,7 @@ if (dt.configuration.api_version_major >= 6) then file_chooser_button, output_label, export_chooser_button, + warning_label, dt.new_widget("box") { orientation = "vertical", @@ -108,6 +117,7 @@ else file_chooser_button, output_label, export_chooser_button, + warning_label, export_button }, nil, From 01184bee721d217dc1d1e29d60e7e40bded6756f Mon Sep 17 00:00:00 2001 From: Noah Date: Mon, 4 May 2020 23:58:52 -0700 Subject: [PATCH 08/70] Updated API version check and forced PNG to 16 bits --- contrib/exportLUT.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/contrib/exportLUT.lua b/contrib/exportLUT.lua index 65a4f57..e2f599e 100644 --- a/contrib/exportLUT.lua +++ b/contrib/exportLUT.lua @@ -29,7 +29,7 @@ overwritten silently. local dt = require "darktable" local du = require "lib/dtutils" -du.check_min_api_version("3.0.0", "exportLUT") +du.check_min_api_version("5.0.0", "exportLUT") -- Thanks Kevin Ertel for this bit local os_path_seperator = '/' @@ -70,8 +70,9 @@ local function export_luts() dt.styles.apply(style, identity) io_lut = dt.new_format("png") - dt.print("Exporting: " .. export_chooser_button.value .. os_path_seperator .. style.name .. ".png") + io_lut.bpp = 16 io_lut:write_image(identity, export_chooser_button.value .. os_path_seperator .. style.name .. ".png") + dt.print("Exported: " .. export_chooser_button.value .. os_path_seperator .. style.name .. ".png") end identity:reset() end From 5709cfebd4b6f1304732b509e0905c23e48d944d Mon Sep 17 00:00:00 2001 From: Noah Date: Tue, 5 May 2020 00:02:47 -0700 Subject: [PATCH 09/70] Remove unneeded API check --- contrib/exportLUT.lua | 51 ++++++++++++------------------------------- 1 file changed, 14 insertions(+), 37 deletions(-) diff --git a/contrib/exportLUT.lua b/contrib/exportLUT.lua index e2f599e..da187f1 100644 --- a/contrib/exportLUT.lua +++ b/contrib/exportLUT.lua @@ -83,45 +83,22 @@ local export_button = dt.new_widget("button"){ clicked_callback = export_luts } -if (dt.configuration.api_version_major >= 6) then - - dt.register_lib( - "export haldclut", - "export haldclut", - true, - false, - {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, +dt.register_lib( + "export haldclut", + "export haldclut", + true, + false, + {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, + dt.new_widget("box") + { + orientation = "vertical", identity_label, file_chooser_button, output_label, export_chooser_button, warning_label, - dt.new_widget("box") - { - orientation = "vertical", - export_button - }, - nil, - nil - ) -else - dt.register_lib( - "export haldclut", - "export haldclut", - true, - false, - {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, - dt.new_widget("box") - { - orientation = "vertical", - identity_label, - file_chooser_button, - output_label, - export_chooser_button, - warning_label, - export_button - }, - nil, - nil - ) -end \ No newline at end of file + export_button + }, + nil, + nil +) \ No newline at end of file From 4455347930947099fa2f67a9eb86d05ed5d08cf3 Mon Sep 17 00:00:00 2001 From: Noah Date: Wed, 6 May 2020 01:14:34 -0700 Subject: [PATCH 10/70] Exporting luts now creates a job --- contrib/exportLUT.lua | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/contrib/exportLUT.lua b/contrib/exportLUT.lua index da187f1..eaacf44 100644 --- a/contrib/exportLUT.lua +++ b/contrib/exportLUT.lua @@ -59,21 +59,38 @@ local warning_label = dt.new_widget("label"){ label = "WARNING: files may be silently overwritten" } +local function end_job(job) + job.valid = false +end + local function export_luts() - identity = dt.database.import(file_chooser_button.value) + local identity = dt.database.import(file_chooser_button.value) if(type(identity) ~= "userdata") then dt.print("Invalid identity lut file") else + local job = dt.gui.create_job('Exporting styles as haldCLUTs', true, end_job) + + local size = 1 + + for style_num, style in ipairs(dt.styles) do + size = size + 1 + end + + local count = 0 for style_num, style in ipairs(dt.styles) do identity:reset() dt.styles.apply(style, identity) - io_lut = dt.new_format("png") + local io_lut = dt.new_format("png") io_lut.bpp = 16 io_lut:write_image(identity, export_chooser_button.value .. os_path_seperator .. style.name .. ".png") + count = count + 1 + job.percent = count / size dt.print("Exported: " .. export_chooser_button.value .. os_path_seperator .. style.name .. ".png") end + dt.print("Done exporting haldCLUTs") + job.valid = false identity:reset() end end From aef7363beee9a8f88fa4983c401b347ea395175e Mon Sep 17 00:00:00 2001 From: Noah Date: Wed, 6 May 2020 13:19:12 -0700 Subject: [PATCH 11/70] make 8bit not 16bit luts (extra depth uneeded) --- contrib/exportLUT.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/exportLUT.lua b/contrib/exportLUT.lua index eaacf44..25741bc 100644 --- a/contrib/exportLUT.lua +++ b/contrib/exportLUT.lua @@ -83,7 +83,7 @@ local function export_luts() dt.styles.apply(style, identity) local io_lut = dt.new_format("png") - io_lut.bpp = 16 + io_lut.bpp = 8 io_lut:write_image(identity, export_chooser_button.value .. os_path_seperator .. style.name .. ".png") count = count + 1 job.percent = count / size From 23131a301bcd2770e44b3e60c217a7b77805d229 Mon Sep 17 00:00:00 2001 From: Noah Clarke Date: Thu, 7 May 2020 12:15:31 -0700 Subject: [PATCH 12/70] Fix include path --- contrib/exportLUT.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/exportLUT.lua b/contrib/exportLUT.lua index 25741bc..6d29647 100644 --- a/contrib/exportLUT.lua +++ b/contrib/exportLUT.lua @@ -17,7 +17,7 @@ ]] --[[ Add the following line to .config/darktable/luarc to enable this lightable module: - require "exportLut" + require "contrib/exportLut" Given a haldCLUT identity file this script generates haldCLUTS from all the user's styles and exports them to a location of their choosing. @@ -118,4 +118,4 @@ dt.register_lib( }, nil, nil -) \ No newline at end of file +) From a02176fc6331dd6f4c8c73fdf3b3cc98a0eb753d Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sat, 30 May 2020 20:12:39 -0400 Subject: [PATCH 13/70] Added instructions for using script_manager.lua as the luarc file. --- README.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6b0e20f..49551e5 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,7 @@ are met as well as providing an easy update path. Single scripts listed as stand ### snap packages -The snap version of darktable comes with lua included starting with version 2.4.3snap2. It is currently in the edge channel, but should reach the stable channel soon. +The snap version of darktable comes with lua included starting with version 2.4.3snap2. Ensure git is installed on your system. If it isn't, use the package manager to install it. Then open a terminal and: @@ -138,8 +138,6 @@ Ensure git is installed on your system. If it isn't, use the package manager to Ensure git is installed on your system. Git can be obtained from https://gitforwindows.org/, as well as other places. If you use the gitforwindows.org distribution, install the Git Bash Shell also as it will aid in debugging the scripts if necessary. Then open a command prompt and run: -Open a command prompt. - cd %LOCALAPPDATA%\darktable git clone https://github.com/darktable-org/lua-scripts.git lua @@ -154,11 +152,19 @@ You can also create or add lines to the luarc file from the command line: `echo 'require "contrib/gimp"' > ~/.config/darktable/luarc` to create the file with a gimp entry\ or `echo 'require "contrib/hugin"' >> ~/.config/darktable/luarc` to add an entry for hugin. +Alteratively you can use script_manager.lua as your luarc file. script_manager.lua provides a point and click interface for managing the lua scripts. To use it: + + ln -s $HOME/.config/darktable/lua/tools/script_manager.lua $HOME/.config/darktable/luarc + On windows from a command prompt: `echo require "contrib/gimp" > %LOCALAPPDATA%\darktable\luarc` to create the file with a gimp entry\ or `echo require "contrib/hugin" >> %LOCALAPPDATA%\darktable\luarc` to add an entry for hugin. +Alteratively you can use script_manager.lua as your luarc file. script_manager.lua provides a point and click interface for managing the lua scripts. To use it: + + copy %LOCALAPPDATA%\darktable\lua\tools\script_manager.lua %LOCALAPPDATA%\darktable\luarc + ## Disabling To disable a script open the luarc file in your text editor and insert `--` at the start of the line containing the script you wish to disable, then save the file. From 33f91af1af429500686025114fe4d49e9ab744a1 Mon Sep 17 00:00:00 2001 From: Tobias Scheck Date: Sat, 6 Jun 2020 12:39:26 +0200 Subject: [PATCH 14/70] add photils plugin --- README.md | 1 + contrib/photils.lua | 416 ++++++++++++++++++++++++++++ locale/de_DE/LC_MESSAGES/photils.po | 83 ++++++ 3 files changed, 500 insertions(+) create mode 100644 contrib/photils.lua create mode 100644 locale/de_DE/LC_MESSAGES/photils.po diff --git a/README.md b/README.md index 49551e5..2381dbc 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,7 @@ LabelsToTags|Yes|LMW|Apply tags based on color labels and ratings OpenInExplorer|No|LMW|Open the selected images in the system file manager passport_guide|Yes|LMW|Add passport cropping guide to darkroom crop tool pdf_slideshow|No|LM|Export images to a PDF slideshow +[photils](https://github.com/scheckmedia/photils-dt)|No|LM|Automatic tag suggestions for your images quicktag|Yes|LMW|Create shortcuts for quickly applying tags rate_group|Yes|LMW|Apply or remove a star rating from grouped images rename-tags|Yes|LMW|Change a tag name diff --git a/contrib/photils.lua b/contrib/photils.lua new file mode 100644 index 0000000..102bd4d --- /dev/null +++ b/contrib/photils.lua @@ -0,0 +1,416 @@ +--[[ photils Auto Tagging plugin + copyright (c) 2020 Tobias Scheck + + darktable is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + darktable is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with darktable. If not, see . +--]] + +--[[ + A darktable plugin which tries to predict keywords based on the selected image. + This plugin uses photils-cli to handle this task. Photils-cli is an application + which passes the image through a neural network and generates a feature vector. + This feature vector will be used to find similar images in a self-hosted online + database and the corresponding tags. The usage of the feature vector has this advantage + that at no time your selected image will leave the PC. Rather a representation + of the image is sent. + + ADDITIONAL SOFTWARE NEEDED FOR THIS SCRIPT + * photils-cli - https://github.com/scheckmedia/photils-cli + + USAGE + * require this script from your main lua file + To do this add this line to the file .config/darktable/luarc: + require "contrib/photils" + * Select an image + * Press "Get Tags" + * Select the tags you want from a list of suggestions + * Press "Attach .. Tags" to add the selected tags to your image +--]] + +local dt = require "darktable" +local du = require "lib/dtutils" +local df = require "lib/dtutils.file" +local dtsys = require "lib/dtutils.system" + +local MODULE_NAME = "photils" +du.check_min_api_version("5.0.0", MODULE_NAME) + +local PS = dt.configuration.running_os == "windows" and "\\" or "/" +local gettext = dt.gettext +gettext.bindtextdomain(MODULE_NAME, + dt.configuration.config_dir .. PS .. "lua" .. PS .. "locale" .. PS) + +local exporter = dt.new_format("jpeg") +exporter.quality = 80 +exporter.max_height = 224 +exporter.max_width = 224 + +-- helper functions + +local function _(msgid) + return gettext.dgettext(MODULE_NAME, msgid) +end + +local function num_keys(tbl) + local num = 0 + for _ in pairs(tbl) do num = num + 1 end + return num +end + +local function has_key(tbl, value) + for k, _ in pairs(tbl) do + if k == value then + return true + end + end + + return false +end + +local photils_installed = df.check_if_bin_exists("photils-cli") + +--[[ + local state object + + maybe per_page is a preference variable but I think 10 + is a good value for the ui +]] +local PHOTILS = { + tags = {}, + page = 1, + per_page = 10, + selected_tags = {}, + in_pagination = false, + tagged_image = "" +} + +local GUI = { + container = dt.new_widget("box") { + orientation = "vertical", + sensitive = true, + dt.new_widget("button") { + label = _("Get Tags"), + sensitive = photils_installed, + clicked_callback = function() PHOTILS.on_tags_clicked() end + }, + reset_callback = function() PHOTILS.on_reset(true) end + }, + stack = dt.new_widget("stack"), + prev_button = dt.new_widget("button") { + label = "<", + sensitive = false, + clicked_callback = function() + PHOTILS.page = PHOTILS.page - 1 + PHOTILS.paginate() + end + }, + next_button = dt.new_widget("button") { + label = ">", + sensitive = false, + clicked_callback = function() + PHOTILS.page = PHOTILS.page + 1 + PHOTILS.paginate() + end + }, + tag_box = dt.new_widget("box") {orientation = "vertical"}, + tag_view = dt.new_widget("box") {orientation = "vertical"}, + page_label = dt.new_widget("label") {label = ""}, + error_view = dt.new_widget("box") {orientation = "vertical"}, + warning_label = dt.new_widget("label") { + label = "" + }, + restart_required_label = dt.new_widget("label") { + label = _("requires a restart to be applied") + }, + attach_button = dt.new_widget("button") { + label = "", + sensitive = false, + clicked_callback = function() PHOTILS.attach_tags() end + }, + confidence_slider = dt.new_widget("slider") { + step = 1, + digits = 0, + value = 90, + hard_max = 100, + hard_min = 0, + soft_max = 100, + soft_min = 0, + label = _("Min Confidence Value") + }, + warning = dt.new_widget("label") +} + +function PHOTILS.image_changed() + local current_image = tostring(dt.gui.selection()[1]) + if current_image ~= PHOTILS.tagged_image then + if PHOTILS.tagged_image ~= "" then + PHOTILS.tagged_image_has_changed() + end + + PHOTILS.tagged_image = tostring(current_image) + end +end + +function PHOTILS.tagged_image_has_changed() + GUI.warning.label = _( + "The suggested tags were not generated\n for the currently selected image!") +end + +function PHOTILS.paginate() + PHOTILS.in_pagination = true + local num_pages = math.ceil(#PHOTILS.tags / PHOTILS.per_page) + GUI.page_label.label = string.format(_(" Page %s of %s "), PHOTILS.page, + num_pages) + + if PHOTILS.page <= 1 then + PHOTILS.page = 1 + GUI.prev_button.sensitive = false + else + GUI.prev_button.sensitive = true + end + + if PHOTILS.page > num_pages - 1 then + PHOTILS.page = num_pages + GUI.next_button.sensitive = false + else + GUI.next_button.sensitive = true + end + + local offset = ((PHOTILS.page - 1) * PHOTILS.per_page) + 1 + local tag_index = 1 + for i = offset, offset + PHOTILS.per_page - 1, 1 do + local tag = PHOTILS.tags[i] + GUI.tag_box[tag_index].value = has_key(PHOTILS.selected_tags, tag) + + if tag then + GUI.tag_box[tag_index].label = tag + GUI.tag_box[tag_index].sensitive = true + else + GUI.tag_box[tag_index].label = "" + GUI.tag_box[tag_index].sensitive = false + end + tag_index = tag_index + 1 + end + + PHOTILS.in_pagination = false +end + +function PHOTILS.attach_tags() + local image = dt.gui.selection()[1] + for tag, _ in pairs(PHOTILS.selected_tags) do + local dt_tag = dt.tags.create(tag) + dt.tags.attach(dt_tag, image) + end + + dt.print(_("Tags successfully attached to image")) +end + +function PHOTILS.get_tmp_file() + local tmp_file = os.tmpname() + if dt.configuration.running_os == "windows" then + tmp_file = dt.configuration.tmp_dir .. tmp_file -- windows os.tmpname() defaults to root directory + end + + local f = io.open(tmp_file, "w") + if not f then + dt.print_log(string.format(_("Error writing to `%s`"), tmp_file)) + os.remove(tmp_file) + return nil + end + + return tmp_file +end + +function PHOTILS.get_tags(image, with_export) + local tmp_file = PHOTILS.get_tmp_file() + local in_arg = df.sanitize_filename(tostring(image)) + local out_arg = df.sanitize_filename(tmp_file) + local executable = photils_installed + + if dt.configuration.running_os == "macos" then + executable = executable .. "/Contents/MacOS/photils-cli" + end + + if with_export then + dt.print_log("use export to for prediction") + local export_file = PHOTILS.get_tmp_file() + exporter:write_image(image, export_file) + in_arg = df.sanitize_filename(tostring(export_file)) + end + + local command = executable .. " -c " .. " -i " .. in_arg .. " -o " .. out_arg + + local ret = dtsys.external_command(command) + if ret > 0 then + dt.print_error(string.format("command %s returned error code %d", command, ret)) + os.remove(tmp_file) + + -- try to export the image and run tagging + if not with_export then + return PHOTILS.get_tags(image, true) + end + + return false + end + + for i = #PHOTILS.tags, 1, -1 do + PHOTILS.tags[i] = nil + end + + for tag in io.lines(tmp_file) do + local splitted = du.split(tag, ":") + if 100 * tonumber(splitted[2]) >= GUI.confidence_slider.value then + PHOTILS.tags[#PHOTILS.tags + 1] = splitted[1] + end + end + + dt.print(string.format(_("%s found %d tags for your image"), MODULE_NAME, + #PHOTILS.tags)) + os.remove(tmp_file) + + return true +end + +function PHOTILS.on_tags_clicked() + PHOTILS.page = 1 + GUI.warning.label = "" + + PHOTILS.on_reset(false) + + local images = dt.gui.selection() + + if #images == 0 then + dt.print(_("No image selected.")) + dt.control.sleep(2000) + else + if #images > 1 then + dt.print(_("This plugin can only handle a single image.")) + dt.gui.selection({images[1]}) + dt.control.sleep(2000) + end + + if not PHOTILS.get_tags(images[1], true) then + local msg = string.format(_("%s failed, see terminal output for details"), MODULE_NAME) + GUI.warning_label.label = msg + GUI.stack.active = GUI.error_view + dt.print(msg) + return + end + + if #PHOTILS.tags == 0 then + local msg = string.format(_("No tags where found"), MODULE_NAME) + GUI.warning_label.label = msg + GUI.stack.active = GUI.error_view + return + end + + GUI.stack.active = GUI.tag_view + PHOTILS.paginate() + end +end + +function PHOTILS.tag_selected(tag_button) + if PHOTILS.in_pagination then return end + + if tag_button.value then + PHOTILS.selected_tags[tag_button.label] = tag_button.label + else + PHOTILS.selected_tags[tag_button.label] = nil + end + + local num_selected = num_keys(PHOTILS.selected_tags) + if num_selected == 0 then + GUI.attach_button.label = "" + GUI.attach_button.sensitive = false + else + GUI.attach_button.label = string.format(_("Attach %d Tags"), + num_selected) + GUI.attach_button.sensitive = true + end +end + +function PHOTILS.on_reset(with_view) + if with_view then GUI.stack.active = 1 end + + for k, _ in pairs(PHOTILS.selected_tags) do + PHOTILS.selected_tags[k] = nil + end + + for _, v in ipairs(GUI.tag_box) do + v.value = false + end + + GUI.attach_button.label = "" + GUI.attach_button.sensitive = false +end + +-- add a fix number of buttons +for _ = 1, PHOTILS.per_page, 1 do + local btn_tag = dt.new_widget("check_button") { + label = "", + sensitive = false, + clicked_callback = PHOTILS.tag_selected + } + + table.insert(GUI.tag_box, btn_tag) +end + +if not photils_installed then + GUI.warning_label.label = _("photils-cli not found") + dt.print_log(_("photils-cli not found")) +else + GUI.warning_label.label = _("Select an image, click \"Get Tags\" and get \nsuggestions for tags.") +end + +GUI.pagination = dt.new_widget("box") { + orientation = "horizontal", + GUI.prev_button, + GUI.page_label, + GUI.next_button +} + + +table.insert(GUI.error_view, GUI.warning_label) +if not photils_installed then + table.insert(GUI.error_view, df.executable_path_widget({"photils-cli"})) + table.insert(GUI.error_view, GUI.restart_required_label) +end +table.insert(GUI.stack, GUI.error_view) +table.insert(GUI.stack, GUI.tag_view) + +table.insert(GUI.tag_view, GUI.pagination) +table.insert(GUI.tag_view, GUI.tag_box) +table.insert(GUI.tag_view, GUI.attach_button) +table.insert(GUI.tag_view, GUI.warning) + +table.insert(GUI.container, GUI.confidence_slider) +table.insert(GUI.container, GUI.stack) + +GUI.stack.active = 1 + +local plugin_display_views = { + [dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}, + [dt.gui.views.darkroom] = {"DT_UI_CONTAINER_PANEL_LEFT_CENTER", 100} +} + +-- dt.control.dispatch(PHOTILS.image_changed) +dt.register_event("mouse-over-image-changed",PHOTILS.image_changed) +dt.register_lib(MODULE_NAME, + "photils autotagger", + true, + true, + plugin_display_views, + GUI.container, + nil, + nil +) diff --git a/locale/de_DE/LC_MESSAGES/photils.po b/locale/de_DE/LC_MESSAGES/photils.po new file mode 100644 index 0000000..f1480a1 --- /dev/null +++ b/locale/de_DE/LC_MESSAGES/photils.po @@ -0,0 +1,83 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: Lua photils\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-12 13:12+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../../../contrib/photils.lua:97 +msgid "Get Tags" +msgstr "Hole Stichwörter" + +#: ../../../contrib/photils.lua:128 +msgid "requires a restart to be applied" +msgstr "erfordert die Neustart um angewendet zu werden" + +#: ../../../contrib/photils.lua:155 +msgid "" +"The suggested tags were not generated\n" +" for the currently selected image!" +msgstr "" +"Die vorgeschlagenen Stichwörter wurden für das\n" +"aktuell ausgewählte Bild nicht generiert!" + +#: ../../../contrib/photils.lua:161 +#, lua-format +msgid " Page %s of %s " +msgstr " Seite %s von %s " + +#: ../../../contrib/photils.lua:204 +msgid "Tags successfully attached to image" +msgstr "Stichwörter erfolgreich an Bild angefügt" + +#: ../../../contrib/photils.lua:215 +#, lua-format +msgid "Error writing to `%s`" +msgstr "Fehler beim Schreiben in `%s`" + +#: ../../../contrib/photils.lua:229 +#, lua-format +msgid "%s failed, see terminal output for details" +msgstr "%s fehlgeschlagen, siehe Terminal-Ausgabe für Details" + +#: ../../../contrib/photils.lua:243 +#, lua-format +msgid "%s found %d tags for your image" +msgstr "%s gefunden %d-Stichwörter für Ihr Bild" + +#: ../../../contrib/photils.lua:257 +msgid "No image selected." +msgstr "Kein Bild ausgewählt." + +#: ../../../contrib/photils.lua:262 +msgid "This plugin can only handle a single image." +msgstr "Dieses Plugin kann nur ein einziges Bild verarbeiten." + +#: ../../../contrib/photils.lua:293 +#, lua-format +msgid "Attach %d Tags" +msgstr "%d-Stichwörter anhängen" + +#: ../../../contrib/photils.lua:326 ../../../contrib/photils.lua:327 +msgid "photils-cli not found" +msgstr "photils-cli nicht gefunden" + +#: ../../../contrib/photils.lua:329 +msgid "" +"Select an image, click \"Get Tags\" and get \n" +"suggestions for tags." +msgstr "" +"Wählen Sie ein Bild aus, drücken Sie \"Hole Stichwörter\"\n" +" und erhalten Sie Vorschläge für Stichwörter." From 60fa4b9ee02fe67b4844ff639a7cd77db3030818 Mon Sep 17 00:00:00 2001 From: Tobias Scheck Date: Tue, 9 Jun 2020 08:50:26 +0200 Subject: [PATCH 15/70] update description --- contrib/photils.lua | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/contrib/photils.lua b/contrib/photils.lua index 102bd4d..f4a046e 100644 --- a/contrib/photils.lua +++ b/contrib/photils.lua @@ -16,13 +16,11 @@ --]] --[[ - A darktable plugin which tries to predict keywords based on the selected image. - This plugin uses photils-cli to handle this task. Photils-cli is an application - which passes the image through a neural network and generates a feature vector. - This feature vector will be used to find similar images in a self-hosted online - database and the corresponding tags. The usage of the feature vector has this advantage - that at no time your selected image will leave the PC. Rather a representation - of the image is sent. + A darktable plugin that tries to predict keywords based on the selected image. + This plugin uses photils-cli to handle this task. Photils-cli is an application + that passes the image through a neural network, classifies it, and extracts the + suggested tags. Everything happens offline without the need that your data are + sent over the internet. ADDITIONAL SOFTWARE NEEDED FOR THIS SCRIPT * photils-cli - https://github.com/scheckmedia/photils-cli From 1c9042c496e2b798ec08b53e7b4d9c7cf0da3bc4 Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Tue, 9 Jun 2020 20:22:02 -0400 Subject: [PATCH 16/70] Added a sanitize_lua function to the string library for sanitizing strings of lua "magic" characters before using the string in a string function that involves matching. script_manager needs the path to the lua directory sanitized of lua "magic" characters to prevent failure to extract the category and script names. --- lib/dtutils/string.lua | 26 ++++++++++++++++++++++++++ tools/script_manager.lua | 3 ++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/lib/dtutils/string.lua b/lib/dtutils/string.lua index f58f38c..e3cc817 100644 --- a/lib/dtutils/string.lua +++ b/lib/dtutils/string.lua @@ -269,5 +269,31 @@ function dtutils_string.sanitize(str) end end +dtutils_string.libdoc.functions["sanitize_lua"] = { + Name = [[sanitize_lua]], + Synopsis = [[escape lua 'magic' characters from a pattern string]], + Usage = [[local ds = require "lib/dtutils.string" + + local result = ds.sanitize_lua(str) + str - string - the string that needs to be made safe]], + Description = [[sanitize_lua escapes lua 'magic' characters so that + a string may be used in lua string/patten matching.]], + Return_Value = [[result - string - a lua pattern safe string]], + Limitations = [[]], + Example = [[]], + See_Also = [[]], + Reference = [[]], + License = [[]], + Copyright = [[]], +} + +function dtutils_string.sanitize_lua(str) + str = string.gsub(str, "%-", "%%-") + str = string.gsub(str, "%(", "%%(") + str = string.gsub(str, "%)", "%%)") + return str +end + + return dtutils_string diff --git a/tools/script_manager.lua b/tools/script_manager.lua index 9759b88..0946ae5 100644 --- a/tools/script_manager.lua +++ b/tools/script_manager.lua @@ -39,6 +39,7 @@ local dt = require "darktable" local du = require "lib/dtutils" local df = require "lib/dtutils.file" +local ds = require "lib/dtutils.string" local dtsys = require "lib/dtutils.system" local gettext = dt.gettext @@ -215,7 +216,7 @@ local function scan_scripts() -- scan the scripts local output = io.popen(find_cmd) for line in output:lines() do - local l = string.gsub(line, LUA_DIR .. PS, "") -- strip the lua dir off + local l = string.gsub(line, ds.sanitize_lua(LUA_DIR) .. PS, "") -- strip the lua dir off local script_file = l:sub(1,-5) if not string.match(script_file, "script_manager") then -- let's not include ourself if not string.match(script_file, "plugins") then -- skip plugins From fd97ac18da3c87a039b756a512a9a18aa15f3cf9 Mon Sep 17 00:00:00 2001 From: Tobias Scheck Date: Wed, 10 Jun 2020 14:48:18 +0200 Subject: [PATCH 17/70] add comments for clarification; formatting --- contrib/photils.lua | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/contrib/photils.lua b/contrib/photils.lua index f4a046e..f498903 100644 --- a/contrib/photils.lua +++ b/contrib/photils.lua @@ -160,8 +160,7 @@ function PHOTILS.image_changed() end function PHOTILS.tagged_image_has_changed() - GUI.warning.label = _( - "The suggested tags were not generated\n for the currently selected image!") + GUI.warning.label = _("The suggested tags were not generated\n for the currently selected image!") end function PHOTILS.paginate() @@ -184,6 +183,13 @@ function PHOTILS.paginate() GUI.next_button.sensitive = true end + --[[ + calculates the start positon in the tag array based on the current page + and takes N tags from that array to show these in darktable + e.g. page 1 goes from 1 to 10, page 2 from 11 to 20 a.s.o. + the paginaton approach is related to a problem with the dynamic addition + of mutliple widgets https://github.com/darktable-org/darktable/issues/4934#event-3318100463 + ]]-- local offset = ((PHOTILS.page - 1) * PHOTILS.per_page) + 1 local tag_index = 1 for i = offset, offset + PHOTILS.per_page - 1, 1 do From 2e27b812d6f619737d37ab3823545fce5937bba4 Mon Sep 17 00:00:00 2001 From: Tobias Scheck Date: Wed, 10 Jun 2020 14:48:27 +0200 Subject: [PATCH 18/70] fix spelling --- locale/de_DE/LC_MESSAGES/photils.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locale/de_DE/LC_MESSAGES/photils.po b/locale/de_DE/LC_MESSAGES/photils.po index f1480a1..0acd02a 100644 --- a/locale/de_DE/LC_MESSAGES/photils.po +++ b/locale/de_DE/LC_MESSAGES/photils.po @@ -23,7 +23,7 @@ msgstr "Hole Stichwörter" #: ../../../contrib/photils.lua:128 msgid "requires a restart to be applied" -msgstr "erfordert die Neustart um angewendet zu werden" +msgstr "erfordert einen Neustart um angewendet zu werden" #: ../../../contrib/photils.lua:155 msgid "" From 26d97b8cdf2c427878c76c7df10bb3fc05360890 Mon Sep 17 00:00:00 2001 From: GLLM Date: Thu, 11 Jun 2020 22:06:00 +0200 Subject: [PATCH 19/70] Update OpenInExplorer.lua Add the possibility to define a shortcut for this LUA script. --- contrib/OpenInExplorer.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/contrib/OpenInExplorer.lua b/contrib/OpenInExplorer.lua index d456911..496bc79 100644 --- a/contrib/OpenInExplorer.lua +++ b/contrib/OpenInExplorer.lua @@ -108,4 +108,9 @@ if proper_install then function() open_in_fmanager(act_os, fmng_cmd[act_os]) end, _("Opens the file manager at the selected image's location") ) + dt.register_event( + "shortcut", + function(event, shortcut) open_in_fmanager(act_os, fmng_cmd[act_os]) end, + "OpenInExplorer" + ) end From 1378441dfa74fa72f8cce5afbdba895eee071bd3 Mon Sep 17 00:00:00 2001 From: Tobias Scheck Date: Sun, 14 Jun 2020 07:47:28 +0200 Subject: [PATCH 20/70] change labels to lower case to fit darktable style --- contrib/photils.lua | 14 +++++++------- locale/de_DE/LC_MESSAGES/photils.po | 28 +++++++++------------------- 2 files changed, 16 insertions(+), 26 deletions(-) diff --git a/contrib/photils.lua b/contrib/photils.lua index f498903..39b71b9 100644 --- a/contrib/photils.lua +++ b/contrib/photils.lua @@ -30,7 +30,7 @@ To do this add this line to the file .config/darktable/luarc: require "contrib/photils" * Select an image - * Press "Get Tags" + * Press "get tags" * Select the tags you want from a list of suggestions * Press "Attach .. Tags" to add the selected tags to your image --]] @@ -97,7 +97,7 @@ local GUI = { orientation = "vertical", sensitive = true, dt.new_widget("button") { - label = _("Get Tags"), + label = _("get tags"), sensitive = photils_installed, clicked_callback = function() PHOTILS.on_tags_clicked() end }, @@ -143,7 +143,7 @@ local GUI = { hard_min = 0, soft_max = 100, soft_min = 0, - label = _("Min Confidence Value") + label = _("min confidence value") }, warning = dt.new_widget("label") } @@ -166,7 +166,7 @@ end function PHOTILS.paginate() PHOTILS.in_pagination = true local num_pages = math.ceil(#PHOTILS.tags / PHOTILS.per_page) - GUI.page_label.label = string.format(_(" Page %s of %s "), PHOTILS.page, + GUI.page_label.label = string.format(_(" page %s of %s "), PHOTILS.page, num_pages) if PHOTILS.page <= 1 then @@ -312,7 +312,7 @@ function PHOTILS.on_tags_clicked() end if #PHOTILS.tags == 0 then - local msg = string.format(_("No tags where found"), MODULE_NAME) + local msg = string.format(_("no tags where found"), MODULE_NAME) GUI.warning_label.label = msg GUI.stack.active = GUI.error_view return @@ -337,7 +337,7 @@ function PHOTILS.tag_selected(tag_button) GUI.attach_button.label = "" GUI.attach_button.sensitive = false else - GUI.attach_button.label = string.format(_("Attach %d Tags"), + GUI.attach_button.label = string.format(_("attach %d tags"), num_selected) GUI.attach_button.sensitive = true end @@ -373,7 +373,7 @@ if not photils_installed then GUI.warning_label.label = _("photils-cli not found") dt.print_log(_("photils-cli not found")) else - GUI.warning_label.label = _("Select an image, click \"Get Tags\" and get \nsuggestions for tags.") + GUI.warning_label.label = _("Select an image, click \"get tags\" and get \nsuggestions for tags.") end GUI.pagination = dt.new_widget("box") { diff --git a/locale/de_DE/LC_MESSAGES/photils.po b/locale/de_DE/LC_MESSAGES/photils.po index 0acd02a..b81dbc7 100644 --- a/locale/de_DE/LC_MESSAGES/photils.po +++ b/locale/de_DE/LC_MESSAGES/photils.po @@ -17,15 +17,15 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../../../contrib/photils.lua:97 -msgid "Get Tags" -msgstr "Hole Stichwörter" +msgid "get tags" +msgstr "hole stichwörter" -#: ../../../contrib/photils.lua:128 msgid "requires a restart to be applied" msgstr "erfordert einen Neustart um angewendet zu werden" -#: ../../../contrib/photils.lua:155 +msgid "min confidence value" +msgstr "min vertrauenswert" + msgid "" "The suggested tags were not generated\n" " for the currently selected image!" @@ -33,48 +33,38 @@ msgstr "" "Die vorgeschlagenen Stichwörter wurden für das\n" "aktuell ausgewählte Bild nicht generiert!" -#: ../../../contrib/photils.lua:161 #, lua-format -msgid " Page %s of %s " -msgstr " Seite %s von %s " +msgid " page %s of %s " +msgstr " seite %s von %s " -#: ../../../contrib/photils.lua:204 msgid "Tags successfully attached to image" msgstr "Stichwörter erfolgreich an Bild angefügt" -#: ../../../contrib/photils.lua:215 #, lua-format msgid "Error writing to `%s`" msgstr "Fehler beim Schreiben in `%s`" -#: ../../../contrib/photils.lua:229 #, lua-format msgid "%s failed, see terminal output for details" msgstr "%s fehlgeschlagen, siehe Terminal-Ausgabe für Details" -#: ../../../contrib/photils.lua:243 #, lua-format msgid "%s found %d tags for your image" msgstr "%s gefunden %d-Stichwörter für Ihr Bild" -#: ../../../contrib/photils.lua:257 msgid "No image selected." msgstr "Kein Bild ausgewählt." -#: ../../../contrib/photils.lua:262 msgid "This plugin can only handle a single image." msgstr "Dieses Plugin kann nur ein einziges Bild verarbeiten." -#: ../../../contrib/photils.lua:293 #, lua-format -msgid "Attach %d Tags" -msgstr "%d-Stichwörter anhängen" +msgid "attach %d tags" +msgstr "%d stichwörter anhängen" -#: ../../../contrib/photils.lua:326 ../../../contrib/photils.lua:327 msgid "photils-cli not found" msgstr "photils-cli nicht gefunden" -#: ../../../contrib/photils.lua:329 msgid "" "Select an image, click \"Get Tags\" and get \n" "suggestions for tags." From 72bd66d3f567a885e060baf94c893257ef1f1e10 Mon Sep 17 00:00:00 2001 From: Tobias Scheck Date: Sun, 14 Jun 2020 08:57:17 +0200 Subject: [PATCH 21/70] add option to display confidence value, add notice that windows version is not available yet --- contrib/photils.lua | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/contrib/photils.lua b/contrib/photils.lua index 39b71b9..85a2275 100644 --- a/contrib/photils.lua +++ b/contrib/photils.lua @@ -23,12 +23,13 @@ sent over the internet. ADDITIONAL SOFTWARE NEEDED FOR THIS SCRIPT - * photils-cli - https://github.com/scheckmedia/photils-cli + * photils-cli - https://github.com/scheckmedia/photils-cli at the moment only + available for Linux and MacOS USAGE * require this script from your main lua file - To do this add this line to the file .config/darktable/luarc: - require "contrib/photils" + To do this add this line to the file .config/darktable/luarc: + require "contrib/photils" * Select an image * Press "get tags" * Select the tags you want from a list of suggestions @@ -85,6 +86,7 @@ local photils_installed = df.check_if_bin_exists("photils-cli") ]] local PHOTILS = { tags = {}, + confidences = {}, page = 1, per_page = 10, selected_tags = {}, @@ -194,9 +196,15 @@ function PHOTILS.paginate() local tag_index = 1 for i = offset, offset + PHOTILS.per_page - 1, 1 do local tag = PHOTILS.tags[i] + local conf = PHOTILS.confidences[i] + GUI.tag_box[tag_index].value = has_key(PHOTILS.selected_tags, tag) if tag then + if dt.preferences.read(MODULE_NAME, "show_confidence", "bool") then + tag = tag .. string.format(" (%.3f)", conf) + end + GUI.tag_box[tag_index].label = tag GUI.tag_box[tag_index].sensitive = true else @@ -269,12 +277,14 @@ function PHOTILS.get_tags(image, with_export) for i = #PHOTILS.tags, 1, -1 do PHOTILS.tags[i] = nil + PHOTILS.confidences[i] = nil end for tag in io.lines(tmp_file) do local splitted = du.split(tag, ":") if 100 * tonumber(splitted[2]) >= GUI.confidence_slider.value then PHOTILS.tags[#PHOTILS.tags + 1] = splitted[1] + PHOTILS.confidences[#PHOTILS.confidences+1] = splitted[2] end end @@ -327,7 +337,13 @@ function PHOTILS.tag_selected(tag_button) if PHOTILS.in_pagination then return end if tag_button.value then - PHOTILS.selected_tags[tag_button.label] = tag_button.label + local tag = tag_button.label + if dt.preferences.read(MODULE_NAME, "show_confidence", "bool") then + local idx = string.find(tag, "%(") - 2 + tag = string.sub(tag, 0, idx) + end + + PHOTILS.selected_tags[tag] = tag else PHOTILS.selected_tags[tag_button.label] = nil end @@ -407,7 +423,15 @@ local plugin_display_views = { [dt.gui.views.darkroom] = {"DT_UI_CONTAINER_PANEL_LEFT_CENTER", 100} } --- dt.control.dispatch(PHOTILS.image_changed) + +-- uses photils: prefix because script settings are all together and not seperated by script +dt.preferences.register(MODULE_NAME, + "show_confidence", + "bool", + _("photils: show confidence value"), + _("if enabled, the confidence value for each tag is displayed"), + true) + dt.register_event("mouse-over-image-changed",PHOTILS.image_changed) dt.register_lib(MODULE_NAME, "photils autotagger", From 87502fb17f4f85442e8f48c0054cfa05cf69c8b4 Mon Sep 17 00:00:00 2001 From: Tobias Scheck Date: Mon, 15 Jun 2020 11:16:14 +0200 Subject: [PATCH 22/70] move function to create temp files to dtutils/file.lua --- contrib/photils.lua | 20 ++-------------- lib/dtutils/file.lua | 55 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 45 insertions(+), 30 deletions(-) diff --git a/contrib/photils.lua b/contrib/photils.lua index 85a2275..1c72f4b 100644 --- a/contrib/photils.lua +++ b/contrib/photils.lua @@ -227,24 +227,8 @@ function PHOTILS.attach_tags() dt.print(_("Tags successfully attached to image")) end -function PHOTILS.get_tmp_file() - local tmp_file = os.tmpname() - if dt.configuration.running_os == "windows" then - tmp_file = dt.configuration.tmp_dir .. tmp_file -- windows os.tmpname() defaults to root directory - end - - local f = io.open(tmp_file, "w") - if not f then - dt.print_log(string.format(_("Error writing to `%s`"), tmp_file)) - os.remove(tmp_file) - return nil - end - - return tmp_file -end - function PHOTILS.get_tags(image, with_export) - local tmp_file = PHOTILS.get_tmp_file() + local tmp_file = df.create_tmp_file() local in_arg = df.sanitize_filename(tostring(image)) local out_arg = df.sanitize_filename(tmp_file) local executable = photils_installed @@ -255,7 +239,7 @@ function PHOTILS.get_tags(image, with_export) if with_export then dt.print_log("use export to for prediction") - local export_file = PHOTILS.get_tmp_file() + local export_file = df.create_tmp_file() exporter:write_image(image, export_file) in_arg = df.sanitize_filename(tostring(export_file)) end diff --git a/lib/dtutils/file.lua b/lib/dtutils/file.lua index 9fa2c26..423e834 100644 --- a/lib/dtutils/file.lua +++ b/lib/dtutils/file.lua @@ -44,7 +44,7 @@ dtutils_file.libdoc.functions["check_if_bin_exists"] = { bin - string - the binary to check for]], Description = [[check_if_bin_exists checks to see if the specified binary exists. check_if_bin_exists first checks to see if a preference for the binary has been - registered and uses that if found. The presence of the file is verified, then + registered and uses that if found. The presence of the file is verified, then quoted and returned. If no preference is specified and the operating system is linux then the which command is used to check for a binary in the path. If found that path is returned. If no binary is found, false is returned.]], @@ -61,7 +61,7 @@ function dtutils_file.check_if_bin_exists(bin) local result = false local path = nil - if string.match(bin, "/") or string.match(bin, "\\") then + if string.match(bin, "/") or string.match(bin, "\\") then path = bin else path = dtutils_file.get_executable_path_preference(bin) @@ -233,7 +233,7 @@ function dtutils_file.check_if_file_exists(filepath) local p = io.popen("if exist " .. dtutils_file.sanitize_filename(filepath) .. " (echo 'yes') else (echo 'no')") local ans = p:read("*all") p:close() - if string.match(ans, "yes") then + if string.match(ans, "yes") then result = true end -- result = os.execute('if exist "'..filepath..'" (cmd /c exit 0) else (cmd /c exit 1)') @@ -383,8 +383,8 @@ dtutils_file.libdoc.functions["filename_increment"] = { local result = df.filename_increment(filepath) filepath - string - filename to increment]], - Description = [[filename_increment solves the problem of filename confllict by adding an - increment to the filename. If the supplied filename has no increment then + Description = [[filename_increment solves the problem of filename confllict by adding an + increment to the filename. If the supplied filename has no increment then "01" is added to the basename. If the filename already has an increment, then 1 is added to it and the filename returned.]], Return_Value = [[result - string - the incremented filename]], @@ -436,7 +436,7 @@ dtutils_file.libdoc.functions["create_unique_filename"] = { filepath - string - the path and filename requested]], Description = [[create_unique_filename takes a requested filepath and checks to see if it exists. If if doesn't then it's returned intact. If it already exists, then a two - digit increment is added to the filename and it is tested again. The increment keeps + digit increment is added to the filename and it is tested again. The increment keeps increasing until either a unique filename is found or there have been 100 attempts.]], Return_Value = [[result - string - the incremented filename]], Limitations = [[create_unique_filename will only attempt 100 increments.]], @@ -515,7 +515,7 @@ dtutils_file.libdoc.functions["executable_path_widget"] = { local widget = df.executable_path_widget(executables) executables - table - a table of strings that are executable names]], Description = [[executable_path_widget takes a table of executable names - and builds a set of file selector widgets to get the path to the executable. + and builds a set of file selector widgets to get the path to the executable. The resulting widgets are wrapped in a box widget and returned.]], Return_Value = [[widget - widget - a widget containing a file selector widget for each executable.]], @@ -530,10 +530,10 @@ dtutils_file.libdoc.functions["executable_path_widget"] = { function dtutils_file.executable_path_widget(executables) local box_widgets = {} table.insert(box_widgets, dt.new_widget("section_label"){label = "select executable(s)"}) - for _, executable in pairs(executables) do + for _, executable in pairs(executables) do table.insert(box_widgets, dt.new_widget("label"){label = "select " .. executable .. " executable"}) local path = dtutils_file.get_executable_path_preference(executable) - if not path then + if not path then path = "" end table.insert(box_widgets, dt.new_widget("file_chooser_button"){ @@ -562,7 +562,7 @@ dtutils_file.libdoc.functions["sanitize_filename"] = { local sanitized_filename = df.sanitize_filename(filename) filename - string - a filepath and filename]], Description = [[sanitize_file places quotes around the filename in an - operating system specific manner. The result is safe to pass as + operating system specific manner. The result is safe to pass as an argument to the operating system.]], Return_Value = [[sanitized_filename - string - quoted filename]], Limitations = [[]], @@ -584,7 +584,7 @@ dtutils_file.libdoc.functions["mkdir"] = { df.mkdir(path) path - string - a directory path]], - Description = [[mkdir creates directories if not already exists. It + Description = [[mkdir creates directories if not already exists. It create whole parents subtree if needed ]], Return_Value = [[path - string - a directory path]], @@ -596,7 +596,7 @@ dtutils_file.libdoc.functions["mkdir"] = { Copyright = [[]], } -function dtutils_file.mkdir(path) +function dtutils_file.mkdir(path) if not dtutils_file.check_if_file_exists(path) then local mkdir_cmd = dt.configuration.running_os == "windows" and "mkdir" or "mkdir -p" return dsys.external_command(mkdir_cmd.." "..path) @@ -627,6 +627,37 @@ function dtutils_file.rmdir(path) return dsys.external_command(rm_cmd.." "..path) end +dtutils_file.libdoc.functions["create_tmp_file"] = { + Name = [[create_tmp_file]], + Synopsis = [[creates a temporary file]], + Usage = [[local df = require "lib/dtutils.file + + local result = df.create_tmp_file()]], + Description = [[create_tmp_file can be used to create temporary files]], + Return_Value = [[result - string - path to the created temporary file.]], + Limitations = [[]], + Example = [[]], + See_Also = [[]], + Reference = [[]], + License = [[]], + Copyright = [[]], +} + +function dtutils_file.create_tmp_file() + local tmp_file = os.tmpname() + if dt.configuration.running_os == "windows" then + tmp_file = dt.configuration.tmp_dir .. tmp_file -- windows os.tmpname() defaults to root directory + end + + local f = io.open(tmp_file, "w") + if not f then + log.msg(log.error, string.format("Error writing to `%s`", tmp_file)) + os.remove(tmp_file) + return nil + end + + return tmp_file +end return dtutils_file From 71e72b688f74c217462373d966b2251138c36426 Mon Sep 17 00:00:00 2001 From: Noah Date: Tue, 16 Jun 2020 01:50:59 -0700 Subject: [PATCH 23/70] Exported luts now have folder hierarchy --- contrib/exportLUT.lua | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/contrib/exportLUT.lua b/contrib/exportLUT.lua index 6d29647..dd452aa 100644 --- a/contrib/exportLUT.lua +++ b/contrib/exportLUT.lua @@ -28,12 +28,16 @@ overwritten silently. local dt = require "darktable" local du = require "lib/dtutils" +local df = require("lib/dtutils.file") +local ds = require("lib/dtutils.system") du.check_min_api_version("5.0.0", "exportLUT") -- Thanks Kevin Ertel for this bit local os_path_seperator = '/' if dt.configuration.running_os == 'windows' then os_path_seperator = '\\' end +local mkdir_command = 'mkdir -p ' +if dt.configuration.running_os == 'windows' then mkdir_command = 'mkdir ' end local file_chooser_button = dt.new_widget("file_chooser_button"){ title = "Identity_file_chooser", @@ -63,6 +67,18 @@ local function end_job(job) job.valid = false end +local function output_path(style_name, job) + local output_location = export_chooser_button.value .. os_path_seperator .. style_name .. ".png" + output_location = string.gsub(output_location, "|", os_path_seperator) + local output_dir = string.reverse(output_location) + output_dir = string.gsub(output_dir, ".-" .. os_path_seperator, os_path_seperator, 1) + output_dir = string.reverse(output_dir) + if(output_dir ~= "") then + df.mkdir(df.sanitize_filename(output_dir)) + end + return output_location +end + local function export_luts() local identity = dt.database.import(file_chooser_button.value) if(type(identity) ~= "userdata") then @@ -81,13 +97,13 @@ local function export_luts() identity:reset() dt.styles.apply(style, identity) - local io_lut = dt.new_format("png") io_lut.bpp = 8 - io_lut:write_image(identity, export_chooser_button.value .. os_path_seperator .. style.name .. ".png") + + io_lut:write_image(identity, output_path(style.name, job)) count = count + 1 job.percent = count / size - dt.print("Exported: " .. export_chooser_button.value .. os_path_seperator .. style.name .. ".png") + dt.print("Exported: " .. output_path(style.name, job)) end dt.print("Done exporting haldCLUTs") job.valid = false From 802c17d5905dafc1bf30223a9e0f08db8931ccd7 Mon Sep 17 00:00:00 2001 From: Noah Date: Tue, 16 Jun 2020 01:59:43 -0700 Subject: [PATCH 24/70] Added translated text --- contrib/exportLUT.lua | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/contrib/exportLUT.lua b/contrib/exportLUT.lua index dd452aa..5d85bdc 100644 --- a/contrib/exportLUT.lua +++ b/contrib/exportLUT.lua @@ -31,6 +31,8 @@ local du = require "lib/dtutils" local df = require("lib/dtutils.file") local ds = require("lib/dtutils.system") +local gettext = dt.gettext + du.check_min_api_version("5.0.0", "exportLUT") -- Thanks Kevin Ertel for this bit @@ -40,27 +42,27 @@ local mkdir_command = 'mkdir -p ' if dt.configuration.running_os == 'windows' then mkdir_command = 'mkdir ' end local file_chooser_button = dt.new_widget("file_chooser_button"){ - title = "Identity_file_chooser", + title = gettext.gettext("Identity_file_chooser"), value = "", is_directory = false } local export_chooser_button = dt.new_widget("file_chooser_button"){ - title = "Export_location_chooser", + title = gettext.gettext("Export_location_chooser"), value = "", is_directory = true } local identity_label = dt.new_widget("label"){ - label = "choose the identity haldclut file" + label = gettext.gettext("choose the identity haldclut file") } local output_label = dt.new_widget("label"){ - label = "choose the output location" + label = gettext.gettext("choose the output location") } local warning_label = dt.new_widget("label"){ - label = "WARNING: files may be silently overwritten" + label = gettext.gettext("WARNING: files may be silently overwritten") } local function end_job(job) @@ -82,9 +84,9 @@ end local function export_luts() local identity = dt.database.import(file_chooser_button.value) if(type(identity) ~= "userdata") then - dt.print("Invalid identity lut file") + dt.print(gettext.gettext("Invalid identity lut file")) else - local job = dt.gui.create_job('Exporting styles as haldCLUTs', true, end_job) + local job = dt.gui.create_job(gettext.gettext('Exporting styles as haldCLUTs'), true, end_job) local size = 1 @@ -103,22 +105,22 @@ local function export_luts() io_lut:write_image(identity, output_path(style.name, job)) count = count + 1 job.percent = count / size - dt.print("Exported: " .. output_path(style.name, job)) + dt.print(gettext.gettext("Exported: ") .. output_path(style.name, job)) end - dt.print("Done exporting haldCLUTs") + dt.print(gettext.gettext("Done exporting haldCLUTs")) job.valid = false identity:reset() end end local export_button = dt.new_widget("button"){ - label = "export", + label = gettext.gettext("export"), clicked_callback = export_luts } dt.register_lib( - "export haldclut", - "export haldclut", + gettext.gettext("export haldclut"), + gettext.gettext("export haldclut"), true, false, {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, From 948e8690dd0d274d7207987e74472b00d8e65fd3 Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sat, 20 Jun 2020 14:49:31 -0400 Subject: [PATCH 25/70] Pulled preklov's branch, resolved conflicts, then merged into new branch with only 1 commit, essentially squashing the delete and replace file commits. --- contrib/OpenInExplorer.lua | 195 ++++++++++++++++----- locale/de_DE/LC_MESSAGES/OpenInExplorer.po | 67 +++++-- 2 files changed, 200 insertions(+), 62 deletions(-) diff --git a/contrib/OpenInExplorer.lua b/contrib/OpenInExplorer.lua index 496bc79..425ba54 100644 --- a/contrib/OpenInExplorer.lua +++ b/contrib/OpenInExplorer.lua @@ -32,12 +32,18 @@ Install: (see here for more detail: https://github.com/darktable-org/lua-scripts Select the photo(s) you wish to find in your operating system's file manager and press "show in file explorer" in the "selected images" section. -- Nautilus (Linux), Explorer (Windows), and Finder (macOS before Catalina) will open one window for each selected image at the file's location. The file name will be highlighted. +- Nautilus (Linux), Explorer (Windows), and Finder (macOS prior to Mojave) will open one window for each selected image at the file's location. The file name will be highlighted. -- On macOS Catalina the Finder will open one window for each different directory. In these windows only the last one of the corresponding files will be highlighted (bug or feature?). +- On macOS Mojave and Catalina the Finder will open one window for each different directory. In these windows only the last one of the corresponding files will be highlighted (bug or feature?). - Dolphin (Linux) will open one window with tabs for the different directories. All the selected images' file names are highlighted in their respective directories. +As an alternative option you can choose to show the image file names as symbolic links in an arbitrary directory. Go to preferences|Lua options. This option is not available for Windows users as on Windows solely admins are allowed to create links. + +- Pros: You do not clutter up your display with multiple windows. So there is no need to limit the number of selections. + +- Cons: If you want to work with the files you are one step behind the original data. + ----KNOWN ISSUES---- ]] @@ -50,6 +56,7 @@ local gettext = dt.gettext --Check API version du.check_min_api_version("5.0.0", "OpenInExplorer") +-- Tell gettext where to find the .mo file translating messages for a particular domain gettext.bindtextdomain("OpenInExplorer",dt.configuration.config_dir.."/lua/locale/") local function _(msgid) @@ -59,58 +66,150 @@ end local act_os = dt.configuration.running_os local PS = act_os == "windows" and "\\" or "/" ---Detect OS and quit if it is not supported-- -local proper_install = true +--Detect OS and quit if it is not supported. if act_os ~= "macos" and act_os ~= "windows" and act_os ~= "linux" then - proper_install = false - dt.print_error(_('OpenInExplorer plug-in only supports Linux, macOS, and Windows at this time')) + dt.print(_("OpenInExplorer plug-in only supports Linux, macOS, and Windows at this time")) + dt.print_error("OpenInExplorer plug-in only supports Linux, macOS, and Windows at this time") return end ---Format strings for the commands to open the corresponding OS' file manager -local fmng_cmd = {} -fmng_cmd.linux = [[busctl --user call org.freedesktop.FileManager1 /org/freedesktop/FileManager1 org.freedesktop.FileManager1 ShowItems ass %d %s""]] -fmng_cmd.macos = 'open -Rn %s' -fmng_cmd.windows = 'explorer.exe /select, %s' +local use_links, links_dir = false, "" +if act_os ~= "windows" then + use_links = dt.preferences.read("OpenInExplorer", "use_links", "bool") + links_dir = dt.preferences.read("OpenInExplorer", "linked_image_files_dir", "string") +end ---The working function that opens the file manager windows with the selected image file names highlighted. -local function open_in_fmanager(op_sys, fmcmd) - local images = dt.gui.selection() - local curr_image, run_cmd, file_uris = '', '', '' - if #images == 0 then - dt.print(_('Please select an image')) - elseif #images <= 15 then - for _,image in pairs(images) do - curr_image = image.path..PS..image.filename - if op_sys == 'linux' then - file_uris = file_uris .. df.sanitize_filename("file://" .. curr_image) .. " " - dt.print_log("file_uris is " .. file_uris) - else - run_cmd = string.format(fmcmd, df.sanitize_filename(curr_image)) - dt.print_log("OpenInExplorer run_cmd = "..run_cmd) - dsys.external_command(run_cmd) - end - end - if op_sys == 'linux' then - run_cmd = string.format(fmcmd, #images, file_uris) - dt.print_log("OpenInExplorer run_cmd = "..run_cmd) - dsys.external_command(run_cmd) - end - else - dt.print(_('Please select fewer images (max 15)')) +--Check if the directory exists that was chosen for the file links. Return boolean. +local function check_if_links_dir_exists() + local dir_exists = true + if not links_dir then + --Just for paranoic reasons. I tried, but I couldn't devise a setting for a nil value. + dt.print(_("No links directory selected.\nPlease check the dt preferences (lua options)")) + dt.print_error("OpenInExplorer: No links directory selected") + dir_exists = false + elseif not df.check_if_file_exists(links_dir) then + dt.print(string.format(_("Links directory '%s' not found.\nPlease check the dt preferences (lua options)"), links_dir)) + dt.print_error(string.format("OpenInExplorer: Links directory '%s' not found", links_dir)) + dir_exists = false + end + return dir_exists +end + +--Format strings for the commands to open the corresponding OS's file manager. +local open_dir = {} +open_dir.windows = "explorer.exe /n, %s" +open_dir.macos = "open %s" +open_dir.linux = [[busctl --user call org.freedesktop.FileManager1 /org/freedesktop/FileManager1 org.freedesktop.FileManager1 ShowFolders ass 1 %s ""]] + +local open_files = {} +open_files.windows = "explorer.exe /select, %s" +open_files.macos = "open -Rn %s" +open_files.linux = [[busctl --user call org.freedesktop.FileManager1 /org/freedesktop/FileManager1 org.freedesktop.FileManager1 ShowItems ass %d %s ""]] + +--Call the file mangager for each selected image on Linux. +--There is one call to busctl containing a list of all the image file names. +local function call_list_of_files(selected_images) + local current_image, file_uris, run_cmd = "", "", "" + for _, image in pairs(selected_images) do + current_image = image.path..PS..image.filename + file_uris = file_uris .. df.sanitize_filename("file://" .. current_image) .. " " + dt.print_log("file_uris is " .. file_uris) + end + run_cmd = string.format(open_files.linux, #selected_images, file_uris) + dt.print_log("OpenInExplorer run_cmd = "..run_cmd) + dsys.external_command(run_cmd) +end + +--Call the file manager for each selected image on Windows and macOS. +local function call_file_by_file(selected_images) + local current_image, run_cmd = "", "" + for _, image in pairs(selected_images) do + current_image = image.path..PS..image.filename + run_cmd = string.format(open_files[act_os], df.sanitize_filename(current_image)) + dt.print_log("OpenInExplorer run_cmd = "..run_cmd) + dsys.external_command(run_cmd) end end --- GUI -- -if proper_install then - dt.gui.libs.image.register_action( - _("show in file explorer"), - function() open_in_fmanager(act_os, fmng_cmd[act_os]) end, - _("Opens the file manager at the selected image's location") - ) - dt.register_event( - "shortcut", - function(event, shortcut) open_in_fmanager(act_os, fmng_cmd[act_os]) end, - "OpenInExplorer" - ) +--Create a link for each selected image, and finally call the file manager. +local function set_links(selected_images) + local current_image, link_target, run_cmd, k = "", "", "", nil + for k, image in pairs(selected_images) do + current_image = image.path..PS..image.filename + link_target = df.create_unique_filename(links_dir .. PS .. image.filename) + run_cmd = string.format("ln -s %s %s", df.sanitize_filename(current_image), df.sanitize_filename(link_target)) + --[[ + In case Windows will allow normal users to create soft links: + if act_os == "windows" then + run_cmd = string.format("mklink %s %s", df.sanitize_filename(link_target), df.sanitize_filename(current_image)) + end + ]] + if dsys.external_command(run_cmd) ~= 0 then + dt.print(_("Failed to create links. Missing rights?")) + dt.print_error("OpenInExplorer: Failed to create links") + return + end + end + --The URI format is necessary only for the Linux busctl command. + --But it is accepted by the Windows Explorer and macOS's Finder all the same. + run_cmd = string.format(open_dir[act_os], df.sanitize_filename("file://"..links_dir)) + dt.print_log("OpenInExplorer run_cmd = "..run_cmd) + dsys.external_command(run_cmd) end + +--The working function that starts the particular task. +local function open_in_fmanager() + local images = dt.gui.selection() + if #images == 0 then + dt.print(_("Please select an image")) + else + if use_links and not check_if_links_dir_exists() then + return + end + if #images > 15 and not use_links then + dt.print(_("Please select fewer images (max. 15)")) + elseif use_links then + set_links(images) + else + if act_os == "linux" then + call_list_of_files(images) + else + call_file_by_file(images) + end + end + end +end + + +-- GUI -- +dt.gui.libs.image.register_action( + _("show in file explorer"), + function() open_in_fmanager() end, + _("Open the file manager at the selected image's location") +) +if act_os ~= "windows" then + dt.preferences.register("OpenInExplorer", "linked_image_files_dir", -- name + "directory", -- type + _("OpenInExplorer: linked files directory"), -- label + _("Directory to store the links to the file names. Requires restart to take effect"), -- tooltip + "Links to image files", -- default + dt.new_widget("file_chooser_button"){ + title = _("Select directory"), + is_directory = true, + } + ) + dt.preferences.register("OpenInExplorer", "use_links", -- name + "bool", -- type + _("OpenInExplorer: use links"), -- label + _("Use links instead of multiple windows. Requires restart to take effect"), -- tooltip + false, -- default + "" + ) +end + +dt.register_event( + "shortcut", + function(event, shortcut) open_in_fmanager(act_os, fmng_cmd[act_os]) end, + "OpenInExplorer" +) + diff --git a/locale/de_DE/LC_MESSAGES/OpenInExplorer.po b/locale/de_DE/LC_MESSAGES/OpenInExplorer.po index 07d451a..f0dc8ef 100644 --- a/locale/de_DE/LC_MESSAGES/OpenInExplorer.po +++ b/locale/de_DE/LC_MESSAGES/OpenInExplorer.po @@ -1,39 +1,78 @@ -# OpenInExplorer Darktable Plug-In. -# Copyright (C) 2020 Volker Lenhardt +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Volker Lenhardt , 2020. # #, fuzzy msgid "" msgstr "" -"Project-Id-Version: OpenInExplorer\n" +"Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-04-19 14:43+0200\n" +"POT-Creation-Date: 2020-06-11 19:07+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: Volker Lenhardt \n" +"Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: de_DE\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: OpenInExplorer.lua:64 +#: OpenInExplorer.lua:71 msgid "" -"OpenInExplorer plug-in only supports Linux, macOS, and Windows at this time" -msgstr "OpenInExplorer-Plug-in kann nur auf macOS, Linux oder Windows laufen" +"OpenInExplorer plug-in only supports Linux and macOS, and Windows at this time" +msgstr "OpenInExplorer-Plug-in unterstützt zur Zeit nur Linux, macOS oder Windows" -#: OpenInExplorer.lua:79 +#: OpenInExplorer.lua:87 +msgid "" +"No links directory selected.\n" +"Please check the dt preferences (lua options)" +msgstr "Kein Verknüpfungs-Verzeichnis ausgewählt.\nBitte die dt-Voreinstellungen überprüfen (Lua-Optionen)" + +#: OpenInExplorer.lua:91 +#, lua-format +msgid "" +"Links directory '%s' not found.\n" +"Please check the dt preferences (lua options)" +msgstr "Das Verknüpfungs-Verzeichnis '%s' konnte nicht gefunden werden.\nBitte die dt-Voreinstellungen überprüfen (Lua-Optionen)" + +#: OpenInExplorer.lua:148 +msgid "Failed to create links. Missing rights?" +msgstr "Die Verknüpfungen konnten nicht erstellt werden. Fehlende Rechte?" + +#: OpenInExplorer.lua:164 msgid "Please select an image" msgstr "Es wurde kein Bild ausgewählt" -#: OpenInExplorer.lua:98 -msgid "Please select fewer images (max 15)" +#: OpenInExplorer.lua:170 +msgid "Please select fewer images (max. 15)" msgstr "Bitte nicht mehr als 15 Bilder auswählen" -#: OpenInExplorer.lua:105 +#: OpenInExplorer.lua:186 msgid "show in file explorer" msgstr "im Dateimanager anzeigen" -#: OpenInExplorer.lua:107 -msgid "Opens the file manager at the selected image's location" +#: OpenInExplorer.lua:188 +msgid "Open the file manager at the selected image's location" msgstr "Öffnet den Dateimanager an der Position des ausgewählten Bildes" + +#: OpenInExplorer.lua:193 +msgid "OpenInExplorer: linked files directory" +msgstr "OpenInExplorer: Verknüpfungs-Verzeichnis" + +#: OpenInExplorer.lua:194 +msgid "" +"Directory to store the links to the file names. Requires restart to take " +"effect" +msgstr "Verzeichnis für die Verknüpfungen zu den Dateinamen. Erfordert dt-Neustart" + +#: OpenInExplorer.lua:197 +msgid "Select directory" +msgstr "Verzeichnis auswählen" + +#: OpenInExplorer.lua:203 +msgid "OpenInExplorer: use links" +msgstr "OpenInExplorer: Verknüpfungen nutzen" + +#: OpenInExplorer.lua:204 +msgid "Use links instead of multiple windows. Requires restart to take effect" +msgstr "Verknüpfungen statt einzelner Fenster nutzen. Erfordert dt-Neustart" From 497dbc8eaa5c24a7ec32da568ed8796545026a3e Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sun, 21 Jun 2020 16:32:14 -0400 Subject: [PATCH 26/70] Fixed function call arguments in shortcut. --- contrib/OpenInExplorer.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/OpenInExplorer.lua b/contrib/OpenInExplorer.lua index 425ba54..f1430cf 100644 --- a/contrib/OpenInExplorer.lua +++ b/contrib/OpenInExplorer.lua @@ -209,7 +209,7 @@ end dt.register_event( "shortcut", - function(event, shortcut) open_in_fmanager(act_os, fmng_cmd[act_os]) end, + function(event, shortcut) open_in_fmanager() end, "OpenInExplorer" ) From 14b97cdbd92954647c0245b110b6d3ab88bf070c Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sun, 21 Jun 2020 17:14:36 -0400 Subject: [PATCH 27/70] Created image_time.lua to adjust non-destructively adjust image time. --- contrib/image_time.lua | 516 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 516 insertions(+) create mode 100644 contrib/image_time.lua diff --git a/contrib/image_time.lua b/contrib/image_time.lua new file mode 100644 index 0000000..62f2e2d --- /dev/null +++ b/contrib/image_time.lua @@ -0,0 +1,516 @@ +--[[ + + image_time.lua - synchronize image time for images shot with different cameras + + Copyright (C) 2019, 2020 Bill Ferguson . + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +]] +--[[ + image_time - non-destructively modify the image time + + DESCRIPTION + + image_time non destructively adjusts image times by modifying the + database image exif_datetime_taken field. There are 4 modes: adjust time, + set time, synchronize time, and reset time. + + ADJUST TIME + + adjust time mode lets you chose an offset in terms of years, months, + days, hours, minutes, and seconds. The adjustment can be added or + subtracted. + + WARNING: When adding and subtracting months the result will usually + be what is expected unless the time being adjusted is at the end of + the month. This is because a month is a variable amount of time that + can be 28, 29, 30 or 31 days depending on the month. Example: It's + March 31st and I subtract a month which not sets the time to February + 31st. When that gets set to a valid time, then the date changes to + March 3rd. + + SET TIME + + set time mode allows you to pick a date and time and set the image + time accordingly. Fields may be left out. This is useful when + importing scanned images that don't have an embedded date. + + SYNCHRONIZE TIME + + I recently purchased a 7DmkII to replace my aging 7D. My 7D was still + serviceable, so I bought a remote control and figured I'd try shooting + events from 2 different perspectives. I didn't think to synchonize the + time between the 2 cameras, so when I loaded the images and sorted by + time it was a disaster. I hacked a script together with hard coded values + to adjust the exif_datetime_taken value in the database for the 7D images + so that everything sorted properly. I've tried shooting with 2 cameras + several times since that first attempt. I've gotten better at getting the + camera times close, but still haven't managed to get them to sync. So I + decided to think the problem through and write a proper script to take + care of the problem. + + RESET TIME + + Select the images and click reset. + + USAGE + + ADJUST TIME + + Change the year, month, day, hour, minute, second dropdowns to the amount + of change desired. Select add or subtract. Select the images. Click + adjust. + + SET TIME + + Set the time fields to the desired time. Select the images to change. Click + set. + + SYNCHRONIZE TIME + + Select 2 images, one from each camera, of the same moment in time. Click + the Calculate button to calculate the time difference. The difference is + displayed in the difference entry. You can manually adjust it by changing + the value if necessary. + + Select the images that need their time adjusted. Determine which way to adjust + adjust the time (add or subtract) and select the appropriate choice. + + If the image times get messed up and you just want to start over, select reset time + from the mode and reset the image times. + + RESET TIME + + Select the images and click reset. + + ADDITIONAL SOFTWARE REQUIRED + * exiv2 + + BUGS, COMMENTS, SUGGESTIONS + * Send to Bill Ferguson, wpferguson@gmail.com + + CHANGES + +]] +local dt = require "darktable" +local du = require "lib/dtutils" +local df = require "lib/dtutils.file" +local ds = require "lib/dtutils.string" +local gettext = dt.gettext + +local adj_time = {} + +du.check_min_api_version("3.0.0", "image_time") + + +-- Tell gettext where to find the .mo file translating messages for a particular domain +gettext.bindtextdomain("image_time",dt.configuration.config_dir.."/lua/locale/") + +local function _(msgid) + return gettext.dgettext("image_time", msgid) +end + +local PS = dt.configuration.runnin_os == "windows" and "\\" or "/" +local ERROR = -1 + +-- function to convert from exif time to system time +local function exiftime2systime(exiftime) + local yr,mo,dy,h,m,s = string.match(exiftime, "(%d-):(%d-):(%d-) (%d-):(%d-):(%d+)") + return(os.time{year=yr, month=mo, day=dy, hour=h, min=m, sec=s}) +end + +-- function to convert from systime to exif time +local function systime2exiftime(systime) + local t = os.date("*t", systime) + return(string.format("%4d:%02d:%02d %02d:%02d:%02d", t.year, t.month, t.day, t.hour, t.min, t.sec)) +end + +local function vars2exiftime(year, month, day, hour, min, sec) + local y = tonumber(year) and string.format("%4d", year) or " " + local mo = tonumber(month) and string.format("%02d", month) or " " + local d = tonumber(day) and string.format("%02d", day) or " " + local h = tonumber(hour) and string.format("%02d", hour) or " " + local m = tonumber(min) and string.format("%02d", min) or " " + local s = tonumber(sec) and string.format("%02d", sec) or " " + return(y .. ":" .. mo .. ":" .. d .. " " .. h .. ":" .. m .. ":" .. s) +end + +local function exiftime2vars(exiftime) + return string.match(exiftime, "(%d+):(%d+):(%d+) (%d+):(%d+):(%d+)") +end + +local function calc_time_difference(image1, image2) + return math.abs(exiftime2systime(image1.exif_datetime_taken) - exiftime2systime(image2.exif_datetime_taken)) +end + +local function adjust_image_time(image, difference) + image.exif_datetime_taken = systime2exiftime(exiftime2systime(image.exif_datetime_taken) + difference) + return +end + +local function calculate_difference(images) + if #images == 2 then + adj_time.diff_entry.text = calc_time_difference(images[1], images[2]) + adj_time.btn.sensitive = true + else + dt.print(_("Error: 2 images must be selected")) + end +end + +local function synchronize_times(images, difference) + for _, image in ipairs(images) do + adjust_image_time(image, difference) + end +end + +local function synchronize_time(images) + local sign = 1 + if adj_time.sdir.value == "subtract" then + sign = -1 + end + synchronize_times(images, tonumber(adj_time.diff_entry.text) * sign) +end + +local function add_time(images) + synchronize_times(images, tonumber(adj_time.diff_entry.text)) +end + +local function year_month2months(year, month) + year_months = tonumber(year) and year * 12 or 0 + local months = tonumber(month) and tonumber(month) or 0 + + return year_months + months +end + +local function months2year_month(months) + dt.print_log("months is " .. months) + local year = math.floor(months / 12) + local month = months - (year * 12) + + return year, month +end + +local function get_image_taken_time(image) + -- get original image time + local datetime = nil + + local exiv2 = df.check_if_bin_exists("exiv2") + if exiv2 then + p = io.popen(exiv2 .. " -K Exif.Image.DateTime " .. image.path .. PS .. image.filename) + if p then + for line in p:lines() do + if string.match(line, "Exif.Image.DateTime") then + datetime = string.match(line, "(%d-:%d-:%d- %d-:%d-:%d+)") + end + end + p:close() + end + else + dt.print(_("unable to detect exiv2")) + datetime = ERROR + end + return datetime +end + +local function _get_windows_image_file_creation_time(image) + local datetime = nil + local p = io.popen("dir " .. image.path .. PS .. image.filename) + if p then + for line in p:lines() do + if string.match(line, ds.sanitize_lua(image.filename)) then + local mo, day, yr, hr, min, apm = string.match(line, "(%d+)/(%d+)/(%d+) (%d-):(%d+) (%S+)") + if apm == "PM" then + hr = hr + 12 + end + datetime = vars2exiftime(yr, mo, day, hr, min, 0) + end + end + p:close() + else + dt.print(_("unable to get information for ") .. image.filename) + datetime = ERROR + end + return datetime +end + +local function _get_nix_image_file_creation_time(image) + local datetime = nil + local p = io.popen("ls -lL --time-style=full-iso " .. image.path .. PS .. image.filename) + if p then + for line in p:lines() do + if string.match(line, ds.sanitize_lua(image.filename)) then + datetime = vars2exiftime(string.match(line, "(%d+)%-(%d-)%-(%d-) (%d-):(%d-):(%d+).")) + end + end + p:close() + else + dt.print(_("unable to get information for ") .. image.filename) + datetime = ERROR + end + return datetime +end + +local function get_image_file_creation_time(image) + -- no exif time in the image file so get the creation time + local datetime = nil + if dt.configuration.running_os == "windows" then + datetime = _get_windows_image_file_creation_time(image) + else + datetime = _get_nix_image_file_creation_time(image) + end + return datetime +end + +local function get_original_image_time(image) + local image_time = image.exif_datetime_taken + local reset_time = nil + + reset_time = get_image_taken_time(image) + + if reset_time then + if reset_time == ERROR then + return image_time + else + return reset_time + end + else + reset_time = get_image_file_creation_time(image) + + if reset_time then + if reset_time == ERROR then + return image_time + else + return reset_time + end + end + end +end + +local function reset_time(images) + if #images > 0 then + for _, image in ipairs(images) do + image.exif_datetime_taken = get_original_image_time(image) + end + else + dt.print_error(_("reset time: no images selected")) + dt.print(_("please select the images that need their time reset")) + end +end + +local function adjust_time(images) + local SEC_MIN = 60 + local SEC_HR = SEC_MIN * 60 + local SEC_DY = SEC_HR * 24 + + local offset = nil + local sign = 1 + + if #images < 1 then + dt.print(_("please select some images and try again")) + return + end + + if adj_time.adir.value == _("subtract") then + sign = -1 + end + + for _, image in ipairs(images) do + local y, mo, d, h, m, s = exiftime2vars(image.exif_datetime_taken) + local image_months = year_month2months(y, mo) + local months_diff = year_month2months(adj_time.ayr.value, adj_time.amo.value) + y, mo = months2year_month(image_months + (months_diff * sign)) + local exif_new = vars2exiftime(y, mo, d, h, m, s) + offset = adj_time.ady.value * SEC_DY + offset = offset + adj_time.ahr.value * SEC_HR + offset = offset + adj_time.amn.value * SEC_MIN + offset = offset + adj_time.asc.value + offset = offset * sign + image.exif_datetime_taken = systime2exiftime(exiftime2systime(exif_new) + offset) + end +end + +local function set_time(images) + if #images < 1 then + dt.print(_("please select some images and try again")) + return + end + + local y = adj_time.syr.value + local mo = adj_time.smo.value + local d = adj_time.sdy.value + local h = adj_time.shr.value + local m = adj_time.smn.value + local s = adj_time.ssc.value + + for _, image in ipairs(images) do + image.exif_datetime_taken = vars2exiftime(y, mo, d, h, m, s) + end +end + +local function seq(first, last) + local result = {} + + local num = first + + while num <= last do + table.insert(result, num) + num = num + 1 + end + + return table.unpack(result) +end + +-- widgets + +adj_time.widgets = { + -- name, type, tooltip, placeholder, + {"ayr", "combobox", _("years"), _("years to adjust by, 0 - ?"), {seq(0,20)}, 1}, + {"amo", "combobox", _("months"), ("months to adjust by, 0-12"), {seq(0,12)}, 1}, + {"ady", "combobox", _("days"), ("days to adjust by, 0-31"), {seq(0,31)}, 1}, + {"ahr", "combobox", _("hours"), _("hours to adjust by, 0-23"), {seq(0,23)}, 1}, + {"amn", "combobox", _("minutes"), _("minutes to adjust by, 0-59"), {seq(0,59)}, 1}, + {"asc", "combobox", _("seconds"), _("seconds to adjust by, 0-59"), {seq(0,59)}, 1}, + {"adir", "combobox", _("add/subtract"), _("add or subtract time"), {_("add"), _("subtract")}, 1}, + {"syr", "combobox", _("year"), _("year to set, 1900 - now"), {" ", seq(1900,os.date("*t", os.time()).year)}, 122}, + {"smo", "combobox", _("month"), _("month to set, 1-12"), {" ", seq(1,12)}, 1}, + {"sdy", "combobox", _("day"), _("day to set, 1-31"), {" ", seq(1,31)}, 1}, + {"shr", "combobox", _("hour"), _("hour to set, 0-23"), {" ", seq(0,23)}, 1}, + {"smn", "combobox", _("minute"), _("minutes to set, 0-59"), {" ", seq(0, 59)}, 1}, + {"ssc", "combobox", _("seconds"), _("seconds to set, 0-59"), {" ", seq(0,59)}, 1}, + {"sdir", "combobox", _("add/subtract"), _("add or subtract time"), {_("add"), _("subtract")}, 1}, +} + +for _, widget in ipairs(adj_time.widgets) do + adj_time[widget[1]] = dt.new_widget(widget[2]){ + label = widget[3], + tooltip = widget[4], + selected = widget[6], + table.unpack(widget[5]) + } +end + +adj_time.diff_entry = dt.new_widget("entry"){ + tooltip = _("Time difference between images in seconds"), + placeholder = _("Select 2 images and use the calculate button"), + text = "", +} + +adj_time.calc_btn = dt.new_widget("button"){ + label = _("Calculate"), + tooltip = _("calculate time difference between 2 images"), + clicked_callback = function() + calculate_difference(dt.gui.action_images) + end +} + +adj_time.btn = dt.new_widget("button"){ + label = _("synchronize image times"), + tooltip = _("apply the time difference from selected images"), + sensitive = false, + clicked_callback = function() + synchronize_time(dt.gui.action_images) + end +} + +adj_time.stack = dt.new_widget("stack"){ + dt.new_widget("box"){ + orientation = "vertical", + dt.new_widget("label"){label = _("adjust time")}, + dt.new_widget("section_label"){label = _("days, months, years")}, + adj_time.ady, + adj_time.amo, + adj_time.ayr, + dt.new_widget("section_label"){label = _("hours, minutes, seconds")}, + adj_time.ahr, + adj_time.amn, + adj_time.asc, + dt.new_widget("section_label"){label = _("adjustment direction")}, + adj_time.adir, + dt.new_widget("button"){ + label = _("adjust"), + clicked_callback = function() + adjust_time(dt.gui.action_images) + end + } + }, + dt.new_widget("box"){ + orientation = "vertical", + dt.new_widget("label"){label = _("set time")}, + dt.new_widget("section_label"){label = _("date: ")}, + adj_time.sdy, + adj_time.smo, + adj_time.syr, + dt.new_widget("section_label"){label = _("time:")}, + adj_time.shr, + adj_time.smn, + adj_time.ssc, + dt.new_widget("button"){ + label = _("set"), + clicked_callback = function() + set_time(dt.gui.action_images) + end + } + }, + dt.new_widget("box"){ + orientation = "vertical", + dt.new_widget("label"){label = _("synchronize image time")}, + dt.new_widget("section_label"){label = _("calculate difference between images")}, + adj_time.diff_entry, + adj_time.calc_btn, + dt.new_widget("section_label"){label = _("apply difference")}, + adj_time.sdir, + adj_time.btn, + }, + dt.new_widget("box"){ + orientation = "vertical", + dt.new_widget("label"){label = _("reset to original time")}, + dt.new_widget("separator"){}, + dt.new_widget("button"){ + label = _("reset"), + clicked_callback = function() + reset_time(dt.gui.action_images) + end + } + }, +} + +adj_time.mode = dt.new_widget("combobox"){ + label = _("mode"), + tooltip = _("select mode"), + selected = 1, + changed_callback = function(this) + adj_time.stack.active = this.selected + end, + _("adjust time"), + _("set time"), + _("synchronize time"), + _("reset time") +} + +adj_time.widget = dt.new_widget("box"){ + orientation = "vertical", + adj_time.mode, + adj_time.stack, +} + +dt.register_lib( + "image_time", -- Module name + _("image time"), -- Visible name + true, -- expandable + false, -- resetable + {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, -- containers + adj_time.widget, + nil,-- view_enter + nil -- view_leave +) From e5ab30006bce8962d79f269e1b496688c7b4d25e Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Wed, 24 Jun 2020 21:51:40 -0400 Subject: [PATCH 28/70] Added reset function. Changed namespace to img_time. --- contrib/image_time.lua | 124 ++++++++++++++++++++++++----------------- 1 file changed, 74 insertions(+), 50 deletions(-) diff --git a/contrib/image_time.lua b/contrib/image_time.lua index 62f2e2d..a13a79a 100644 --- a/contrib/image_time.lua +++ b/contrib/image_time.lua @@ -109,7 +109,7 @@ local df = require "lib/dtutils.file" local ds = require "lib/dtutils.string" local gettext = dt.gettext -local adj_time = {} +local img_time = {} du.check_min_api_version("3.0.0", "image_time") @@ -161,8 +161,8 @@ end local function calculate_difference(images) if #images == 2 then - adj_time.diff_entry.text = calc_time_difference(images[1], images[2]) - adj_time.btn.sensitive = true + img_time.diff_entry.text = calc_time_difference(images[1], images[2]) + img_time.btn.sensitive = true else dt.print(_("Error: 2 images must be selected")) end @@ -176,14 +176,14 @@ end local function synchronize_time(images) local sign = 1 - if adj_time.sdir.value == "subtract" then + if img_time.sdir.value == "subtract" then sign = -1 end - synchronize_times(images, tonumber(adj_time.diff_entry.text) * sign) + synchronize_times(images, tonumber(img_time.diff_entry.text) * sign) end local function add_time(images) - synchronize_times(images, tonumber(adj_time.diff_entry.text)) + synchronize_times(images, tonumber(img_time.diff_entry.text)) end local function year_month2months(year, month) @@ -321,20 +321,20 @@ local function adjust_time(images) return end - if adj_time.adir.value == _("subtract") then + if img_time.adir.value == _("subtract") then sign = -1 end for _, image in ipairs(images) do local y, mo, d, h, m, s = exiftime2vars(image.exif_datetime_taken) local image_months = year_month2months(y, mo) - local months_diff = year_month2months(adj_time.ayr.value, adj_time.amo.value) + local months_diff = year_month2months(img_time.ayr.value, img_time.amo.value) y, mo = months2year_month(image_months + (months_diff * sign)) local exif_new = vars2exiftime(y, mo, d, h, m, s) - offset = adj_time.ady.value * SEC_DY - offset = offset + adj_time.ahr.value * SEC_HR - offset = offset + adj_time.amn.value * SEC_MIN - offset = offset + adj_time.asc.value + offset = img_time.ady.value * SEC_DY + offset = offset + img_time.ahr.value * SEC_HR + offset = offset + img_time.amn.value * SEC_MIN + offset = offset + img_time.asc.value offset = offset * sign image.exif_datetime_taken = systime2exiftime(exiftime2systime(exif_new) + offset) end @@ -346,12 +346,12 @@ local function set_time(images) return end - local y = adj_time.syr.value - local mo = adj_time.smo.value - local d = adj_time.sdy.value - local h = adj_time.shr.value - local m = adj_time.smn.value - local s = adj_time.ssc.value + local y = img_time.syr.value + local mo = img_time.smo.value + local d = img_time.sdy.value + local h = img_time.shr.value + local m = img_time.smn.value + local s = img_time.ssc.value for _, image in ipairs(images) do image.exif_datetime_taken = vars2exiftime(y, mo, d, h, m, s) @@ -371,9 +371,28 @@ local function seq(first, last) return table.unpack(result) end +local function reset_widgets() + dt.print_log("took the reset function") + img_time.ayr.selected = 1 + img_time.amo.selected = 1 + img_time.ady.selected = 1 + img_time.ahr.selected = 1 + img_time.ayr.selected = 1 + img_time.amn.selected = 1 + img_time.asc.selected = 1 + img_time.adir.selected = 1 + img_time.syr.selected = #img_time.syr + img_time.smo.selected = 1 + img_time.sdy.selected = 1 + img_time.shr.selected = 1 + img_time.smn.selected = 1 + img_time.ssc.selected = 1 + img_time.adir.selected = 1 +end + -- widgets -adj_time.widgets = { +img_time.widgets = { -- name, type, tooltip, placeholder, {"ayr", "combobox", _("years"), _("years to adjust by, 0 - ?"), {seq(0,20)}, 1}, {"amo", "combobox", _("months"), ("months to adjust by, 0-12"), {seq(0,12)}, 1}, @@ -382,7 +401,7 @@ adj_time.widgets = { {"amn", "combobox", _("minutes"), _("minutes to adjust by, 0-59"), {seq(0,59)}, 1}, {"asc", "combobox", _("seconds"), _("seconds to adjust by, 0-59"), {seq(0,59)}, 1}, {"adir", "combobox", _("add/subtract"), _("add or subtract time"), {_("add"), _("subtract")}, 1}, - {"syr", "combobox", _("year"), _("year to set, 1900 - now"), {" ", seq(1900,os.date("*t", os.time()).year)}, 122}, + {"syr", "combobox", _("year"), _("year to set, 1900 - now"), {" ", seq(1900,os.date("*t", os.time()).year)}, 1}, {"smo", "combobox", _("month"), _("month to set, 1-12"), {" ", seq(1,12)}, 1}, {"sdy", "combobox", _("day"), _("day to set, 1-31"), {" ", seq(1,31)}, 1}, {"shr", "combobox", _("hour"), _("hour to set, 0-23"), {" ", seq(0,23)}, 1}, @@ -391,8 +410,8 @@ adj_time.widgets = { {"sdir", "combobox", _("add/subtract"), _("add or subtract time"), {_("add"), _("subtract")}, 1}, } -for _, widget in ipairs(adj_time.widgets) do - adj_time[widget[1]] = dt.new_widget(widget[2]){ +for _, widget in ipairs(img_time.widgets) do + img_time[widget[1]] = dt.new_widget(widget[2]){ label = widget[3], tooltip = widget[4], selected = widget[6], @@ -400,13 +419,15 @@ for _, widget in ipairs(adj_time.widgets) do } end -adj_time.diff_entry = dt.new_widget("entry"){ +img_time.syr.selected = #img_time.syr + +img_time.diff_entry = dt.new_widget("entry"){ tooltip = _("Time difference between images in seconds"), placeholder = _("Select 2 images and use the calculate button"), text = "", } -adj_time.calc_btn = dt.new_widget("button"){ +img_time.calc_btn = dt.new_widget("button"){ label = _("Calculate"), tooltip = _("calculate time difference between 2 images"), clicked_callback = function() @@ -414,7 +435,7 @@ adj_time.calc_btn = dt.new_widget("button"){ end } -adj_time.btn = dt.new_widget("button"){ +img_time.btn = dt.new_widget("button"){ label = _("synchronize image times"), tooltip = _("apply the time difference from selected images"), sensitive = false, @@ -423,20 +444,20 @@ adj_time.btn = dt.new_widget("button"){ end } -adj_time.stack = dt.new_widget("stack"){ +img_time.stack = dt.new_widget("stack"){ dt.new_widget("box"){ orientation = "vertical", dt.new_widget("label"){label = _("adjust time")}, dt.new_widget("section_label"){label = _("days, months, years")}, - adj_time.ady, - adj_time.amo, - adj_time.ayr, + img_time.ady, + img_time.amo, + img_time.ayr, dt.new_widget("section_label"){label = _("hours, minutes, seconds")}, - adj_time.ahr, - adj_time.amn, - adj_time.asc, + img_time.ahr, + img_time.amn, + img_time.asc, dt.new_widget("section_label"){label = _("adjustment direction")}, - adj_time.adir, + img_time.adir, dt.new_widget("button"){ label = _("adjust"), clicked_callback = function() @@ -448,13 +469,13 @@ adj_time.stack = dt.new_widget("stack"){ orientation = "vertical", dt.new_widget("label"){label = _("set time")}, dt.new_widget("section_label"){label = _("date: ")}, - adj_time.sdy, - adj_time.smo, - adj_time.syr, + img_time.sdy, + img_time.smo, + img_time.syr, dt.new_widget("section_label"){label = _("time:")}, - adj_time.shr, - adj_time.smn, - adj_time.ssc, + img_time.shr, + img_time.smn, + img_time.ssc, dt.new_widget("button"){ label = _("set"), clicked_callback = function() @@ -466,11 +487,11 @@ adj_time.stack = dt.new_widget("stack"){ orientation = "vertical", dt.new_widget("label"){label = _("synchronize image time")}, dt.new_widget("section_label"){label = _("calculate difference between images")}, - adj_time.diff_entry, - adj_time.calc_btn, + img_time.diff_entry, + img_time.calc_btn, dt.new_widget("section_label"){label = _("apply difference")}, - adj_time.sdir, - adj_time.btn, + img_time.sdir, + img_time.btn, }, dt.new_widget("box"){ orientation = "vertical", @@ -485,12 +506,12 @@ adj_time.stack = dt.new_widget("stack"){ }, } -adj_time.mode = dt.new_widget("combobox"){ +img_time.mode = dt.new_widget("combobox"){ label = _("mode"), tooltip = _("select mode"), selected = 1, changed_callback = function(this) - adj_time.stack.active = this.selected + img_time.stack.active = this.selected end, _("adjust time"), _("set time"), @@ -498,19 +519,22 @@ adj_time.mode = dt.new_widget("combobox"){ _("reset time") } -adj_time.widget = dt.new_widget("box"){ +img_time.widget = dt.new_widget("box"){ orientation = "vertical", - adj_time.mode, - adj_time.stack, + reset_callback = function(this) + reset_widgets() + end, + img_time.mode, + img_time.stack, } dt.register_lib( "image_time", -- Module name _("image time"), -- Visible name true, -- expandable - false, -- resetable + true, -- resetable {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, -- containers - adj_time.widget, + img_time.widget, nil,-- view_enter nil -- view_leave ) From 323c8b68456f38de6852ceeab31f2fe63932b60e Mon Sep 17 00:00:00 2001 From: "U-DESKTOP-HQME86J\\marco" Date: Sat, 4 Jul 2020 10:27:06 +0200 Subject: [PATCH 29/70] add doc comments --- contrib/RL_out_sharp.lua | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/contrib/RL_out_sharp.lua b/contrib/RL_out_sharp.lua index fcc553e..75446d1 100644 --- a/contrib/RL_out_sharp.lua +++ b/contrib/RL_out_sharp.lua @@ -1,10 +1,29 @@ --[[ + Richardson-Lucy output sharpening for darktable using GMic + darktable is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + darktable is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with darktable. If not, see . +]] + +--[[ DESCRIPTION RL_out_sharp.lua - Richardson-Lucy output sharpening using GMic This script provides a new target storage "RL output sharpen". Images exported will be sharpened using GMic (RL deblur algorithm) + + REQUIRED SOFTWARE + GMic command line interface (CLI) https://gmic.eu/download.shtml USAGE * require this script from main lua file @@ -33,7 +52,6 @@ CHANGES * 20200308 - initial version - ]] local dt = require "darktable" @@ -156,7 +174,7 @@ sigma_slider = dt.new_widget("slider"){ soft_max = 2.0, hard_min = 0.0, hard_max = 3.0, - step = 0.1, + step = 0.05, digits = 2, value = 1.0 } From 2d49b49bec1a2967ad4f65f6df17bf8ec523c7f6 Mon Sep 17 00:00:00 2001 From: "U-DESKTOP-HQME86J\\marco" Date: Sat, 4 Jul 2020 10:45:59 +0200 Subject: [PATCH 30/70] add doc comments to ext_editor --- contrib/ext_editor.lua | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/contrib/ext_editor.lua b/contrib/ext_editor.lua index 19e711c..4035c22 100644 --- a/contrib/ext_editor.lua +++ b/contrib/ext_editor.lua @@ -1,11 +1,25 @@ --[[ + ext_editor.lua - edit images with external editors - DESCRIPTION + darktable is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + darktable is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with darktable. If not, see . +]] + +--[[ ext_editor.lua - edit images with external editors This script provides helpers to edit image files with programs external to darktable. It adds: - - a new target storage "collection". Image exported will be reimported to collection for - further edit with external programs + - a new target storage "collection". Image exported will be reimported to collection for further edit with external programs - a new lighttable module "external editors", to select a program from a list of up to - 9 external editors and run it on a selected image (adjust this limit by changing MAX_EDITORS) - a set of lua preferences in order to configure name and path of up to 9 external editors @@ -48,16 +62,8 @@ CAVEATS * MAC compatibility not tested - TODO - * send multiple images to the same program, maybe - BUGS, COMMENTS, SUGGESTIONS * send to Marco Carrarini, marco.carrarini@gmail.com - - CHANGES - * 20191224 - initial version - * 20191227 - added button "update list", better error handling, fixed bug with groups/tags in "edit" - ]] From 593917db9a50426fd77b0752dddf65d73f4914eb Mon Sep 17 00:00:00 2001 From: Noah Date: Sat, 4 Jul 2020 23:20:30 -0700 Subject: [PATCH 31/70] Fix gettext implementation --- contrib/exportLUT.lua | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/contrib/exportLUT.lua b/contrib/exportLUT.lua index 5d85bdc..aa76b0d 100644 --- a/contrib/exportLUT.lua +++ b/contrib/exportLUT.lua @@ -33,6 +33,12 @@ local ds = require("lib/dtutils.system") local gettext = dt.gettext +gettext.bindtextdomain("exportLUT",dt.configuration.config_dir.."/lua/locale/") + +local function _(msgid) + return gettext.dgettext("exportLUT", msgid) +end + du.check_min_api_version("5.0.0", "exportLUT") -- Thanks Kevin Ertel for this bit @@ -42,27 +48,27 @@ local mkdir_command = 'mkdir -p ' if dt.configuration.running_os == 'windows' then mkdir_command = 'mkdir ' end local file_chooser_button = dt.new_widget("file_chooser_button"){ - title = gettext.gettext("Identity_file_chooser"), + title = _("Identity_file_chooser"), value = "", is_directory = false } local export_chooser_button = dt.new_widget("file_chooser_button"){ - title = gettext.gettext("Export_location_chooser"), + title = _("Export_location_chooser"), value = "", is_directory = true } local identity_label = dt.new_widget("label"){ - label = gettext.gettext("choose the identity haldclut file") + label = _("choose the identity haldclut file") } local output_label = dt.new_widget("label"){ - label = gettext.gettext("choose the output location") + label = _("choose the output location") } local warning_label = dt.new_widget("label"){ - label = gettext.gettext("WARNING: files may be silently overwritten") + label = _("WARNING: files may be silently overwritten") } local function end_job(job) @@ -84,9 +90,9 @@ end local function export_luts() local identity = dt.database.import(file_chooser_button.value) if(type(identity) ~= "userdata") then - dt.print(gettext.gettext("Invalid identity lut file")) + dt.print(_("Invalid identity lut file")) else - local job = dt.gui.create_job(gettext.gettext('Exporting styles as haldCLUTs'), true, end_job) + local job = dt.gui.create_job(_('Exporting styles as haldCLUTs'), true, end_job) local size = 1 @@ -105,22 +111,22 @@ local function export_luts() io_lut:write_image(identity, output_path(style.name, job)) count = count + 1 job.percent = count / size - dt.print(gettext.gettext("Exported: ") .. output_path(style.name, job)) + dt.print(_("Exported: ") .. output_path(style.name, job)) end - dt.print(gettext.gettext("Done exporting haldCLUTs")) + dt.print(_("Done exporting haldCLUTs")) job.valid = false identity:reset() end end local export_button = dt.new_widget("button"){ - label = gettext.gettext("export"), + label = _("export"), clicked_callback = export_luts } dt.register_lib( - gettext.gettext("export haldclut"), - gettext.gettext("export haldclut"), + _("export haldclut"), + _("export haldclut"), true, false, {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, From a40fe3099de49b8041013b29f27dd19ca36d275d Mon Sep 17 00:00:00 2001 From: Cameron Chamberlain Date: Sun, 19 Jul 2020 10:54:48 +1000 Subject: [PATCH 32/70] Typo in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2381dbc..2439e05 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ geoJSON_export|No|L|Create a geo JSON script with thumbnails for use in ... geoToolbox|No|LMW|A toolbox of geo functions gimp|No|LMW|Open an image in GIMP for editing and return the result gpx_export|No|LMW|Export a GPX track file from selected images GPS data -HDRMerge|No|LMW|Combind the selected images into an HDR DNG and return the result +HDRMerge|No|LMW|Combine the selected images into an HDR DNG and return the result hugin|No|LMW|Combine selected images into a panorama and return the result image_stack|No|LMW|Combine a stack of images to remove noise or transient objects kml_export|No|L|Export photos with a KML file for usage in Google Earth From 53bb95e6fd544998000be2fdff60699903b9a3d8 Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sun, 19 Jul 2020 13:13:24 -0400 Subject: [PATCH 33/70] Added entry widget to display the current setting, or a placeholder specifying what would or should happen depending on operating system to provide visual feedback. --- tools/executable_manager.lua | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tools/executable_manager.lua b/tools/executable_manager.lua index 03e35f6..d037d00 100644 --- a/tools/executable_manager.lua +++ b/tools/executable_manager.lua @@ -117,8 +117,15 @@ for _,pref in ipairs(matches) do end local executable_path_widgets = {} +local executable_path_values = {} +local placeholder_text = dt.configuration.running_os == windows and "select an executable" or "search path for executable" for i,exec in ipairs(exec_table) do + executable_path_values[exec] = dt.new_widget("entry"){ + text = df.get_executable_path_preference(exec), + placeholder = placeholder_text, + editable = false + } executable_path_widgets[exec] = dt.new_widget("file_chooser_button"){ title = _("select ") .. exec .. _(" executable"), value = df.get_executable_path_preference(exec), @@ -126,6 +133,7 @@ for i,exec in ipairs(exec_table) do changed_callback = function(self) if df.check_if_bin_exists(self.value) then df.set_executable_path_preference(exec, self.value) + executable_path_values[exec].text = df.get_executable_path_preference(exec) end end } @@ -155,13 +163,18 @@ exec_man.selector = dt.new_widget("combobox"){ for i,exec in ipairs(exec_table) do exec_man.stack[i] = dt.new_widget("box"){ + dt.new_widget("section_label"){label = "current"}, + executable_path_values[exec], + dt.new_widget("section_label"){label = "select"}, executable_path_widgets[exec], + dt.new_widget("section_label"){label = "reset"}, dt.new_widget("button"){ label = "clear", tooltip = _("Clear path for ") .. exec, clicked_callback = function() df.set_executable_path_preference(exec, "") executable_path_widgets[exec].value = "" + executable_path_values[exec].text = "" end } From 57a9a8495c8330e21474c368e6ef5f6ee0263b88 Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sun, 19 Jul 2020 15:38:08 -0400 Subject: [PATCH 34/70] made newly added strings translatable --- tools/executable_manager.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/executable_manager.lua b/tools/executable_manager.lua index d037d00..f45ecb6 100644 --- a/tools/executable_manager.lua +++ b/tools/executable_manager.lua @@ -118,7 +118,7 @@ end local executable_path_widgets = {} local executable_path_values = {} -local placeholder_text = dt.configuration.running_os == windows and "select an executable" or "search path for executable" +local placeholder_text = dt.configuration.running_os == windows and _("select an executable") or _("search path for executable") for i,exec in ipairs(exec_table) do executable_path_values[exec] = dt.new_widget("entry"){ @@ -163,11 +163,11 @@ exec_man.selector = dt.new_widget("combobox"){ for i,exec in ipairs(exec_table) do exec_man.stack[i] = dt.new_widget("box"){ - dt.new_widget("section_label"){label = "current"}, + dt.new_widget("section_label"){label = _("current")}, executable_path_values[exec], - dt.new_widget("section_label"){label = "select"}, + dt.new_widget("section_label"){label = _("select")}, executable_path_widgets[exec], - dt.new_widget("section_label"){label = "reset"}, + dt.new_widget("section_label"){label = _("reset")}, dt.new_widget("button"){ label = "clear", tooltip = _("Clear path for ") .. exec, From b23595ff54e3b3228dda5a8659c6dcf5944808be Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Mon, 3 Aug 2020 18:52:28 -0400 Subject: [PATCH 35/70] Added latest scripts --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2439e05..6b9a0f3 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ CollectHelper|Yes|LMW|Add buttons to selected images module to manipulate the co copy_attach_detach_tags|Yes|LMW|Copy and paste tags from/to images cr2hdr|Yes|L|Process image created with Magic Lantern Dual ISO enfuseAdvanced|No|LMW|Merge multiple images into Dynamic Range Increase (DRI) or Depth From Focus (DFF) images +exportLUT|Yes|LMW|Create a LUT from a style and export it ext_editor|No|LW|Export pictures to collection and edit them with up to nine user-defined external editors face_recognition|No|LM|Identify and tag images using facial recognition fujifilm_ratings|No|LM|Support importing Fujifilm ratings @@ -49,6 +50,7 @@ gpx_export|No|LMW|Export a GPX track file from selected images GPS data HDRMerge|No|LMW|Combine the selected images into an HDR DNG and return the result hugin|No|LMW|Combine selected images into a panorama and return the result image_stack|No|LMW|Combine a stack of images to remove noise or transient objects +image_time|Yes|LMW|Adjust the EXIF image time kml_export|No|L|Export photos with a KML file for usage in Google Earth LabelsToTags|Yes|LMW|Apply tags based on color labels and ratings OpenInExplorer|No|LMW|Open the selected images in the system file manager @@ -215,7 +217,7 @@ Open a terminal and start darktable with the command `darktable -d lua`. This pr ### Windows -Open the Git Bash Shell. Start darktable with the command `/c/Program\ Files/darktable/bin/darktable -d lua`. This provides debugging information to give you insight into what is happening. +Open a command prompt. Start darktable with the command C:\"Program Files\darktable\bind\darktable" -d lua > log.txt. This provides debugging information to give you insight into what is happening. ## Contributing From 797d668ebb71720e749eb6728d81f3aae2cfb8f9 Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Tue, 4 Aug 2020 11:11:41 -0400 Subject: [PATCH 36/70] Fixed typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6b9a0f3..438f508 100644 --- a/README.md +++ b/README.md @@ -217,7 +217,7 @@ Open a terminal and start darktable with the command `darktable -d lua`. This pr ### Windows -Open a command prompt. Start darktable with the command C:\"Program Files\darktable\bind\darktable" -d lua > log.txt. This provides debugging information to give you insight into what is happening. +Open a command prompt. Start darktable with the command "C:\Program Files\darktable\bin\darktable" -d lua > log.txt. This provides debugging information to give you insight into what is happening. ## Contributing From d1e330eee07bdae2792b2204fe97edd473e21b17 Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sat, 8 Aug 2020 22:01:58 -0400 Subject: [PATCH 37/70] Added check to ensure we are in lighttable view prior to callling darktable.register_lib. If darktable was invoked in single image (darkroom) mode, then an event handler is registered to detect the change from darkroom mode to lighttable mode so that we can then call darktable.register_lib. --- tools/script_manager.lua | 52 ++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 15 deletions(-) diff --git a/tools/script_manager.lua b/tools/script_manager.lua index 0946ae5..9592a7e 100644 --- a/tools/script_manager.lua +++ b/tools/script_manager.lua @@ -450,6 +450,26 @@ local function link_downloads_directory() os.execute("ln -s " .. "$HOME/Downloads " .. LUA_DIR .. "/downloads") end +local function install_module() + if not sm.module_installed then + dt.register_lib( + "script_manager", -- Module name + "script manager", -- Visible name + true, -- expandable + false, -- resetable + {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_LEFT_CENTER", 0}}, -- containers + dt.new_widget("box") -- widget + { + orientation = "vertical", + sm.main_box, + }, + nil,-- view_enter + nil -- view_leave + ) + sm.module_installed = true + end +end + -- - - - - - - - - - - - - - - - - - - - - - - - -- M A I N P R O G R A M -- - - - - - - - - - - - - - - - - - - - - - - - @@ -466,6 +486,8 @@ sm.script_names = {} sm.script_paths = {} sm.main_menu_choices = {} sm.main_stack_items = {} +sm.event_registered = false +sm.module_installed = false -- see if we've run this before @@ -742,21 +764,21 @@ sm.main_box = dt.new_widget("box"){ -- D A R K T A B L E I N T E G R A T I O N -- - - - - - - - - - - - - - - - - - - - - - - - --- register the module -dt.register_lib( - "script_manager", -- Module name - "script manager", -- Visible name - true, -- expandable - false, -- resetable - {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_LEFT_CENTER", 0}}, -- containers - dt.new_widget("box") -- widget - { - orientation = "vertical", - sm.main_box, - }, - nil,-- view_enter - nil -- view_leave -) +if dt.gui.current_view().name == "lighttable" then + install_module() +else + if not sm.event_registered then + dt.register_event( + "view-changed", + function(event, old_view, new_view) + if new_view.name == "lighttable" and old_view.name == "darkroom" then + install_module() + end + end + ) + sm.event_registered = true + end +end -- set up the scripts block if we have them otherwise we'll wait until we download them From 50be8a924044a0bd2b919e2513d9bb89aaa99ae0 Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sat, 8 Aug 2020 22:11:29 -0400 Subject: [PATCH 38/70] Added check to ensure we are in lighttable view prior to callling darktable.register_lib. If darktable was invoked in single image (darkroom) mode, then an event handler is registered to detect the change from darkroom mode to lighttable mode so that we can then call darktable.register_lib. --- official/enfuse.lua | 66 +++++++++++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 20 deletions(-) diff --git a/official/enfuse.lua b/official/enfuse.lua index 3b5bb7c..7432a1e 100644 --- a/official/enfuse.lua +++ b/official/enfuse.lua @@ -46,10 +46,35 @@ du.check_min_api_version("3.0.0", "enfuse") -- Tell gettext where to find the .mo file translating messages for a particular domain gettext.bindtextdomain("enfuse",dt.configuration.config_dir..PS .. "lua" .. PS .. "locale" .. PS) +local enf = {} +enf.event_registered = false +enf.module_installed = false +enf.lib_widgets = {} + local function _(msgid) return gettext.dgettext("enfuse", msgid) end +local function install_module() + if not enf.module_installed then + dt.register_lib( + "enfuse", -- plugin name + "enfuse", -- name + true, -- expandable + false, -- resetable + {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, -- containers + dt.new_widget("box") -- widget + { + orientation = "vertical", + sensitive = enfuse_installed, + table.unpack(enf.lib_widgets) + }, + nil,-- view_enter + nil -- view_leave + ) + enf.module_installed = true + end +end -- add a new lib -- is enfuse installed? local enfuse_installed = df.check_if_bin_exists("enfuse") @@ -229,30 +254,31 @@ if enfuse_installed then local lib_widgets = {} if not enfuse_installed then - table.insert(lib_widgets, df.executable_path_widget({"ffmpeg"})) + table.insert(enf.lib_widgets, df.executable_path_widget({"ffmpeg"})) end - table.insert(lib_widgets, exposure_mu) - table.insert(lib_widgets, depth) - table.insert(lib_widgets, blend_colorspace) - table.insert(lib_widgets, enfuse_button) + table.insert(enf.lib_widgets, exposure_mu) + table.insert(enf.lib_widgets, depth) + table.insert(enf.lib_widgets, blend_colorspace) + table.insert(enf.lib_widgets, enfuse_button) -- ... and tell dt about it all - dt.register_lib( - "enfuse", -- plugin name - "enfuse", -- name - true, -- expandable - false, -- resetable - {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, -- containers - dt.new_widget("box") -- widget - { - orientation = "vertical", - sensitive = enfuse_installed, - table.unpack(lib_widgets) - }, - nil,-- view_enter - nil -- view_leave - ) + if dt.gui.current_view().name == "lighttable" then + install_module() + else + if not enf.event_registered then + dt.register_event( + "view-changed", + function(event, old_view, new_view) + if new_view.name == "lighttable" and old_view.name == "darkroom" then + dt.print_log("view changed from darkroom to lighttable") + install_module() + end + end + ) + enf.event_registered = true + end + end else dt.print_error("enfuse executable not found") error("enfuse executable not found") From 4e68e420ccf2236641fe3c2c525aee9a631ece23 Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sat, 8 Aug 2020 22:40:40 -0400 Subject: [PATCH 39/70] removed debugging print statemant --- official/enfuse.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/official/enfuse.lua b/official/enfuse.lua index 7432a1e..4213b48 100644 --- a/official/enfuse.lua +++ b/official/enfuse.lua @@ -271,7 +271,6 @@ if enfuse_installed then "view-changed", function(event, old_view, new_view) if new_view.name == "lighttable" and old_view.name == "darkroom" then - dt.print_log("view changed from darkroom to lighttable") install_module() end end From 2ddd0965cd16302304c16925f9d9ff2cccc3e089 Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sat, 8 Aug 2020 22:40:54 -0400 Subject: [PATCH 40/70] Added check to ensure we are in lighttable view prior to callling darktable.register_lib. If darktable was invoked in single image (darkroom) mode, then an event handler is registered to detect the change from darkroom mode to lighttable mode so that we can then call darktable.register_lib. --- examples/moduleExample.lua | 94 ++++++++++++++++++++++++++------------ 1 file changed, 66 insertions(+), 28 deletions(-) diff --git a/examples/moduleExample.lua b/examples/moduleExample.lua index 2c46a08..12de682 100644 --- a/examples/moduleExample.lua +++ b/examples/moduleExample.lua @@ -46,6 +46,44 @@ local function _(msgid) return gettext.dgettext("moduleExample", msgid) end +-- declare a local namespace and a couple of variables we'll need to install the module +local mE = {} +mE.widgets = {} +mE.event_registered = false -- keep track of whether we've added an event callback or not +mE.module_installed = false -- keep track of whether the module is module_installed + +--[[ We have to create the module in one of two ways depending on which view darktable starts + in. In orker to not repeat code, we wrap the darktable.register_lib in a local function. + ]] + +local function install_module() + if not mE.module_installed then + -- https://www.darktable.org/lua-api/index.html#darktable_register_lib + dt.register_lib( + "exampleModule", -- Module name + "exampleModule", -- name + true, -- expandable + false, -- resetable + {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, -- containers + -- https://www.darktable.org/lua-api/types_lua_box.html + dt.new_widget("box") -- widget + { + orientation = "vertical", + dt.new_widget("button") + { + label = _("MyButton"), + clicked_callback = function (_) + dt.print(_("Button clicked")) + end + }, + table.unpack(mE.widgets), + }, + nil,-- view_enter + nil -- view_leave + ) + mE.module_installed = true + end +end -- https://www.darktable.org/lua-api/types_lua_check_button.html local check_button = dt.new_widget("check_button"){label = _("MyCheck_button"), value = true} @@ -90,35 +128,35 @@ local slider = dt.new_widget("slider") value = 52 -- The current value of the slider } --- https://www.darktable.org/lua-api/index.html#darktable_register_lib -dt.register_lib( - "exampleModule", -- Module name - "exampleModule", -- name - true, -- expandable - false, -- resetable - {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, -- containers - -- https://www.darktable.org/lua-api/types_lua_box.html - dt.new_widget("box") -- widget - { - orientation = "vertical", - dt.new_widget("button") - { - label = _("MyButton"), - clicked_callback = function (_) - dt.print(_("Button clicked")) +-- pack the widgets in a table for loading in the module + +table.insert(mE.widgets, check_button) +table.insert(mE.widgets, combobox) +table.insert(mE.widgets, entry) +table.insert(mE.widgets, file_chooser_button) +table.insert(mE.widgets, label) +table.insert(mE.widgets, separator) +table.insert(mE.widgets, slider) + +-- ... and tell dt about it all + + +if dt.gui.current_view().name == "lighttable" then -- make sure we are in lighttable view + install_module() -- register the lib +else + if not mE.event_registered then -- if we are not in lighttable view then register an event to signal when we might be + -- https://www.darktable.org/lua-api/index.html#darktable_register_event + dt.register_event( + "view-changed", -- we want to be informed when the view changes + function(event, old_view, new_view) + if new_view.name == "lighttable" and old_view.name == "darkroom" then -- if the view changes from darkroom to lighttable + install_module() -- register the lib + end end - }, - check_button, - combobox, - entry, - file_chooser_button, - label, - separator, - slider - }, - nil,-- view_enter - nil -- view_leave -) + ) + mE.event_registered = true -- keep track of whether we have an event handler installed + end +end -- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua -- kate: hl Lua; From cc4f1d7251e24e74a1a8510129e234ff832a5d9a Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sat, 8 Aug 2020 23:11:33 -0400 Subject: [PATCH 41/70] Added check to ensure we are in lighttable view prior to callling darktable.register_lib. If darktable was invoked in single image (darkroom) mode, then an event handler is registered to detect the change from darkroom mode to lighttable mode so that we can then call darktable.register_lib. --- official/image_path_in_ui.lua | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/official/image_path_in_ui.lua b/official/image_path_in_ui.lua index 18e57ca..60bcce6 100644 --- a/official/image_path_in_ui.lua +++ b/official/image_path_in_ui.lua @@ -33,8 +33,22 @@ local du = require "lib/dtutils" du.check_min_api_version("2.0.0", "image_path_in_ui") +local ipiu = {} +ipiu.module_installed = false +ipiu.event_registered = false + local main_label = dt.new_widget("label"){selectable = true, ellipsize = "middle", halign = "start"} +local function install_module() + if not ipiu.module_installed then + dt.register_lib("image_path_no_ui","Selected Images path",true,false,{ + [dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_LEFT_CENTER",300} + }, main_label + ) + ipiu.module_installed = true + end +end + local function reset_widget() local selection = dt.gui.selection() local result = "" @@ -54,10 +68,21 @@ end main_label.reset_callback = reset_widget -dt.register_lib("image_path_no_ui","Selected Images path",true,false,{ - [dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_LEFT_CENTER",300} - }, main_label - ); +if dt.gui.current_view().name == "lighttable" then + install_module() +else + if not ipiu.event_registered then + dt.register_event( + "view-changed", + function(event, old_view, new_view) + if new_view.name == "lighttable" and old_view.name == "darkroom" then + install_module() + end + end + ) + ipiu.event_registered = true + end +end dt.register_event("mouse-over-image-changed",reset_widget); From d05536bed4697f2ce2b802775b5f799d0d073d82 Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sat, 8 Aug 2020 23:21:54 -0400 Subject: [PATCH 42/70] Added check to ensure we are in lighttable view prior to callling darktable.register_lib. If darktable was invoked in single image (darkroom) mode, then an event handler is registered to detect the change from darkroom mode to lighttable mode so that we can then call darktable.register_lib. --- contrib/AutoGrouper.lua | 65 +++++++++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 18 deletions(-) diff --git a/contrib/AutoGrouper.lua b/contrib/AutoGrouper.lua index 0d92915..18ff103 100644 --- a/contrib/AutoGrouper.lua +++ b/contrib/AutoGrouper.lua @@ -45,6 +45,17 @@ local function _(msgid) return gettext.dgettext("AutoGrouper", msgid) end +local Ag = {} +Ag.module_installed = false +Ag.event_registered = false + +local GUI = { + gap = {}, + selected = {}, + collection = {} +} + + local function InRange(test, low, high) --tests if test value is within range of low and high (inclusive) if test >= low and test <= high then return true @@ -111,12 +122,26 @@ local function main(on_collection) end end +local function install_module() + if not Ag.module_installed then + dt.register_lib( + 'AutoGroup_Lib', -- Module name + _('auto group'), -- name + true, -- expandable + true, -- resetable + {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 99}}, -- containers + dt.new_widget("box"){ + orientation = "vertical", + GUI.gap, + GUI.selected, + GUI.collection + } + ) + Ag.module_installed = true + end +end + -- GUI -- -GUI = { - gap = {}, - selected = {}, - collection = {} -} temp = dt.preferences.read(MOD, 'active_gap', 'integer') if not InRange(temp, 1, 86400) then temp = 3 end GUI.gap = dt.new_widget('slider'){ @@ -143,16 +168,20 @@ GUI.collection = dt.new_widget("button"){ tooltip =_('auto group the entire collection'), clicked_callback = function() main(true) end } -dt.register_lib( - 'AutoGroup_Lib', -- Module name - _('auto group'), -- name - true, -- expandable - true, -- resetable - {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 99}}, -- containers - dt.new_widget("box"){ - orientation = "vertical", - GUI.gap, - GUI.selected, - GUI.collection - } -) + +if dt.gui.current_view().name == "lighttable" then + install_module() +else + if not Ag.event_registered then + dt.register_event( + "view-changed", + function(event, old_view, new_view) + if new_view.name == "lighttable" and old_view.name == "darkroom" then + install_module() + end + end + ) + Ag.event_registered = true + end +end + From 994b9c6472da4b99750b7ec155671ccdc498ebe8 Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sat, 8 Aug 2020 23:28:50 -0400 Subject: [PATCH 43/70] Added check to ensure we are in lighttable view prior to callling darktable.register_lib. If darktable was invoked in single image (darkroom) mode, then an event handler is registered to detect the change from darkroom mode to lighttable mode so that we can then call darktable.register_lib. --- contrib/quicktag.lua | 66 ++++++++++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 20 deletions(-) diff --git a/contrib/quicktag.lua b/contrib/quicktag.lua index 31a4b79..104c4fe 100644 --- a/contrib/quicktag.lua +++ b/contrib/quicktag.lua @@ -47,6 +47,12 @@ local dt = require "darktable" local du = require "lib/dtutils" local debug = require "darktable.debug" +local qt = {} +qt.module_installed = false +qt.event_registered = false +qt.widget_table = {} + + local gettext = dt.gettext @@ -177,6 +183,27 @@ local function update_quicktag_list() end end +local function install_module() + if not qt.module_installed then + dt.register_lib( + "quicktag", -- Module name + "quicktag", -- name + true, -- expandable + false, -- resetable + {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 490}}, + + dt.new_widget("box"){ + orientation = "vertical", + table.unpack(qt.widget_table), + + }, + nil,-- view_enter + nil -- view_leave + ) + qt.module_installed = true + end +end + update_quicktag_list() local new_quicktag = dt.new_widget("entry"){ @@ -213,33 +240,32 @@ local new_qt_widget = dt.new_widget ("box") { -- back UI elements in a table -- thanks to wpferguson for the hint -local widget_table = {} for i=1,qnr do - widget_table[#widget_table + 1] = button[i] + qt.widget_table[#qt.widget_table + 1] = button[i] end -widget_table[#widget_table + 1] = dt.new_widget("separator"){} -widget_table[#widget_table + 1] = old_quicktag -widget_table[#widget_table + 1] = new_qt_widget +qt.widget_table[#qt.widget_table + 1] = dt.new_widget("separator"){} +qt.widget_table[#qt.widget_table + 1] = old_quicktag +qt.widget_table[#qt.widget_table + 1] = new_qt_widget --create module -dt.register_lib( - "quicktag", -- Module name - "quicktag", -- name - true, -- expandable - false, -- resetable - {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 490}}, - - dt.new_widget("box"){ - orientation = "vertical", - table.unpack(widget_table), - - }, - nil,-- view_enter - nil -- view_leave -) +if dt.gui.current_view().name == "lighttable" then + install_module() +else + if not qt.event_registered then + dt.register_event( + "view-changed", + function(event, old_view, new_view) + if new_view.name == "lighttable" and old_view.name == "darkroom" then + install_module() + end + end + ) + qt.event_registered = true + end +end -- create shortcuts for i=1,qnr do From be5557080b1afb3486568e4d5f169402d87faa92 Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sat, 8 Aug 2020 23:38:48 -0400 Subject: [PATCH 44/70] Added check to ensure we are in lighttable view prior to callling darktable.register_lib. If darktable was invoked in single image (darkroom) mode, then an event handler is registered to detect the change from darkroom mode to lighttable mode so that we can then call darktable.register_lib. --- contrib/transfer_hierarchy.lua | 40 +++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/contrib/transfer_hierarchy.lua b/contrib/transfer_hierarchy.lua index c2ba9cb..70bb598 100755 --- a/contrib/transfer_hierarchy.lua +++ b/contrib/transfer_hierarchy.lua @@ -99,6 +99,10 @@ end -- Helper functions: BEGIN +local th = {} +th.module_installed = false +th.event_registered = false + local function pathExists(path) local success, err, errno = os.rename(path, path) if not success then @@ -122,6 +126,16 @@ local function createDirectory(path) end end +local function install_module() + if not th.module_installed then + darktable.register_lib(LIB_ID, + "transfer hierarchy", true, true, { + [darktable.gui.views.lighttable] = { "DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 700 } + }, th.transfer_widget, nil, nil) + th.module_installed = true + end +end + -- Helper functions: END @@ -292,7 +306,7 @@ end -local transfer_widget = darktable.new_widget("box") { +th.transfer_widget = darktable.new_widget("box") { orientation = "vertical", darktable.new_widget("button") { label = _("calculate"), @@ -347,12 +361,18 @@ darktable.preferences.register( -- Preferences: END - - - - - -darktable.register_lib(LIB_ID, - "transfer hierarchy", true, true, { - [darktable.gui.views.lighttable] = { "DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 700 } - }, transfer_widget, nil, nil) +if darktable.gui.current_view().name == "lighttable" then + install_module() +else + if not th.event_registered then + darktable.register_event( + "view-changed", + function(event, old_view, new_view) + if new_view.name == "lighttable" and old_view.name == "darkroom" then + install_module() + end + end + ) + th.event_registered = true + end +end From 8a710798f7f01924b9d0cd76ee4b54cce2955984 Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sun, 9 Aug 2020 00:17:34 -0400 Subject: [PATCH 45/70] Added check to ensure we are in lighttable view prior to callling darktable.register_lib. If darktable was invoked in single image (darkroom) mode, then an event handler is registered to detect the change from darkroom mode to lighttable mode so that we can then call darktable.register_lib. --- contrib/ext_editor.lua | 58 ++++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 14 deletions(-) diff --git a/contrib/ext_editor.lua b/contrib/ext_editor.lua index 4035c22..6999c05 100644 --- a/contrib/ext_editor.lua +++ b/contrib/ext_editor.lua @@ -84,6 +84,12 @@ du.check_min_api_version("5.0.2", MODULE_NAME) -- darktable 3.x -- OS compatibility local PS = dt.configuration.running_os == "windows" and "\\" or "/" +-- namespace +local ee = {} +ee.module_installed = false +ee.event_registered = false +ee.widgets = {} + -- translation local gettext = dt.gettext @@ -329,6 +335,26 @@ local function export2collection(storage, image_table, extra_data) dt.print (_("finished exporting")) end +-- install the module in the UI +local function install_module() + if not ee.module_installed then + -- register new module "external editors" in lighttable ------------------------ + dt.register_lib( + MODULE_NAME, + _("external editors"), + true, -- expandable + false, -- resetable + {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, + dt.new_widget("box") { + orientation = "vertical", + table.unpack(ee.widgets), + }, + nil, -- view_enter + nil -- view_leave + ) + ee.module_installed = true + end +end -- combobox, with variable number of entries ---------------------------------- local combobox = dt.new_widget("combobox") { @@ -381,22 +407,26 @@ local box1 = dt.new_widget("box") { button_update_list } +table.insert(ee.widgets, combobox) +table.insert(ee.widgets, box1) -- register new module "external editors" in lighttable ------------------------ -dt.register_lib( - MODULE_NAME, - _("external editors"), - true, -- expandable - false, -- resetable - {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, - dt.new_widget("box") { - orientation = "vertical", - combobox, - box1 - }, - nil, -- view_enter - nil -- view_leave - ) +if dt.gui.current_view().name == "lighttable" then + install_module() +else + if not ee.event_registered then + dt.register_event( + "view-changed", + function(event, old_view, new_view) + if new_view.name == "lighttable" and old_view.name == "darkroom" then + install_module() + end + end + ) + ee.event_registered = true + end +end + -- initialize list of programs and widgets ------------------------------------ From 138b23674a2b428c2440f8674af4b20890f1be97 Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sun, 9 Aug 2020 00:36:43 -0400 Subject: [PATCH 46/70] Added check to ensure we are in lighttable view prior to callling darktable.register_lib. If darktable was invoked in single image (darkroom) mode, then an event handler is registered to detect the change from darkroom mode to lighttable mode so that we can then call darktable.register_lib. --- contrib/photils.lua | 53 +++++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/contrib/photils.lua b/contrib/photils.lua index 1c72f4b..cc41b34 100644 --- a/contrib/photils.lua +++ b/contrib/photils.lua @@ -91,7 +91,13 @@ local PHOTILS = { per_page = 10, selected_tags = {}, in_pagination = false, - tagged_image = "" + tagged_image = "", + module_installed = false, + event_registered = false, + plugin_display_views = { + [dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}, + [dt.gui.views.darkroom] = {"DT_UI_CONTAINER_PANEL_LEFT_CENTER", 100} + }, } local GUI = { @@ -358,6 +364,21 @@ function PHOTILS.on_reset(with_view) GUI.attach_button.sensitive = false end +local function install_module() + if not PHOTILS.module_installed then + dt.register_lib(MODULE_NAME, + "photils autotagger", + true, + true, + PHOTILS.plugin_display_views, + GUI.container, + nil, + nil + ) + PHOTILS.module_installed = true + end +end + -- add a fix number of buttons for _ = 1, PHOTILS.per_page, 1 do local btn_tag = dt.new_widget("check_button") { @@ -402,10 +423,6 @@ table.insert(GUI.container, GUI.stack) GUI.stack.active = 1 -local plugin_display_views = { - [dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}, - [dt.gui.views.darkroom] = {"DT_UI_CONTAINER_PANEL_LEFT_CENTER", 100} -} -- uses photils: prefix because script settings are all together and not seperated by script @@ -417,12 +434,20 @@ dt.preferences.register(MODULE_NAME, true) dt.register_event("mouse-over-image-changed",PHOTILS.image_changed) -dt.register_lib(MODULE_NAME, - "photils autotagger", - true, - true, - plugin_display_views, - GUI.container, - nil, - nil -) + +if dt.gui.current_view().name == "lighttable" then + install_module() +else + if not PHOTILS.event_registered then + dt.register_event( + "view-changed", + function(event, old_view, new_view) + if new_view.name == "lighttable" and old_view.name == "darkroom" then + install_module() + end + end + ) + PHOTILS.event_registered = true + end +end + From 52acdb9036b463e528e2fb27cc44bc4507ecb141 Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sun, 9 Aug 2020 00:45:27 -0400 Subject: [PATCH 47/70] Added check to ensure we are in lighttable view prior to callling darktable.register_lib. If darktable was invoked in single image (darkroom) mode, then an event handler is registered to detect the change from darkroom mode to lighttable mode so that we can then call darktable.register_lib. --- contrib/copy_attach_detach_tags.lua | 65 ++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 20 deletions(-) diff --git a/contrib/copy_attach_detach_tags.lua b/contrib/copy_attach_detach_tags.lua index 2fb8330..9b43c47 100644 --- a/contrib/copy_attach_detach_tags.lua +++ b/contrib/copy_attach_detach_tags.lua @@ -51,6 +51,11 @@ local function _(msgid) return gettext.dgettext("copy_attach_detach_tags", msgid) end +local cadt = {} +cadt.module_installed = false +cadt.event_registered = false +cadt.widget_table = {} + local image_tags = {} @@ -156,6 +161,26 @@ local function replace_tags() dt.print(_('Tags replaced')) end +local function install_module() + if not cadt.module_installed then + dt.register_lib("tagging_addon","Tagging addon",true,true,{ + [dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER",500} + }, + dt.new_widget("box") { + -- orientation = "vertical", + reset_callback = function() + taglist_label.label = "" + image_tags = {} + end, + table.unpack(cadt.widget_table), + }, + nil, + nil + ) + cadt.module_installed = true + end +end + -- create modul Tagging addons taglist_label.reset_callback = mcopy_tags @@ -190,31 +215,31 @@ local box2 = dt.new_widget("box"){ local sep = dt.new_widget("separator"){} -- pack elements into widget table for a nicer layout -local widget_table = {} -widget_table[1] = box1 -widget_table[#widget_table+1] = box2 +cadt.widget_table[1] = box1 +cadt.widget_table[#cadt.widget_table+1] = box2 -widget_table[#widget_table+1] = sep -widget_table[#widget_table+1] = taglabel -widget_table[#widget_table+1] = taglist_label +cadt.widget_table[#cadt.widget_table+1] = sep +cadt.widget_table[#cadt.widget_table+1] = taglabel +cadt.widget_table[#cadt.widget_table+1] = taglist_label -- create modul -dt.register_lib("tagging_addon","Tagging addon",true,true,{ - [dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER",500} - }, - dt.new_widget("box") { - -- orientation = "vertical", - reset_callback = function() - taglist_label.label = "" - image_tags = {} - end, - table.unpack(widget_table), - }, - nil, - nil - ) +if dt.gui.current_view().name == "lighttable" then + install_module() +else + if not cadt.event_registered then + dt.register_event( + "view-changed", + function(event, old_view, new_view) + if new_view.name == "lighttable" and old_view.name == "darkroom" then + install_module() + end + end + ) + cadt.event_registered = true + end +end -- shortcut for copy From 5f5ad426bf1acbbfa3b28a7717a9d2aa83a9d007 Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sun, 9 Aug 2020 01:01:33 -0400 Subject: [PATCH 48/70] Added check to ensure we are in lighttable view prior to callling darktable.register_lib. If darktable was invoked in single image (darkroom) mode, then an event handler is registered to detect the change from darkroom mode to lighttable mode so that we can then call darktable.register_lib. --- contrib/rename-tags.lua | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/contrib/rename-tags.lua b/contrib/rename-tags.lua index a0c70be..f385a7a 100644 --- a/contrib/rename-tags.lua +++ b/contrib/rename-tags.lua @@ -35,6 +35,10 @@ local debug = require "darktable.debug" -- check API version du.check_min_api_version("3.0.0", "rename-tags") +local rt = {} +rt.module_installed = false +rt.event_registered = false + -- GUI entries local old_tag = darktable.new_widget("entry") { tooltip = "Enter old tag" } local new_tag = darktable.new_widget("entry") { tooltip = "Enter new tag" } @@ -99,6 +103,13 @@ local function rename_tags() rename_reset() end +local function install_module() + if not rt.module_installed then + darktable.register_lib ("rename_tags", "rename tag", true, true, {[darktable.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 20},}, rt.rename_widget, nil, nil) + rt.module_installed = true + end +end + -- GUI local old_widget = darktable.new_widget ("box") { orientation = "horizontal", @@ -112,7 +123,7 @@ local new_widget = darktable.new_widget ("box") { new_tag } -local rename_widget = darktable.new_widget ("box") { +rt.rename_widget = darktable.new_widget ("box") { orientation = "vertical", reset_callback = rename_reset, old_widget, @@ -120,6 +131,20 @@ local rename_widget = darktable.new_widget ("box") { darktable.new_widget("button") { label = "Go", clicked_callback = rename_tags } } +if darktable.gui.current_view().name == "lighttable" then + install_module() +else + if not rt.event_registered then + darktable.register_event( + "view-changed", + function(event, old_view, new_view) + if new_view.name == "lighttable" and old_view.name == "darkroom" then + install_module() + end + end + ) + rt.event_registered = true + end +end -darktable.register_lib ("rename_tags", "rename tag", true, true, {[darktable.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 20},}, rename_widget, nil, nil) From 432b6b5dd767a5952c9026941c8f44c5a1e84dcd Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sun, 9 Aug 2020 01:21:17 -0400 Subject: [PATCH 49/70] Added check to ensure we are in lighttable view prior to callling darktable.register_lib. If darktable was invoked in single image (darkroom) mode, then an event handler is registered to detect the change from darkroom mode to lighttable mode so that we can then call darktable.register_lib. --- contrib/geoToolbox.lua | 52 +++++++++++++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/contrib/geoToolbox.lua b/contrib/geoToolbox.lua index 19e3c7c..5a30862 100644 --- a/contrib/geoToolbox.lua +++ b/contrib/geoToolbox.lua @@ -40,6 +40,12 @@ local function _(msgid) return gettext.dgettext("geoToolbox", msgid) end + +local gT = {} +gT.module_installed = false +gT.event_registered = false + + -- local labelDistance = dt.new_widget("label") labelDistance.label = _("Distance:") @@ -572,6 +578,22 @@ local function altitude_profile() end +local function install_module() + if not gT.module_installed then + dt.register_lib( + "geoToolbox", -- Module name + "geo toolbox", -- name + true, -- expandable + false, -- resetable + {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, -- containers + gT.widget, + nil,-- view_enter + nil -- view_leave + ) + gT.module_installed = true + end +end + local separator = dt.new_widget("separator"){} local separator2 = dt.new_widget("separator"){} @@ -579,13 +601,7 @@ local separator3 = dt.new_widget("separator"){} local separator4 = dt.new_widget("separator"){} local separator5 = dt.new_widget("separator"){} -dt.register_lib( - "geoToolbox", -- Module name - "geo toolbox", -- name - true, -- expandable - false, -- resetable - {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, -- containers - dt.new_widget("box") +gT.widget = dt.new_widget("box") { orientation = "vertical", dt.new_widget("button") @@ -664,10 +680,24 @@ dt.register_lib( clicked_callback = altitude_profile }, labelDistance - }, - nil,-- view_enter - nil -- view_leave -) + } + + +if dt.gui.current_view().name == "lighttable" then + install_module() +else + if not gT.event_registered then + dt.register_event( + "view-changed", + function(event, old_view, new_view) + if new_view.name == "lighttable" and old_view.name == "darkroom" then + install_module() + end + end + ) + gT.event_registered = true + end +end -- Preferences dt.preferences.register("geoToolbox", From 880ec7fc587660f18bf7579137ec4b9f6b27e796 Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sun, 9 Aug 2020 01:26:45 -0400 Subject: [PATCH 50/70] Added check to ensure we are in lighttable view prior to callling darktable.register_lib. If darktable was invoked in single image (darkroom) mode, then an event handler is registered to detect the change from darkroom mode to lighttable mode so that we can then call darktable.register_lib. --- contrib/gpx_export.lua | 74 +++++++++++++++++++++++++++++------------- 1 file changed, 51 insertions(+), 23 deletions(-) diff --git a/contrib/gpx_export.lua b/contrib/gpx_export.lua index b6fed82..e36b623 100644 --- a/contrib/gpx_export.lua +++ b/contrib/gpx_export.lua @@ -36,6 +36,10 @@ local function _(msgid) return gettext.dgettext("gpx_export", msgid) end +local gpx = {} +gpx.module_installed = false +gpx.event_registered = false + local path_entry = dt.new_widget("entry") { text = dt.preferences.read("gpx_exporter", "gpxExportPath", "string"), @@ -127,31 +131,55 @@ local function create_gpx_file() end end -dt.register_lib( - "gpx_exporter", - "gpx export", - true, -- expandable - true, -- resetable - {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, -- containers +local function install_module() + if not gpx.module_installed then + dt.register_lib( + "gpx_exporter", + "gpx export", + true, -- expandable + true, -- resetable + {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, -- containers + gpx.widget, + nil,-- view_enter + nil -- view_leave + ) + gpx.module_installed = true + end +end + +gpx.widget = dt.new_widget("box") +{ + orientation = "vertical", + dt.new_widget("button") + { + label = _("export"), + tooltip = _("export gpx file"), + clicked_callback = create_gpx_file + }, dt.new_widget("box") { - orientation = "vertical", - dt.new_widget("button") + orientation = "horizontal", + dt.new_widget("label") { - label = _("export"), - tooltip = _("export gpx file"), - clicked_callback = create_gpx_file - }, - dt.new_widget("box") - { - orientation = "horizontal", - dt.new_widget("label") - { - label = _("file:"), - }, - path_entry + label = _("file:"), }, + path_entry }, - nil,-- view_enter - nil -- view_leave -) +} + + +if dt.gui.current_view().name == "lighttable" then + install_module() +else + if not gpx.event_registered then + dt.register_event( + "view-changed", + function(event, old_view, new_view) + if new_view.name == "lighttable" and old_view.name == "darkroom" then + install_module() + end + end + ) + gpx.event_registered = true + end +end From d10cf968f19976f4b17f37e52e8f3c6285bad71e Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sun, 9 Aug 2020 01:33:09 -0400 Subject: [PATCH 51/70] Added check to ensure we are in lighttable view prior to callling darktable.register_lib. If darktable was invoked in single image (darkroom) mode, then an event handler is registered to detect the change from darkroom mode to lighttable mode so that we can then call darktable.register_lib. --- contrib/exportLUT.lua | 67 +++++++++++++++++++++++++++++++------------ 1 file changed, 48 insertions(+), 19 deletions(-) diff --git a/contrib/exportLUT.lua b/contrib/exportLUT.lua index aa76b0d..bd35fb3 100644 --- a/contrib/exportLUT.lua +++ b/contrib/exportLUT.lua @@ -41,6 +41,11 @@ end du.check_min_api_version("5.0.0", "exportLUT") +local eL = {} +eL.module_installed = false +eL.event_registered = false +eL.widgets = {} + -- Thanks Kevin Ertel for this bit local os_path_seperator = '/' if dt.configuration.running_os == 'windows' then os_path_seperator = '\\' end @@ -119,27 +124,51 @@ local function export_luts() end end +local function install_module() + if not eL.module_installed then + dt.register_lib( + _("export haldclut"), + _("export haldclut"), + true, + false, + {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, + dt.new_widget("box") + { + orientation = "vertical", + table.unpack(eL.widgets), + }, + nil, + nil + ) + eL.module_installed = true + end +end + local export_button = dt.new_widget("button"){ label = _("export"), clicked_callback = export_luts } -dt.register_lib( - _("export haldclut"), - _("export haldclut"), - true, - false, - {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, - dt.new_widget("box") - { - orientation = "vertical", - identity_label, - file_chooser_button, - output_label, - export_chooser_button, - warning_label, - export_button - }, - nil, - nil -) +table.insert(eL.widgets, identity_label) +table.insert(eL.widgets, file_chooser_button) +table.insert(eL.widgets, output_label) +table.insert(eL.widgets, export_chooser_button) +table.insert(eL.widgets, warning_label) +table.insert(eL.widgets, export_button) + +if dt.gui.current_view().name == "lighttable" then + install_module() +else + if not eL.event_registered then + dt.register_event( + "view-changed", + function(event, old_view, new_view) + if new_view.name == "lighttable" and old_view.name == "darkroom" then + install_module() + end + end + ) + eL.event_registered = true + end +end + From d4e21b78774075c6e0bc12e52fda88c7d35e8ed0 Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sun, 9 Aug 2020 01:43:20 -0400 Subject: [PATCH 52/70] Added check to ensure we are in lighttable view prior to callling darktable.register_lib. If darktable was invoked in single image (darkroom) mode, then an event handler is registered to detect the change from darkroom mode to lighttable mode so that we can then call darktable.register_lib. --- contrib/image_time.lua | 44 ++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/contrib/image_time.lua b/contrib/image_time.lua index a13a79a..676f5af 100644 --- a/contrib/image_time.lua +++ b/contrib/image_time.lua @@ -110,6 +110,8 @@ local ds = require "lib/dtutils.string" local gettext = dt.gettext local img_time = {} +img_time.module_installed = false +img_time.event_registered = false du.check_min_api_version("3.0.0", "image_time") @@ -390,6 +392,22 @@ local function reset_widgets() img_time.adir.selected = 1 end +local function install_module() + if not img_time.module_installed then + dt.register_lib( + "image_time", -- Module name + _("image time"), -- Visible name + true, -- expandable + true, -- resetable + {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, -- containers + img_time.widget, + nil,-- view_enter + nil -- view_leave + ) + img_time.module_installed = true + end +end + -- widgets img_time.widgets = { @@ -528,13 +546,19 @@ img_time.widget = dt.new_widget("box"){ img_time.stack, } -dt.register_lib( - "image_time", -- Module name - _("image time"), -- Visible name - true, -- expandable - true, -- resetable - {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, -- containers - img_time.widget, - nil,-- view_enter - nil -- view_leave -) +if dt.gui.current_view().name == "lighttable" then + install_module() +else + if not img_time.event_registered then + dt.register_event( + "view-changed", + function(event, old_view, new_view) + if new_view.name == "lighttable" and old_view.name == "darkroom" then + install_module() + end + end + ) + img_time.event_registered = true + end +end + From b8e3ec43023af8d38d68d13b971a09580be310f2 Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sun, 9 Aug 2020 01:43:31 -0400 Subject: [PATCH 53/70] Added check to ensure we are in lighttable view prior to callling darktable.register_lib. If darktable was invoked in single image (darkroom) mode, then an event handler is registered to detect the change from darkroom mode to lighttable mode so that we can then call darktable.register_lib. --- contrib/HDRMerge.lua | 47 +++++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/contrib/HDRMerge.lua b/contrib/HDRMerge.lua index ad7dd3a..aa13a1c 100644 --- a/contrib/HDRMerge.lua +++ b/contrib/HDRMerge.lua @@ -94,6 +94,10 @@ local GUI = { --GUI Elements Table } } +HDRM.module_installed = false +HDRM.event_registered = false + + --Detect User Styles-- local styles = dt.styles local styles_count = 1 -- 'none' = 1 @@ -264,6 +268,23 @@ local function main() end +local function install_module() + if not HDRM.module_installed then + dt.register_lib( -- register HDRMerge module + 'HDRMerge_Lib', -- Module name + _('HDRMerge'), -- name + true, -- expandable + true, -- resetable + {[dt.gui.views.lighttable] = {'DT_UI_CONTAINER_PANEL_RIGHT_CENTER', 99}}, -- containers + dt.new_widget('box'){ + orientation = 'vertical', + GUI.stack + } + ) + HDRM.module_installed = true + end +end + -- GUI Elements -- local lbl_hdr = dt.new_widget('section_label'){ label = _('HDRMerge options') @@ -411,14 +432,18 @@ else GUI.stack.active = 2 end -dt.register_lib( -- register HDRMerge module - 'HDRMerge_Lib', -- Module name - _('HDRMerge'), -- name - true, -- expandable - true, -- resetable - {[dt.gui.views.lighttable] = {'DT_UI_CONTAINER_PANEL_RIGHT_CENTER', 99}}, -- containers - dt.new_widget('box'){ - orientation = 'vertical', - GUI.stack - } -) +if dt.gui.current_view().name == "lighttable" then + install_module() +else + if not HDRM.event_registered then + dt.register_event( + "view-changed", + function(event, old_view, new_view) + if new_view.name == "lighttable" and old_view.name == "darkroom" then + install_module() + end + end + ) + HDRM.event_registered = true + end +end From dfb8d4e7c6b7f2219f2a8c1068d167e86c0dbb2e Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sun, 9 Aug 2020 01:48:36 -0400 Subject: [PATCH 54/70] Added check to ensure we are in lighttable view prior to callling darktable.register_lib. If darktable was invoked in single image (darkroom) mode, then an event handler is registered to detect the change from darkroom mode to lighttable mode so that we can then call darktable.register_lib. --- contrib/LabelsToTags.lua | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/contrib/LabelsToTags.lua b/contrib/LabelsToTags.lua index 044e920..29f9322 100644 --- a/contrib/LabelsToTags.lua +++ b/contrib/LabelsToTags.lua @@ -55,6 +55,10 @@ du.check_min_api_version("3.0.0", "LabelsToTags") -- Lua 5.3 no longer has "unpack" but "table.unpack" unpack = unpack or table.unpack +local ltt = {} +ltt.module_installed = false +ltt.event_registered = false + local LIB_ID = "LabelsToTags" -- Helper functions: BEGIN @@ -184,7 +188,7 @@ local function doTagging(selfC) job.valid = false end -local my_widget = darktable.new_widget("box") { +ltt.my_widget = darktable.new_widget("box") { orientation = "vertical", mappingComboBox, darktable.new_widget("button") { @@ -217,6 +221,15 @@ darktable.register_tag_mapping = function(name, mapping) mappingComboBox.reset_callback(mappingComboBox) end +local function install_module() + if not ltt.module_installed then + darktable.register_lib(LIB_ID,"labels to tags",true,true,{ + [darktable.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER",20}, + },ltt.my_widget,nil,nil) + ltt.module_installed = true + end +end + --[[ darktable.register_tag_mapping("Example", { ["+----*"] = { "Red", "Only red" }, @@ -229,6 +242,19 @@ darktable.register_tag_mapping("Example", ["*****R"] = { "Rejected" } }) ]] -darktable.register_lib(LIB_ID,"labels to tags",true,true,{ - [darktable.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER",20}, - },my_widget,nil,nil) +if darktable.gui.current_view().name == "lighttable" then + install_module() +else + if not ltt.event_registered then + darktable.register_event( + "view-changed", + function(event, old_view, new_view) + if new_view.name == "lighttable" and old_view.name == "darkroom" then + install_module() + end + end + ) + ltt.event_registered = true + end +end + From b613cc266a232baf469ceea1660a61d72867e20f Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sun, 9 Aug 2020 01:56:38 -0400 Subject: [PATCH 55/70] Added check to ensure we are in lighttable view prior to callling darktable.register_lib. If darktable was invoked in single image (darkroom) mode, then an event handler is registered to detect the change from darkroom mode to lighttable mode so that we can then call darktable.register_lib. --- contrib/face_recognition.lua | 43 +++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/contrib/face_recognition.lua b/contrib/face_recognition.lua index 26caff6..96bc4a2 100644 --- a/contrib/face_recognition.lua +++ b/contrib/face_recognition.lua @@ -55,6 +55,8 @@ local OUTPUT = dt.configuration.tmp_dir .. PS .. "facerecognition.txt" -- namespace local fc = {} +fc.module_installed = false +fc.event_registered = false -- ensure we meet the minimum api du.check_min_api_version("5.0.0", "face_recognition") @@ -337,6 +339,22 @@ local function face_recognition () end end +local function install_module() + if not fc.module_installed then + dt.register_lib( + "face_recognition", -- Module name + _("face recognition"), -- Visible name + true, -- expandable + true, -- resetable + {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 300}}, -- containers + fc.widget, + nil,-- view_enter + nil -- view_leave + ) + fc.module_installed = true + end +end + -- build the interface fc.unknown_tag = dt.new_widget("entry"){ @@ -466,16 +484,21 @@ fc.widget = dt.new_widget("box"){ table.unpack(widgets), } -dt.register_lib( - "face_recognition", -- Module name - _("face recognition"), -- Visible name - true, -- expandable - true, -- resetable - {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 300}}, -- containers - fc.widget, - nil,-- view_enter - nil -- view_leave -) +if dt.gui.current_view().name == "lighttable" then + install_module() +else + if not fc.event_registered then + dt.register_event( + "view-changed", + function(event, old_view, new_view) + if new_view.name == "lighttable" and old_view.name == "darkroom" then + install_module() + end + end + ) + fc.event_registered = true + end +end fc.tolerance.value = dt.preferences.read(MODULE, "tolerance", "float") From 912ae93d1036b78578c2568e98bf691720193818 Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sun, 9 Aug 2020 01:56:48 -0400 Subject: [PATCH 56/70] Added check to ensure we are in lighttable view prior to callling darktable.register_lib. If darktable was invoked in single image (darkroom) mode, then an event handler is registered to detect the change from darkroom mode to lighttable mode so that we can then call darktable.register_lib. --- tools/executable_manager.lua | 57 ++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 18 deletions(-) diff --git a/tools/executable_manager.lua b/tools/executable_manager.lua index f45ecb6..2bbe392 100644 --- a/tools/executable_manager.lua +++ b/tools/executable_manager.lua @@ -40,6 +40,10 @@ local gettext = dt.gettext gettext.bindtextdomain("executable_manager",dt.configuration.config_dir.."/lua/locale/") +local exec_man = {} -- our own namespace +exec_man.module_installed = false +exec_man.event_registered = false + -- - - - - - - - - - - - - - - - - - - - - - - - - - - - -- F U N C T I O N S -- - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -86,12 +90,30 @@ local function update_combobox_choices(combobox, choice_table, selected) combobox.value = selected end +local function install_module() + if not exec_man.module_installed then + dt.register_lib( + "executable_manager", -- Module name + "executable manager", -- Visible name + true, -- expandable + false, -- resetable + {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_LEFT_BOTTOM", 100}}, -- containers + dt.new_widget("box") -- widget + { + orientation = "vertical", + exec_man.selector, + exec_man.stack, + }, + nil,-- view_enter + nil -- view_leave + ) + exec_man.module_installed = true + end +end -- - - - - - - - - - - - - - - - - - - - - - - - - - - - -- M A I N P R O G R A M -- - - - - - - - - - - - - - - - - - - - - - - - - - - - -local exec_man = {} -- our own namespace - local DARKTABLERC = dt.configuration.config_dir .. PS .. "darktablerc" @@ -187,19 +209,18 @@ update_combobox_choices(exec_man.selector, exec_table, 1) -- register the lib -dt.register_lib( - "executable_manager", -- Module name - "executable manager", -- Visible name - true, -- expandable - false, -- resetable - {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_LEFT_BOTTOM", 100}}, -- containers - dt.new_widget("box") -- widget - { - orientation = "vertical", - exec_man.selector, - exec_man.stack, - }, - nil,-- view_enter - nil -- view_leave -) - +if dt.gui.current_view().name == "lighttable" then + install_module() +else + if not exec_man.event_registered then + dt.register_event( + "view-changed", + function(event, old_view, new_view) + if new_view.name == "lighttable" and old_view.name == "darkroom" then + install_module() + end + end + ) + exec_man.event_registered = true + end +end From 7d9b8dbddafa95ed55368c1a0502ba45d16ca470 Mon Sep 17 00:00:00 2001 From: supertobi Date: Mon, 10 Aug 2020 15:21:25 +0200 Subject: [PATCH 57/70] Update video_ffmpeg.lua added more framerate options --- contrib/video_ffmpeg.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/video_ffmpeg.lua b/contrib/video_ffmpeg.lua index 6755e5c..1d59935 100644 --- a/contrib/video_ffmpeg.lua +++ b/contrib/video_ffmpeg.lua @@ -96,7 +96,7 @@ local resolutions = { } } -local framerates = {"15", "16", "23.98", "24", "25", "29,97", "30", "48", "50", "59.94", "60"} +local framerates = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "15", "16", "23.98", "24", "25", "29,97", "30", "48", "50", "59.94", "60", "120", "240", "300"} local formats = { ["AVI"] = { From 509c7da3848fc32f8899007ec5f57f6fe6c68621 Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sun, 16 Aug 2020 13:18:27 -0400 Subject: [PATCH 58/70] changed darktable.current_view().name to darktable.current_view().id for view check because name is translated and id is not. --- contrib/AutoGrouper.lua | 2 +- contrib/HDRMerge.lua | 2 +- contrib/LabelsToTags.lua | 2 +- contrib/copy_attach_detach_tags.lua | 2 +- contrib/exportLUT.lua | 2 +- contrib/ext_editor.lua | 2 +- contrib/face_recognition.lua | 2 +- contrib/geoToolbox.lua | 2 +- contrib/gpx_export.lua | 2 +- contrib/image_time.lua | 2 +- contrib/photils.lua | 2 +- contrib/quicktag.lua | 2 +- contrib/rename-tags.lua | 2 +- contrib/transfer_hierarchy.lua | 2 +- examples/moduleExample.lua | 2 +- official/enfuse.lua | 2 +- official/image_path_in_ui.lua | 2 +- tools/executable_manager.lua | 2 +- tools/script_manager.lua | 2 +- 19 files changed, 19 insertions(+), 19 deletions(-) diff --git a/contrib/AutoGrouper.lua b/contrib/AutoGrouper.lua index 18ff103..4198952 100644 --- a/contrib/AutoGrouper.lua +++ b/contrib/AutoGrouper.lua @@ -169,7 +169,7 @@ GUI.collection = dt.new_widget("button"){ clicked_callback = function() main(true) end } -if dt.gui.current_view().name == "lighttable" then +if dt.gui.current_view().id == "lighttable" then install_module() else if not Ag.event_registered then diff --git a/contrib/HDRMerge.lua b/contrib/HDRMerge.lua index aa13a1c..e9e5d03 100644 --- a/contrib/HDRMerge.lua +++ b/contrib/HDRMerge.lua @@ -432,7 +432,7 @@ else GUI.stack.active = 2 end -if dt.gui.current_view().name == "lighttable" then +if dt.gui.current_view().id == "lighttable" then install_module() else if not HDRM.event_registered then diff --git a/contrib/LabelsToTags.lua b/contrib/LabelsToTags.lua index 29f9322..8c5e5a5 100644 --- a/contrib/LabelsToTags.lua +++ b/contrib/LabelsToTags.lua @@ -242,7 +242,7 @@ darktable.register_tag_mapping("Example", ["*****R"] = { "Rejected" } }) ]] -if darktable.gui.current_view().name == "lighttable" then +if darktable.gui.current_view().id == "lighttable" then install_module() else if not ltt.event_registered then diff --git a/contrib/copy_attach_detach_tags.lua b/contrib/copy_attach_detach_tags.lua index 9b43c47..43b40e2 100644 --- a/contrib/copy_attach_detach_tags.lua +++ b/contrib/copy_attach_detach_tags.lua @@ -225,7 +225,7 @@ cadt.widget_table[#cadt.widget_table+1] = taglist_label -- create modul -if dt.gui.current_view().name == "lighttable" then +if dt.gui.current_view().id == "lighttable" then install_module() else if not cadt.event_registered then diff --git a/contrib/exportLUT.lua b/contrib/exportLUT.lua index bd35fb3..9c7a184 100644 --- a/contrib/exportLUT.lua +++ b/contrib/exportLUT.lua @@ -156,7 +156,7 @@ table.insert(eL.widgets, export_chooser_button) table.insert(eL.widgets, warning_label) table.insert(eL.widgets, export_button) -if dt.gui.current_view().name == "lighttable" then +if dt.gui.current_view().id == "lighttable" then install_module() else if not eL.event_registered then diff --git a/contrib/ext_editor.lua b/contrib/ext_editor.lua index 6999c05..ea957b5 100644 --- a/contrib/ext_editor.lua +++ b/contrib/ext_editor.lua @@ -411,7 +411,7 @@ table.insert(ee.widgets, combobox) table.insert(ee.widgets, box1) -- register new module "external editors" in lighttable ------------------------ -if dt.gui.current_view().name == "lighttable" then +if dt.gui.current_view().id == "lighttable" then install_module() else if not ee.event_registered then diff --git a/contrib/face_recognition.lua b/contrib/face_recognition.lua index 96bc4a2..6d9b0c0 100644 --- a/contrib/face_recognition.lua +++ b/contrib/face_recognition.lua @@ -484,7 +484,7 @@ fc.widget = dt.new_widget("box"){ table.unpack(widgets), } -if dt.gui.current_view().name == "lighttable" then +if dt.gui.current_view().id == "lighttable" then install_module() else if not fc.event_registered then diff --git a/contrib/geoToolbox.lua b/contrib/geoToolbox.lua index 5a30862..1bce5f3 100644 --- a/contrib/geoToolbox.lua +++ b/contrib/geoToolbox.lua @@ -683,7 +683,7 @@ gT.widget = dt.new_widget("box") } -if dt.gui.current_view().name == "lighttable" then +if dt.gui.current_view().id == "lighttable" then install_module() else if not gT.event_registered then diff --git a/contrib/gpx_export.lua b/contrib/gpx_export.lua index e36b623..cb76174 100644 --- a/contrib/gpx_export.lua +++ b/contrib/gpx_export.lua @@ -168,7 +168,7 @@ gpx.widget = dt.new_widget("box") } -if dt.gui.current_view().name == "lighttable" then +if dt.gui.current_view().id == "lighttable" then install_module() else if not gpx.event_registered then diff --git a/contrib/image_time.lua b/contrib/image_time.lua index 676f5af..b285c61 100644 --- a/contrib/image_time.lua +++ b/contrib/image_time.lua @@ -546,7 +546,7 @@ img_time.widget = dt.new_widget("box"){ img_time.stack, } -if dt.gui.current_view().name == "lighttable" then +if dt.gui.current_view().id == "lighttable" then install_module() else if not img_time.event_registered then diff --git a/contrib/photils.lua b/contrib/photils.lua index cc41b34..361ba86 100644 --- a/contrib/photils.lua +++ b/contrib/photils.lua @@ -435,7 +435,7 @@ dt.preferences.register(MODULE_NAME, dt.register_event("mouse-over-image-changed",PHOTILS.image_changed) -if dt.gui.current_view().name == "lighttable" then +if dt.gui.current_view().id == "lighttable" then install_module() else if not PHOTILS.event_registered then diff --git a/contrib/quicktag.lua b/contrib/quicktag.lua index 104c4fe..09f0be9 100644 --- a/contrib/quicktag.lua +++ b/contrib/quicktag.lua @@ -251,7 +251,7 @@ qt.widget_table[#qt.widget_table + 1] = new_qt_widget --create module -if dt.gui.current_view().name == "lighttable" then +if dt.gui.current_view().id == "lighttable" then install_module() else if not qt.event_registered then diff --git a/contrib/rename-tags.lua b/contrib/rename-tags.lua index f385a7a..5ccba2b 100644 --- a/contrib/rename-tags.lua +++ b/contrib/rename-tags.lua @@ -131,7 +131,7 @@ rt.rename_widget = darktable.new_widget ("box") { darktable.new_widget("button") { label = "Go", clicked_callback = rename_tags } } -if darktable.gui.current_view().name == "lighttable" then +if darktable.gui.current_view().id == "lighttable" then install_module() else if not rt.event_registered then diff --git a/contrib/transfer_hierarchy.lua b/contrib/transfer_hierarchy.lua index 70bb598..727595c 100755 --- a/contrib/transfer_hierarchy.lua +++ b/contrib/transfer_hierarchy.lua @@ -361,7 +361,7 @@ darktable.preferences.register( -- Preferences: END -if darktable.gui.current_view().name == "lighttable" then +if darktable.gui.current_view().id == "lighttable" then install_module() else if not th.event_registered then diff --git a/examples/moduleExample.lua b/examples/moduleExample.lua index 12de682..76a992e 100644 --- a/examples/moduleExample.lua +++ b/examples/moduleExample.lua @@ -141,7 +141,7 @@ table.insert(mE.widgets, slider) -- ... and tell dt about it all -if dt.gui.current_view().name == "lighttable" then -- make sure we are in lighttable view +if dt.gui.current_view().id == "lighttable" then -- make sure we are in lighttable view install_module() -- register the lib else if not mE.event_registered then -- if we are not in lighttable view then register an event to signal when we might be diff --git a/official/enfuse.lua b/official/enfuse.lua index 4213b48..a2ac3ec 100644 --- a/official/enfuse.lua +++ b/official/enfuse.lua @@ -263,7 +263,7 @@ if enfuse_installed then -- ... and tell dt about it all - if dt.gui.current_view().name == "lighttable" then + if dt.gui.current_view().id == "lighttable" then install_module() else if not enf.event_registered then diff --git a/official/image_path_in_ui.lua b/official/image_path_in_ui.lua index 60bcce6..7459c52 100644 --- a/official/image_path_in_ui.lua +++ b/official/image_path_in_ui.lua @@ -68,7 +68,7 @@ end main_label.reset_callback = reset_widget -if dt.gui.current_view().name == "lighttable" then +if dt.gui.current_view().id == "lighttable" then install_module() else if not ipiu.event_registered then diff --git a/tools/executable_manager.lua b/tools/executable_manager.lua index 2bbe392..db65dfa 100644 --- a/tools/executable_manager.lua +++ b/tools/executable_manager.lua @@ -209,7 +209,7 @@ update_combobox_choices(exec_man.selector, exec_table, 1) -- register the lib -if dt.gui.current_view().name == "lighttable" then +if dt.gui.current_view().id == "lighttable" then install_module() else if not exec_man.event_registered then diff --git a/tools/script_manager.lua b/tools/script_manager.lua index 9592a7e..b0532e7 100644 --- a/tools/script_manager.lua +++ b/tools/script_manager.lua @@ -764,7 +764,7 @@ sm.main_box = dt.new_widget("box"){ -- D A R K T A B L E I N T E G R A T I O N -- - - - - - - - - - - - - - - - - - - - - - - - -if dt.gui.current_view().name == "lighttable" then +if dt.gui.current_view().id == "lighttable" then install_module() else if not sm.event_registered then From a0a8a61d56c6cd35ccc4cbee2ab280ff3ac1666a Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sun, 16 Aug 2020 15:52:57 -0400 Subject: [PATCH 59/70] Enabled latest dev changes in lua API so that script_manager responds better to panel resizing --- tools/script_manager.lua | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tools/script_manager.lua b/tools/script_manager.lua index b0532e7..5c121a7 100644 --- a/tools/script_manager.lua +++ b/tools/script_manager.lua @@ -65,6 +65,7 @@ local CS = dt.configuration.running_os == "windows" and "&" or ";" local LUA_DIR = dt.configuration.config_dir .. PS .. "lua" local LUA_SCRIPT_REPO = "https://github.com/darktable-org/lua-scripts.git" +local CURR_API_VERSION = dt.configuration.api_version_string dt.print_log("LUA_DIR is " .. LUA_DIR) @@ -284,7 +285,7 @@ local function deactivate(script, scriptname) end local function create_enable_disable_button(btext, sname, req) - return dt.new_widget("button") + button = dt.new_widget("button") { label = btext .. sname, tooltip = get_script_doc(req), @@ -310,6 +311,10 @@ local function create_enable_disable_button(btext, sname, req) end end } + if CURR_API_VERSION >= "6.0.1" then + button.ellipsize = "middle" + end + return button end local function load_script_stack() @@ -733,6 +738,12 @@ sm.main_stack = dt.new_widget("stack"){ table.unpack(sm.main_stack_items), } +if CURR_API_VERSION >= "6.0.1" then + sm.main_stack.h_size_fixed = false + sm.main_stack.v_size_fixed = false +end + + -- make a combobox for the selector sm.main_menu = dt.new_widget("combobox"){ From 650325257ba9b9b3ba9fc69b842c92dd1bba77ad Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sun, 16 Aug 2020 15:57:41 -0400 Subject: [PATCH 60/70] made button a local variable --- tools/script_manager.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/script_manager.lua b/tools/script_manager.lua index 5c121a7..ecb4999 100644 --- a/tools/script_manager.lua +++ b/tools/script_manager.lua @@ -285,7 +285,7 @@ local function deactivate(script, scriptname) end local function create_enable_disable_button(btext, sname, req) - button = dt.new_widget("button") + local button = dt.new_widget("button") { label = btext .. sname, tooltip = get_script_doc(req), From f76fa01240348883f83088ad5c117b70487178b6 Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Tue, 18 Aug 2020 12:08:23 -0400 Subject: [PATCH 61/70] Updated install instructions adding flatpak information and updating preferred way to enable and disable scripts. --- README.md | 44 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 438f508..1179406 100644 --- a/README.md +++ b/README.md @@ -126,7 +126,17 @@ Ensure git is installed on your system. If it isn't, use the package manager to cd ~/snap/darktable/current git clone https://github.com/darktable-org/lua-scripts.git lua -### flatpak and appimage packages +### flatpak packages + +Flatpak packages now use the internal lua interpreter. + + +Ensure git is installed on your system. If it isn't, use the package manager to install it. Then open a terminal and: + + cd ~/.var/app/org.darktable.Darktable/config/darktable + git clone https://github.com/darktable-org/lua-scripts.git lua + +### appimage packages These packages run in their own environment and don't have access to a lua interpreter, therefore the scripts can't run. The packagers could enable the internal interpreter, or allow the package to link the interpreter from the operating system, or bundle a copy of lua with the package. If you use one of these packages and wish to use the lua scripts, please contact the package maintainer and suggest the above fixes. @@ -150,24 +160,34 @@ If you don't have %LOCALAPPDATA%\darktable you have to start dartable at least o When darktable starts it looks for a file name `~/.config/darktable/luarc` (`%LOCALAPPDATA%\darktable\luarc` for windows) and reads it to see which scripts to include. The file is a plain text file with entries of the form `require "/"` where directory is the directory containing the scripts, from the above list, and name is the name from the above list. To include GIMP the line would be `require "contrib/gimp"`. +The recommended way to enable and disable specific scripts is using the script manager module. To use script manager do the following: + +### Linux or MacOS + + echo 'require "tools/script_manager"' > ~/.config/darktable/luarc + +### Windows + + echo "require 'tools/script_manager'" > %LOCALAPPDATA%\darktable\luarc + +### Snap + + echo 'require "tools/script_manager"' > ~/snap/darktable/current/luarc + +### Flatpak + + echo require "tools/script_manager"' > ~/.var/app/org.darktable.Darktable/config/darktable/luarc + You can also create or add lines to the luarc file from the command line: `echo 'require "contrib/gimp"' > ~/.config/darktable/luarc` to create the file with a gimp entry\ or `echo 'require "contrib/hugin"' >> ~/.config/darktable/luarc` to add an entry for hugin. -Alteratively you can use script_manager.lua as your luarc file. script_manager.lua provides a point and click interface for managing the lua scripts. To use it: - - ln -s $HOME/.config/darktable/lua/tools/script_manager.lua $HOME/.config/darktable/luarc - On windows from a command prompt: `echo require "contrib/gimp" > %LOCALAPPDATA%\darktable\luarc` to create the file with a gimp entry\ or `echo require "contrib/hugin" >> %LOCALAPPDATA%\darktable\luarc` to add an entry for hugin. -Alteratively you can use script_manager.lua as your luarc file. script_manager.lua provides a point and click interface for managing the lua scripts. To use it: - - copy %LOCALAPPDATA%\darktable\lua\tools\script_manager.lua %LOCALAPPDATA%\darktable\luarc - ## Disabling To disable a script open the luarc file in your text editor and insert `--` at the start of the line containing the script you wish to disable, then save the file. @@ -181,6 +201,12 @@ To update the script repository, open a terminal or command prompt and do the fo cd ~/snap/darktable/current/lua git pull + +### Flatpak + + cd ~/.var/app/org.darktable.Darktable/config/darktable/lua + git pull + ### Linux and MacOS cd ~/.config/darktable/lua/ From d9c284b54d7e5a89af4111fbd4dadb81ceb84010 Mon Sep 17 00:00:00 2001 From: supertobi Date: Sun, 6 Sep 2020 20:01:34 +0200 Subject: [PATCH 62/70] Update README.md README - suggested update #286 --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1179406..8ca96db 100644 --- a/README.md +++ b/README.md @@ -237,10 +237,14 @@ Running darktable with Lua debugging enabled provides more information about wha Open a terminal and start darktable with the command `snap run darktable -d lua`. This provides debugging information to give you insight into what is happening. -### Linux and MacOS +### Linux Open a terminal and start darktable with the command `darktable -d lua`. This provides debugging information to give you insight into what is happening. +### MacOS + +Open a terminal and start darktable with the command `/Applications/darktable.app/Contents/MacOS/darktable -d lua`. This provides debugging information to give you insight into what is happening. + ### Windows Open a command prompt. Start darktable with the command "C:\Program Files\darktable\bin\darktable" -d lua > log.txt. This provides debugging information to give you insight into what is happening. From 394cbdb4544a4d1d40f040eef0d987b9bb5beb7f Mon Sep 17 00:00:00 2001 From: homer3018 <36423314+homer3018@users.noreply.github.com> Date: Fri, 11 Sep 2020 00:05:22 +0200 Subject: [PATCH 63/70] Typo --- contrib/enfuseAdvanced.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/enfuseAdvanced.lua b/contrib/enfuseAdvanced.lua index 932a6cd..016bdce 100644 --- a/contrib/enfuseAdvanced.lua +++ b/contrib/enfuseAdvanced.lua @@ -939,7 +939,7 @@ GUI.Presets.current_preset = dt.new_widget('combobox'){ end } GUI.Presets.load = dt.new_widget('button'){ - label = _('laod fusion preset'), + label = _('load fusion preset'), tooltip = _('load current fusion parameters from selected preset'), clicked_callback = function() LoadFromPreference(GUI.Presets.current_preset.value) end } From 85c218b350065c69cb3cb9f652061426545d3f73 Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Mon, 14 Sep 2020 20:47:29 -0400 Subject: [PATCH 64/70] [contrib/enfuseAdvanced] fixed translations in for loops by changing the unused variable _ to x so that the translation function _() doesn't get replaced with the value of _. --- contrib/enfuseAdvanced.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/enfuseAdvanced.lua b/contrib/enfuseAdvanced.lua index 932a6cd..e5a3733 100644 --- a/contrib/enfuseAdvanced.lua +++ b/contrib/enfuseAdvanced.lua @@ -240,7 +240,7 @@ end local function ExeUpdate(prog_tbl) --updates executable paths and verifies them dt.preferences.write(mod, 'bin_exists', 'bool', true) - for _,prog in pairs(prog_tbl) do + for x,prog in pairs(prog_tbl) do dt.preferences.write('executable_paths', prog.name, 'string', GUI.exes[prog.name].value) prog.bin = df.check_if_bin_exists(prog.name) if not prog.bin then @@ -455,7 +455,7 @@ local function main(storage, image_table, extra_data) local image_num = 0 local job = dt.gui.create_job('blending '..#variants..' image(s)', true) --create a GUI job bar to display enfuse progress UpdateActivePreference() --load current GUI values into active preference (only applies to elements without a clicked/changed callback) - for _,prefix in pairs(variants) do --for each image to be created load in the preference values, build arguments string, output image, and run command then execute. + for x,prefix in pairs(variants) do --for each image to be created load in the preference values, build arguments string, output image, and run command then execute. job.percent = image_num /(#variants) image_num = image_num+1 ENF.images_string, final_image, source_raw = UpdateENFargs(image_table, prefix) From 8808306a5f6165a210849df977784e3fe2e6eedd Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Wed, 16 Sep 2020 00:05:53 -0400 Subject: [PATCH 65/70] [contrib/enfusedAdvanced.lua] _ was declared globally in a subroutine, thus negating translation once the subroutine was called. --- contrib/enfuseAdvanced.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/enfuseAdvanced.lua b/contrib/enfuseAdvanced.lua index bf6ef3e..a40be53 100644 --- a/contrib/enfuseAdvanced.lua +++ b/contrib/enfuseAdvanced.lua @@ -311,7 +311,7 @@ local function UpdateENFargs(image_table, prefix) --updates the Enfuse arguments local largest_id = 0 local first_raw = {} for raw, temp_image in pairs(image_table) do - _, source_name, source_id = GetFileName(raw.filename) + local _, source_name, source_id = GetFileName(raw.filename) source_id = tonumber(source_id) if source_id < smallest_id then smallest_id = source_id From b5b49245fa25090fa4e6930dffc4f624d291d447 Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Tue, 17 Nov 2020 18:53:54 -0500 Subject: [PATCH 66/70] Needlessly creating the executable path preference for the ufraw-batch executable on linux caused the value to be saved as the startup directory, which in turn caused a crash when trying to extract the embedded jpg. --- examples/multi_os.lua | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/examples/multi_os.lua b/examples/multi_os.lua index 96b60c2..04acf56 100644 --- a/examples/multi_os.lua +++ b/examples/multi_os.lua @@ -204,24 +204,26 @@ end to see if the executable is there. ]] -local executable = "ufraw-batch" -local ufraw_batch_path_widget = dt.new_widget("file_chooser_button"){ - title = _("Select ufraw-batch[.exe] executable"), - value = df.get_executable_path_preference(executable), - is_directory = false, - changed_callback = function(self) - if df.check_if_bin_exists(self.value) then - df.set_executable_path_preference(executable, self.value) +if dt.configuration.running_os ~= "linux" then + local executable = "ufraw-batch" + local ufraw_batch_path_widget = dt.new_widget("file_chooser_button"){ + title = _("Select ufraw-batch[.exe] executable"), + value = df.get_executable_path_preference(executable), + is_directory = false, + changed_callback = function(self) + if df.check_if_bin_exists(self.value) then + df.set_executable_path_preference(executable, self.value) + end end - end -} -dt.preferences.register("executable_paths", "ufraw-batch", -- name - "file", -- type - _('multi_os: ufraw-batch location'), -- label - _('Installed location of ufraw-batch. Requires restart to take effect.'), -- tooltip - "ufraw-batch", -- default - ufraw_batch_path_widget -) + } + dt.preferences.register("executable_paths", "ufraw-batch", -- name + "file", -- type + _('multi_os: ufraw-batch location'), -- label + _('Installed location of ufraw-batch. Requires restart to take effect.'), -- tooltip + "ufraw-batch", -- default + ufraw_batch_path_widget + ) +end --[[ Add a button to the selected images module in lighttable From 536b9726b22940c3e06f7f6df1db61eede7f8446 Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Thu, 19 Nov 2020 00:35:17 -0500 Subject: [PATCH 67/70] [enfuseAdvanced] Added check for comma decimal separator. Replace with period if found. --- contrib/enfuseAdvanced.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contrib/enfuseAdvanced.lua b/contrib/enfuseAdvanced.lua index a40be53..8e822a1 100644 --- a/contrib/enfuseAdvanced.lua +++ b/contrib/enfuseAdvanced.lua @@ -470,6 +470,8 @@ local function main(storage, image_table, extra_data) --copy exif data from original file run_cmd = EXF.bin..' -TagsFromFile '..df.sanitize_filename(source_raw.path..os_path_seperator..source_raw.filename)..' -exif:all --subifd:all -overwrite_original '..df.sanitize_filename(final_image) + -- replace comma decimal separator with period + run_cmd = string.gsub(run_cmd, '(%d),(%d)', "%1.%2") resp = dsys.external_command(run_cmd) From 4ab20d808849df4d8ef87ba12aa6a245ae785dcf Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sat, 21 Nov 2020 18:33:26 -0500 Subject: [PATCH 68/70] Removed official/yield.lua since it was only required for lua API 3.x and less (darktable 2.0 and before). Removed require from scripts that had included it. --- contrib/geoJSON_export.lua | 1 - contrib/geoToolbox.lua | 1 - contrib/hugin.lua | 3 +-- contrib/pdf_slideshow.lua | 1 - contrib/slideshowMusic.lua | 1 - lib/dtutils/system.lua | 1 - official/generate_image_txt.lua | 1 - official/selection_to_pdf.lua | 1 - official/yield.lua | 42 --------------------------------- tools/script_manager.lua | 2 +- 10 files changed, 2 insertions(+), 52 deletions(-) delete mode 100644 official/yield.lua diff --git a/contrib/geoJSON_export.lua b/contrib/geoJSON_export.lua index 4834bb0..4815e07 100644 --- a/contrib/geoJSON_export.lua +++ b/contrib/geoJSON_export.lua @@ -35,7 +35,6 @@ USAGE local dt = require "darktable" local du = require "lib/dtutils" local df = require "lib/dtutils.file" -require "official/yield" local gettext = dt.gettext du.check_min_api_version("3.0.0", "geoJSON_export") diff --git a/contrib/geoToolbox.lua b/contrib/geoToolbox.lua index 1bce5f3..86dd533 100644 --- a/contrib/geoToolbox.lua +++ b/contrib/geoToolbox.lua @@ -28,7 +28,6 @@ require "geoToolbox" local dt = require "darktable" local du = require "lib/dtutils" local df = require "lib/dtutils.file" -require "official/yield" local gettext = dt.gettext du.check_min_api_version("3.0.0", "geoToolbox") diff --git a/contrib/hugin.lua b/contrib/hugin.lua index 83ec3be..1de8f04 100644 --- a/contrib/hugin.lua +++ b/contrib/hugin.lua @@ -40,7 +40,6 @@ local du = require "lib/dtutils" local df = require "lib/dtutils.file" local log = require "lib/dtutils.log" local dtsys = require "lib/dtutils.system" -require "official/yield" local gettext = dt.gettext local namespace = 'module_hugin' @@ -227,4 +226,4 @@ dt.register_storage(namespace, _("hugin panorama"), show_status, create_panorama -- --- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua \ No newline at end of file +-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua diff --git a/contrib/pdf_slideshow.lua b/contrib/pdf_slideshow.lua index f01b014..10e84db 100644 --- a/contrib/pdf_slideshow.lua +++ b/contrib/pdf_slideshow.lua @@ -41,7 +41,6 @@ format (all fields can be the empty string): local dt = require "darktable" local du = require "lib/dtutils" local df = require "lib/dtutils.file" -require "official/yield" local gettext = dt.gettext diff --git a/contrib/slideshowMusic.lua b/contrib/slideshowMusic.lua index 90d6bc3..921c6ff 100644 --- a/contrib/slideshowMusic.lua +++ b/contrib/slideshowMusic.lua @@ -27,7 +27,6 @@ USAGE local dt = require "darktable" local du = require "lib/dtutils" local df = require "lib/dtutils.file" -require "official/yield" local gettext = dt.gettext du.check_min_api_version("2.0.2", "slideshowMusic") diff --git a/lib/dtutils/system.lua b/lib/dtutils/system.lua index f202d6d..f41f821 100644 --- a/lib/dtutils/system.lua +++ b/lib/dtutils/system.lua @@ -1,7 +1,6 @@ local dtutils_system = {} local dt = require "darktable" -require "official/yield" -- necessary for dt.control.execute() dtutils_system.libdoc = { Name = [[dtutils.system]], diff --git a/official/generate_image_txt.lua b/official/generate_image_txt.lua index a214a2a..0d34330 100644 --- a/official/generate_image_txt.lua +++ b/official/generate_image_txt.lua @@ -37,7 +37,6 @@ USAGE local dt = require "darktable" local du = require "lib/dtutils" require "darktable.debug" -require "official/yield" du.check_min_api_version("2.1.0", "generate_image_txt") diff --git a/official/selection_to_pdf.lua b/official/selection_to_pdf.lua index f6fbfe8..9d548da 100644 --- a/official/selection_to_pdf.lua +++ b/official/selection_to_pdf.lua @@ -35,7 +35,6 @@ Plugin allows you to choose how many thumbnails you need per row ]] local dt = require "darktable" local du = require "lib/dtutils" -require "official/yield" du.check_min_api_version("2.0.0", "selection_to_pdf") diff --git a/official/yield.lua b/official/yield.lua deleted file mode 100644 index 3e5cb9b..0000000 --- a/official/yield.lua +++ /dev/null @@ -1,42 +0,0 @@ ---[[ - This file is part of darktable, - Copyright 2016 by Tobias Jakobs. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -]] ---[[ -darktable yield compatibility script - -USAGE -* require this script from your main Lua file in the first line - -]] -local dt = require "darktable" -local yield_orig = coroutine.yield - -if (dt.configuration.api_version_major < 4) then - dt.control = {} - dt.control.execute = function(command) - yield_orig("RUN_COMMAND", command) - end - dt.control.read = function(command) - yield_orig("FILE_READABLE", command) - end - dt.control.sleep = function(command) - yield_orig("WAIT_MS", command) - end -end - --- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua --- kate: hl Lua; diff --git a/tools/script_manager.lua b/tools/script_manager.lua index ecb4999..684d488 100644 --- a/tools/script_manager.lua +++ b/tools/script_manager.lua @@ -226,7 +226,7 @@ local function scan_scripts() if not string.match(script_file, "yield") then -- special case, because everything needs this add_script_data(script_file) else - prequire(script_file) -- load yield.lua + -- prequire(script_file) -- load yield.lua end end end From 43315bb9ccb2e662fcb0d6bc7692d8fca450240f Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Wed, 25 Nov 2020 19:39:49 -0500 Subject: [PATCH 69/70] [enfuseAdvanced] added a sanitize_decimals function to sanitize the command lines. --- contrib/enfuseAdvanced.lua | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/contrib/enfuseAdvanced.lua b/contrib/enfuseAdvanced.lua index 8e822a1..a9f6ea0 100644 --- a/contrib/enfuseAdvanced.lua +++ b/contrib/enfuseAdvanced.lua @@ -180,6 +180,11 @@ for _,i in pairs(dt.styles) do end -- FUNCTION -- + +local function sanitize_decimals(cmd) -- make sure decimal separator is a '.' + return string.gsub(cmd, '(%d),(%d)', "%1.%2") +end + local function InRange(test, low, high) -- tests if test value is within range of low and high (inclusive) if test >= low and test <= high then return true @@ -435,6 +440,9 @@ local function main(storage, image_table, extra_data) local job = dt.gui.create_job('aligning images') image_table, images_to_remove, AIS.images_string = UpdateAISargs(image_table, images_to_remove) local run_cmd = BuildExecuteCmd(AIS) + dt.print_log("AIS run command is " .. run_cmd) + run_cmd = sanitize_decimals(run_cmd) + dt.print_log("AIS decimaal sanitized command is " .. run_cmd) local resp = dsys.external_command(run_cmd) job.valid = false if resp ~= 0 then @@ -460,6 +468,9 @@ local function main(storage, image_table, extra_data) image_num = image_num+1 ENF.images_string, final_image, source_raw = UpdateENFargs(image_table, prefix) local run_cmd = BuildExecuteCmd(ENF) + dt.print_log("ENF run command is " .. run_cmd) + run_cmd = sanitize_decimals(run_cmd) + dt.print_log("ENF decimaal sanitized command is " .. run_cmd) local resp = dsys.external_command(run_cmd) if resp ~= 0 then remove_temp_files(images_to_remove) @@ -471,12 +482,15 @@ local function main(storage, image_table, extra_data) --copy exif data from original file run_cmd = EXF.bin..' -TagsFromFile '..df.sanitize_filename(source_raw.path..os_path_seperator..source_raw.filename)..' -exif:all --subifd:all -overwrite_original '..df.sanitize_filename(final_image) -- replace comma decimal separator with period - run_cmd = string.gsub(run_cmd, '(%d),(%d)', "%1.%2") + dt.print_log("EXF run command is " .. run_cmd) + run_cmd = sanitize_decimals(run_cmd) + dt.print_log("EXF decimaal sanitized command is " .. run_cmd) resp = dsys.external_command(run_cmd) if GUI.Target.auto_import.value then --import image into dt if specified local imported = dt.database.import(final_image) + dt.print_log("image imported") if GUI.Target.apply_style.selected > 1 then --apply specified style to imported image local set_style = styles[GUI.Target.apply_style.selected - 1] dt.styles.apply(set_style , imported) From b26ec58f9f516e932f3350402282fea54a19ceed Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Sun, 13 Dec 2020 22:00:39 -0300 Subject: [PATCH 70/70] Sanitize filename in fujifilm_ratings.lua to handle spaces. --- contrib/fujifilm_ratings.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/fujifilm_ratings.lua b/contrib/fujifilm_ratings.lua index 6cf92c9..29ec406 100644 --- a/contrib/fujifilm_ratings.lua +++ b/contrib/fujifilm_ratings.lua @@ -41,7 +41,7 @@ local function detect_rating(event, image) dt.print_error(_("exiftool not found")) return end - local RAF_filename = tostring(image) + local RAF_filename = df.sanitize_filename(tostring(image)) local JPEG_filename = string.gsub(RAF_filename, "%.RAF$", ".JPG") local command = "exiftool -Rating " .. JPEG_filename dt.print_error(command)