Compare commits
70 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6548a12bf1 | ||
|
|
becfa5350b | ||
|
|
ebd2cd7bf7 | ||
|
|
52b4508e08 | ||
|
|
19fdbc14c5 | ||
|
|
63d5aad465 | ||
|
|
9d6ff85893 | ||
|
|
125af63bda | ||
|
|
65c22e475a | ||
|
|
e78e718769 | ||
|
|
40949b3855 | ||
|
|
06ab263e74 | ||
|
|
bccc86c70a | ||
|
|
12640c7d29 | ||
|
|
febc3b1659 | ||
|
|
9fdd69556c | ||
|
|
4735be470a | ||
|
|
3b8e802e42 | ||
|
|
f54d449316 | ||
|
|
1b0fe4d7b9 | ||
|
|
cf1dca9e1a | ||
|
|
45d54ef4e8 | ||
|
|
8bfab0325b | ||
|
|
4b99d00ab5 | ||
|
|
a5961eb066 | ||
|
|
95e19ef163 | ||
|
|
d4eb6577bf | ||
|
|
294b693905 | ||
|
|
23835edc1f | ||
|
|
5f29211f79 | ||
|
|
025f4299ea | ||
|
|
dc50d40886 | ||
|
|
867c49b1b9 | ||
|
|
13f02c95ea | ||
|
|
d55dae73f0 | ||
|
|
34b9831472 | ||
|
|
014a0fc1c9 | ||
|
|
bf17dccd69 | ||
|
|
890168d0d0 | ||
|
|
191aecacdf | ||
|
|
44ec01b136 | ||
|
|
a177da2040 | ||
|
|
c899040688 | ||
|
|
e8af665b3c | ||
|
|
875734d455 | ||
|
|
14d5a79db2 | ||
|
|
e1b2715ee9 | ||
|
|
7ecd5ca55d | ||
|
|
931e7a4d37 | ||
|
|
1792410efe | ||
|
|
8cbd9224f1 | ||
|
|
24b552d619 | ||
|
|
68ae9326bf | ||
|
|
b4626f2787 | ||
|
|
2fc8ed78e4 | ||
|
|
236b25a235 | ||
|
|
a4f6af73ec | ||
|
|
fad74d6438 | ||
|
|
3e2d4c956d | ||
|
|
cd1d623390 | ||
|
|
9e0374d597 | ||
|
|
e47672b495 | ||
|
|
1905be8577 | ||
|
|
4726821e7d | ||
|
|
7ac37ddc1a | ||
|
|
3889742e06 | ||
|
|
6bf3706455 | ||
|
|
8e412c3eb3 | ||
|
|
3070ca0bc4 | ||
|
|
28ae2ea501 |
@@ -66,6 +66,7 @@ change_group_leader|Yes|LMW|Change which image leads group
|
||||
[rename_images](https://darktable-org.github.io/luadocs/lua.scripts.manual/scripts/contrib/rename_images)|Yes|LMW|Rename single or multiple images
|
||||
[rename-tags](https://darktable-org.github.io/luadocs/lua.scripts.manual/scripts/contrib/rename-tags)|Yes|LMW|Change a tag name
|
||||
[RL_out_sharp](https://darktable-org.github.io/luadocs/lua.scripts.manual/scripts/contrib/rl_out_sharp)|No|LW|Output sharpening using GMic (Richardson-Lucy algorithm)
|
||||
[select_non_existing](https://darktable-org.github.io/luadocs/lua.scripts.manual/scripts/contrib/select_non_existing)|Yes|LMW|Enable selection of non-existing images in the the currently worked on images
|
||||
[select_untagged](https://darktable-org.github.io/luadocs/lua.scripts.manual/scripts/contrib/select_untagged)|Yes|LMW|Enable selection of untagged images
|
||||
[slideshowMusic](https://darktable-org.github.io/luadocs/lua.scripts.manual/scripts/contrib/slideshowMusic)|No|L|Play music during a slideshow
|
||||
[transfer_hierarchy](https://darktable-org.github.io/luadocs/lua.scripts.manual/scripts/contrib/transfer_hierarchy)|Yes|LMW|Image move/copy preserving directory hierarchy
|
||||
@@ -174,7 +175,7 @@ The recommended way to enable and disable specific scripts is using the script m
|
||||
|
||||
### Windows
|
||||
|
||||
echo "require 'tools/script_manager'" > %LOCALAPPDATA%\darktable\luarc
|
||||
echo require "tools/script_manager" > %LOCALAPPDATA%\darktable\luarc
|
||||
|
||||
### Snap
|
||||
|
||||
@@ -182,7 +183,7 @@ The recommended way to enable and disable specific scripts is using the script m
|
||||
|
||||
### Flatpak
|
||||
|
||||
echo require "tools/script_manager"' > ~/.var/app/org.darktable.Darktable/config/darktable/luarc
|
||||
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:
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
local gettext = dt.gettext
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
|
||||
@@ -63,6 +63,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
local function _(msgid)
|
||||
return gettext.dgettext("CollectHelper", msgid)
|
||||
|
||||
@@ -58,6 +58,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
|
||||
local mod = 'module_HDRMerge'
|
||||
|
||||
@@ -59,6 +59,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
-- Lua 5.3 no longer has "unpack" but "table.unpack"
|
||||
unpack = unpack or table.unpack
|
||||
|
||||
@@ -63,6 +63,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain("OpenInExplorer",dt.configuration.config_dir.."/lua/locale/")
|
||||
|
||||
@@ -72,6 +72,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
-- OS compatibility
|
||||
local PS = dt.configuration.running_os == "windows" and "\\" or "/"
|
||||
|
||||
@@ -49,6 +49,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
-- run command and retrieve stdout
|
||||
local function get_stdout(cmd)
|
||||
|
||||
@@ -49,6 +49,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain(MODULE, dt.configuration.config_dir.."/lua/locale/")
|
||||
|
||||
@@ -46,6 +46,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
local gettext = dt.gettext
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain("copy_attach_detach_tags",dt.configuration.config_dir.."/lua/locale/")
|
||||
|
||||
@@ -44,6 +44,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
local queue = {}
|
||||
local processed_files = {}
|
||||
|
||||
158
contrib/cycle_group_leader.lua
Normal file
158
contrib/cycle_group_leader.lua
Normal file
@@ -0,0 +1,158 @@
|
||||
--[[
|
||||
|
||||
cycle_group_leader.lua - change image grouip leader
|
||||
|
||||
Copyright (C) 2024 Bill Ferguson <wpferguson@gmail.com>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
]]
|
||||
--[[
|
||||
cycle_group_leader - change image grouip leader
|
||||
|
||||
cycle_group_leader changes the group leader to the next
|
||||
image in the group. If the end of the group is reached
|
||||
then the next image is wrapped around to the first image.
|
||||
|
||||
ADDITIONAL SOFTWARE NEEDED FOR THIS SCRIPT
|
||||
None
|
||||
|
||||
USAGE
|
||||
* enable with script_manager
|
||||
* assign a key to the shortcut
|
||||
|
||||
BUGS, COMMENTS, SUGGESTIONS
|
||||
Bill Ferguson <wpferguson@gmail.com>
|
||||
|
||||
CHANGES
|
||||
]]
|
||||
|
||||
local dt = require "darktable"
|
||||
local du = require "lib/dtutils"
|
||||
local df = require "lib/dtutils.file"
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- C O N S T A N T S
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
local MODULE = "cycle_group_leader"
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- A P I C H E C K
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
du.check_min_api_version("7.0.0", MODULE)
|
||||
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- S C R I P T M A N A G E R I N T E G R A T I O N
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
local script_data = {}
|
||||
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- I 1 8 N
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
local gettext = dt.gettext
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain(MODULE, dt.configuration.config_dir .. "/lua/locale/")
|
||||
|
||||
local function _(msgid)
|
||||
return gettext.dgettext(MODULE, msgid)
|
||||
end
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- F U N C T I O N S
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
local function toggle_global_toolbox_grouping()
|
||||
dt.gui.libs.global_toolbox.grouping = false
|
||||
dt.gui.libs.global_toolbox.grouping = true
|
||||
end
|
||||
|
||||
local function hinter_msg(msg)
|
||||
dt.print_hinter(msg)
|
||||
dt.control.sleep(1500)
|
||||
dt.print_hinter(" ")
|
||||
end
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- M A I N P R O G R A M
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
local function cycle_group_leader(image)
|
||||
local group_images = image:get_group_members()
|
||||
if #group_images < 2 then
|
||||
hinter_msg(_("No images to cycle to in group"))
|
||||
return
|
||||
else
|
||||
local position = nil
|
||||
for i, img in ipairs(group_images) do
|
||||
if image == img then
|
||||
position = i
|
||||
end
|
||||
end
|
||||
|
||||
if position == #group_images then
|
||||
position = 1
|
||||
else
|
||||
position = position + 1
|
||||
end
|
||||
|
||||
new_leader = group_images[position]
|
||||
new_leader:make_group_leader()
|
||||
dt.gui.selection({new_leader})
|
||||
|
||||
if dt.gui.libs.global_toolbox.grouping then
|
||||
-- toggle the grouping to make the new leader show
|
||||
toggle_global_toolbox_grouping()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- D A R K T A B L E I N T E G R A T I O N
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
local function destroy()
|
||||
-- put things to destroy (events, storages, etc) here
|
||||
dt.destroy_event(MODULE, "shortcut")
|
||||
end
|
||||
|
||||
script_data.destroy = destroy
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- E V E N T S
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
dt.register_event(MODULE, "shortcut",
|
||||
function(event, shortcut)
|
||||
-- ignore the film roll, it contains all the images, not just the imported
|
||||
local images = dt.gui.selection()
|
||||
if #images < 1 then
|
||||
dt.print(_("No image selected. Please select an image and try again"))
|
||||
else
|
||||
cycle_group_leader(images[1])
|
||||
end
|
||||
end,
|
||||
_("cycle group leader")
|
||||
)
|
||||
|
||||
return script_data
|
||||
314
contrib/dbmaint.lua
Normal file
314
contrib/dbmaint.lua
Normal file
@@ -0,0 +1,314 @@
|
||||
--[[
|
||||
|
||||
dbmaint.lua - perform database maintenance
|
||||
|
||||
Copyright (C) 2024 Bill Ferguson <wpferguson.com>.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
]]
|
||||
--[[
|
||||
dbmaint - perform database maintenance
|
||||
|
||||
Perform database maintenance to clean up missing images and filmstrips.
|
||||
|
||||
ADDITIONAL SOFTWARE NEEDED FOR THIS SCRIPT
|
||||
None
|
||||
|
||||
USAGE
|
||||
* start dbmaint from script_manager
|
||||
* scan for missing film rolls or missing images
|
||||
* look at the results and choose to delete or not
|
||||
|
||||
BUGS, COMMENTS, SUGGESTIONS
|
||||
Bill Ferguson <wpferguson.com>
|
||||
|
||||
CHANGES
|
||||
]]
|
||||
|
||||
local dt = require "darktable"
|
||||
local du = require "lib/dtutils"
|
||||
local df = require "lib/dtutils.file"
|
||||
local log = require "lib/dtutils.log"
|
||||
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- C O N S T A N T S
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
local MODULE <const> = "dbmaint"
|
||||
local DEFAULT_LOG_LEVEL <const> = log.error
|
||||
local PS <const> = dt.configuration.running_os == "windows" and "\\" or "/"
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- A P I C H E C K
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
du.check_min_api_version("7.0.0", MODULE) -- choose the minimum version that contains the features you need
|
||||
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- I 1 8 N
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
local gettext = dt.gettext.gettext
|
||||
|
||||
dt.gettext.bindtextdomain(MODULE , dt.configuration.config_dir .. "/lua/locale/")
|
||||
|
||||
local function _(msgid)
|
||||
return gettext(MODULE, msgid)
|
||||
end
|
||||
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- S C R I P T M A N A G E R I N T E G R A T I O N
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
local script_data = {}
|
||||
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
script_data.metadata = {
|
||||
name = "dbmaint",
|
||||
purpose = _("perform database maintenance"),
|
||||
author = "Bill Ferguson <wpferguson.com>",
|
||||
help = "https://docs.darktable.org/lua/stable/lua.scripts.manual/scripts/contrib/dbmaint/"
|
||||
}
|
||||
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- L O G L E V E L
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
log.log_level(DEFAULT_LOG_LEVEL)
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- N A M E S P A C E
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
local dbmaint = {}
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- G L O B A L V A R I A B L E S
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
dbmaint.main_widget = nil
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- A L I A S E S
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
local namespace = dbmaint
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- F U N C T I O N S
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
local function scan_film_rolls()
|
||||
local missing_films = {}
|
||||
|
||||
for _, filmroll in ipairs(dt.films) do
|
||||
if not df.check_if_file_exists(filmroll.path) then
|
||||
table.insert(missing_films, filmroll)
|
||||
end
|
||||
end
|
||||
|
||||
return missing_films
|
||||
end
|
||||
|
||||
local function scan_images(film)
|
||||
local missing_images = {}
|
||||
|
||||
if film then
|
||||
for i = 1, #film do
|
||||
local image = film[i]
|
||||
log.log_msg(log.debug, "checking " .. image.filename)
|
||||
if not df.check_if_file_exists(image.path .. PS .. image.filename) then
|
||||
log.log_msg(log.info, image.filename .. " not found")
|
||||
table.insert(missing_images, image)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return missing_images
|
||||
end
|
||||
|
||||
local function remove_missing_film_rolls(list)
|
||||
for _, filmroll in ipairs(list) do
|
||||
filmroll:delete(true)
|
||||
end
|
||||
end
|
||||
|
||||
-- force the lighttable to reload
|
||||
|
||||
local function refresh_lighttable(film)
|
||||
local rules = dt.gui.libs.collect.filter()
|
||||
dt.gui.libs.collect.filter(rules)
|
||||
end
|
||||
|
||||
local function remove_missing_images(list)
|
||||
local film = list[1].film
|
||||
for _, image in ipairs(list) do
|
||||
image:delete()
|
||||
end
|
||||
refresh_lighttable(film)
|
||||
end
|
||||
|
||||
local function install_module()
|
||||
if not namespace.module_installed then
|
||||
dt.register_lib(
|
||||
MODULE, -- Module name
|
||||
_("DB maintenance"), -- Visible name
|
||||
true, -- expandable
|
||||
true, -- resetable
|
||||
{[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_LEFT_CENTER", 0}}, -- containers
|
||||
namespace.main_widget,
|
||||
nil,-- view_enter
|
||||
nil -- view_leave
|
||||
)
|
||||
namespace.module_installed = true
|
||||
end
|
||||
end
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- U S E R I N T E R F A C E
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
dbmaint.list_widget = dt.new_widget("text_view"){
|
||||
editable = false,
|
||||
reset_callback = function(this)
|
||||
this.text = ""
|
||||
end
|
||||
}
|
||||
|
||||
dbmaint.chooser = dt.new_widget("combobox"){
|
||||
label = "scan for",
|
||||
selected = 1,
|
||||
"film rolls", "images",
|
||||
reset_callback = function(this)
|
||||
this.selected = 1
|
||||
end
|
||||
}
|
||||
|
||||
dbmaint.scan_button = dt.new_widget("button"){
|
||||
label = "scan",
|
||||
tooltip = "click to scan for missing film rolls/files",
|
||||
clicked_callback = function(this)
|
||||
local found = nil
|
||||
local found_text = ""
|
||||
if dbmaint.chooser.value == "film rolls" then
|
||||
found = scan_film_rolls()
|
||||
if #found > 0 then
|
||||
for _, film in ipairs(found) do
|
||||
local dir_name = du.split(film.path, PS)
|
||||
found_text = found_text .. dir_name[#dir_name] .. "\n"
|
||||
end
|
||||
end
|
||||
else
|
||||
log.log_msg(log.debug, "checking path " .. dt.collection[1].path .. " for missing files")
|
||||
found = scan_images(dt.collection[1].film)
|
||||
if #found > 0 then
|
||||
for _, image in ipairs(found) do
|
||||
found_text = found_text .. image.filename .. "\n"
|
||||
end
|
||||
end
|
||||
end
|
||||
if #found > 0 then
|
||||
dbmaint.list_widget.text = found_text
|
||||
dbmaint.found = found
|
||||
dbmaint.remove_button.sensitive = true
|
||||
end
|
||||
end,
|
||||
reset_callback = function(this)
|
||||
dbmaint.found = nil
|
||||
end
|
||||
}
|
||||
|
||||
dbmaint.remove_button = dt.new_widget("button"){
|
||||
label = "remove",
|
||||
tooltip = "remove missing film rolls/images",
|
||||
sensitive = false,
|
||||
clicked_callback = function(this)
|
||||
if dbmaint.chooser.value == "film rolls" then
|
||||
remove_missing_film_rolls(dbmaint.found)
|
||||
else
|
||||
remove_missing_images(dbmaint.found)
|
||||
end
|
||||
dbmaint.found = nil
|
||||
dbmaint.list_widget.text = ""
|
||||
this.sensitive = false
|
||||
end,
|
||||
reset_callback = function(this)
|
||||
this.sensitive = false
|
||||
end
|
||||
}
|
||||
|
||||
dbmaint.main_widget = dt.new_widget("box"){
|
||||
orientation = "vertical",
|
||||
dt.new_widget("section_label"){label = "missing items"},
|
||||
dbmaint.list_widget,
|
||||
dt.new_widget("label"){label = ""},
|
||||
dbmaint.chooser,
|
||||
dt.new_widget("label"){label = ""},
|
||||
dbmaint.scan_button,
|
||||
dbmaint.remove_button
|
||||
}
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- D A R K T A B L E I N T E G R A T I O N
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
local function destroy()
|
||||
dt.gui.libs[MODULE].visible = false
|
||||
|
||||
if namespace.event_registered then
|
||||
dt.destroy_event(MODULE, "view-changed")
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
local function restart()
|
||||
dt.gui.libs[MODULE].visible = true
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
script_data.destroy = destroy
|
||||
script_data.restart = restart
|
||||
script_data.destroy_method = "hide"
|
||||
script_data.show = restart
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- E V E N T S
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
if dt.gui.current_view().id == "lighttable" then
|
||||
install_module()
|
||||
else
|
||||
if not namespace.event_registered then
|
||||
dt.register_event(MODULE, "view-changed",
|
||||
function(event, old_view, new_view)
|
||||
if new_view.name == "lighttable" and old_view.name == "darkroom" then
|
||||
install_module()
|
||||
end
|
||||
end
|
||||
)
|
||||
namespace.event_registered = true
|
||||
end
|
||||
end
|
||||
|
||||
return script_data
|
||||
@@ -74,6 +74,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
local gettext = dt.gettext
|
||||
|
||||
@@ -40,6 +40,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
local gettext = dt.gettext
|
||||
|
||||
|
||||
@@ -82,6 +82,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
-- OS compatibility
|
||||
local PS = dt.configuration.running_os == "windows" and "\\" or "/"
|
||||
|
||||
@@ -61,6 +61,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
-- namespace
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
local function detect_dynamic_range(event, image)
|
||||
if image.exif_maker ~= "FUJIFILM" then
|
||||
|
||||
@@ -37,6 +37,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
gettext.bindtextdomain("fujifilm_ratings", dt.configuration.config_dir.."/lua/locale/")
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain("geoJSON_export",dt.configuration.config_dir.."/lua/locale/")
|
||||
|
||||
@@ -39,6 +39,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain("geoToolbox",dt.configuration.config_dir.."/lua/locale/")
|
||||
|
||||
@@ -81,6 +81,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain("gimp",dt.configuration.config_dir.."/lua/locale/")
|
||||
|
||||
@@ -36,6 +36,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain("gpx_export",dt.configuration.config_dir.."/lua/locale/")
|
||||
@@ -203,5 +204,6 @@ end
|
||||
script_data.destroy = destroy
|
||||
script_data.restart = restart
|
||||
script_data.destroy_method = "hide"
|
||||
script_data.show = restart
|
||||
|
||||
return script_data
|
||||
|
||||
196
contrib/hif_group_leader.lua
Normal file
196
contrib/hif_group_leader.lua
Normal file
@@ -0,0 +1,196 @@
|
||||
--[[
|
||||
|
||||
hif_group_leader.lua - Make hif image group leader
|
||||
|
||||
Copyright (C) 2024 Bill Ferguson <wpferguson@gmail.com>.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
]]
|
||||
--[[
|
||||
hif_group_leader - Make hif image group leader
|
||||
|
||||
After a film roll is imported, check for RAW-JPG image groups
|
||||
and make the JPG image the group leader. This is on by default
|
||||
but can be disabled in preferences.
|
||||
|
||||
Shortcuts are included to filter existing collections or
|
||||
selections of images and make the hif the group leader.
|
||||
|
||||
ADDITIONAL SOFTWARE NEEDED FOR THIS SCRIPT
|
||||
None
|
||||
|
||||
USAGE
|
||||
Start script from script_manager
|
||||
Assign keys to the shortcuts
|
||||
|
||||
BUGS, COMMENTS, SUGGESTIONS
|
||||
Bill Ferguson <wpferguson@gmail.com>
|
||||
|
||||
CHANGES
|
||||
]]
|
||||
|
||||
local dt = require "darktable"
|
||||
local du = require "lib/dtutils"
|
||||
local df = require "lib/dtutils.file"
|
||||
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- C O N S T A N T S
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
local MODULE = "hif_group_leader"
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- A P I C H E C K
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
du.check_min_api_version("7.0.0", MODULE)
|
||||
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- S C R I P T M A N A G E R I N T E G R A T I O N
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
local script_data = {}
|
||||
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- I 1 8 N
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
local gettext = dt.gettext
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain(MODULE, dt.configuration.config_dir .. "/lua/locale/")
|
||||
|
||||
local function _(msgid)
|
||||
return gettext.dgettext(MODULE, msgid)
|
||||
end
|
||||
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- P R E F E R E N C E S
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
dt.preferences.register(MODULE, "on_import", "bool", _("make hif group leader on import"), _("automatically make the hif file the group leader when raw + hif are imported"), true)
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- N A M E S P A C E
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
local jgloi = {}
|
||||
jgloi.images = {}
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- F U N C T I O N S
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
local function toggle_global_toolbox_grouping()
|
||||
dt.gui.libs.global_toolbox.grouping = false
|
||||
dt.gui.libs.global_toolbox.grouping = true
|
||||
end
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- M A I N P R O G R A M
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
local function make_hif_group_leader(images)
|
||||
-- if the image is part of a group, make it the leader
|
||||
for _, image in ipairs(images) do
|
||||
if #image:get_group_members() > 1 then
|
||||
image:make_group_leader()
|
||||
end
|
||||
end
|
||||
if dt.gui.libs.global_toolbox.grouping then
|
||||
-- toggle the grouping to make the new leader show
|
||||
toggle_global_toolbox_grouping()
|
||||
end
|
||||
end
|
||||
|
||||
local function make_existing_hif_group_leader(images)
|
||||
for _, image in ipairs(images) do
|
||||
if string.lower(df.get_filetype(image.filename)) == "hif" then
|
||||
if #image:get_group_members() > 1 then
|
||||
image:make_group_leader()
|
||||
end
|
||||
end
|
||||
end
|
||||
if dt.gui.libs.global_toolbox.grouping then
|
||||
-- toggle the grouping to make the new leader show
|
||||
toggle_global_toolbox_grouping()
|
||||
end
|
||||
end
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- D A R K T A B L E I N T E G R A T I O N
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
local function destroy()
|
||||
if dt.preferences.read(MODULE, "on_import", "bool") then
|
||||
dt.destroy_event(MODULE, "post-import-film")
|
||||
dt.destroy_event(MODULE, "post-import-image")
|
||||
end
|
||||
dt.destroy_event(MODULE .. "_collect", "shortcut")
|
||||
dt.destroy_event(MODULE .. "_select", "shortcut")
|
||||
end
|
||||
|
||||
script_data.destroy = destroy
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- E V E N T S
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
if dt.preferences.read(MODULE, "on_import", "bool") then
|
||||
dt.register_event(MODULE, "post-import-film",
|
||||
function(event, film_roll)
|
||||
-- ignore the film roll, it contains all the images, not just the imported
|
||||
local images = jgloi.images
|
||||
if #images > 0 then
|
||||
jgloi.images = {}
|
||||
make_hif_group_leader(images)
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
dt.register_event(MODULE, "post-import-image",
|
||||
function(event, image)
|
||||
if string.lower(df.get_filetype(image.filename)) == "hif" then
|
||||
table.insert(jgloi.images, image)
|
||||
end
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
dt.register_event(MODULE .. "_collect", "shortcut",
|
||||
function(event, shortcut)
|
||||
-- ignore the film roll, it contains all the images, not just the imported
|
||||
local images = dt.collection
|
||||
make_existing_hif_group_leader(images)
|
||||
end,
|
||||
_("Make hif group leader for collection")
|
||||
)
|
||||
|
||||
dt.register_event(MODULE .. "_select", "shortcut",
|
||||
function(event, shortcut)
|
||||
local images = dt.gui.selection()
|
||||
make_existing_hif_group_leader(images)
|
||||
end,
|
||||
_("Make hif group leader for selection")
|
||||
)
|
||||
|
||||
return script_data
|
||||
@@ -63,6 +63,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain("hugin",dt.configuration.config_dir.."/lua/locale/")
|
||||
|
||||
@@ -80,6 +80,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain("image_stack",dt.configuration.config_dir.."/lua/locale/")
|
||||
|
||||
@@ -122,6 +122,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
|
||||
196
contrib/jpg_group_leader.lua
Normal file
196
contrib/jpg_group_leader.lua
Normal file
@@ -0,0 +1,196 @@
|
||||
--[[
|
||||
|
||||
jpg_group_leader.lua - Make jpg image group leader
|
||||
|
||||
Copyright (C) 2024 Bill Ferguson <wpferguson@gmail.com>.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
]]
|
||||
--[[
|
||||
jpg_group_leader - Make jpg image group leader
|
||||
|
||||
After a film roll is imported, check for RAW-JPG image groups
|
||||
and make the JPG image the group leader. This is on by default
|
||||
but can be disabled in preferences.
|
||||
|
||||
Shortcuts are included to filter existing collections or
|
||||
selections of images and make the jpg the group leader.
|
||||
|
||||
ADDITIONAL SOFTWARE NEEDED FOR THIS SCRIPT
|
||||
None
|
||||
|
||||
USAGE
|
||||
Start script from script_manager
|
||||
Assign keys to the shortcuts
|
||||
|
||||
BUGS, COMMENTS, SUGGESTIONS
|
||||
Bill Ferguson <wpferguson@gmail.com>
|
||||
|
||||
CHANGES
|
||||
]]
|
||||
|
||||
local dt = require "darktable"
|
||||
local du = require "lib/dtutils"
|
||||
local df = require "lib/dtutils.file"
|
||||
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- C O N S T A N T S
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
local MODULE = "jpg_group_leader"
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- A P I C H E C K
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
du.check_min_api_version("7.0.0", MODULE)
|
||||
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- S C R I P T M A N A G E R I N T E G R A T I O N
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
local script_data = {}
|
||||
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- I 1 8 N
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
local gettext = dt.gettext
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain(MODULE, dt.configuration.config_dir .. "/lua/locale/")
|
||||
|
||||
local function _(msgid)
|
||||
return gettext.dgettext(MODULE, msgid)
|
||||
end
|
||||
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- P R E F E R E N C E S
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
dt.preferences.register(MODULE, "on_import", "bool", _("make jpg group leader on import"), _("automatically make the jpg file the group leader when raw + jpg are imported"), true)
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- N A M E S P A C E
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
local jgloi = {}
|
||||
jgloi.images = {}
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- F U N C T I O N S
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
local function toggle_global_toolbox_grouping()
|
||||
dt.gui.libs.global_toolbox.grouping = false
|
||||
dt.gui.libs.global_toolbox.grouping = true
|
||||
end
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- M A I N P R O G R A M
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
local function make_jpg_group_leader(images)
|
||||
-- if the image is part of a group, make it the leader
|
||||
for _, image in ipairs(images) do
|
||||
if #image:get_group_members() > 1 then
|
||||
image:make_group_leader()
|
||||
end
|
||||
end
|
||||
if dt.gui.libs.global_toolbox.grouping then
|
||||
-- toggle the grouping to make the new leader show
|
||||
toggle_global_toolbox_grouping()
|
||||
end
|
||||
end
|
||||
|
||||
local function make_existing_jpg_group_leader(images)
|
||||
for _, image in ipairs(images) do
|
||||
if string.lower(df.get_filetype(image.filename)) == "jpg" then
|
||||
if #image:get_group_members() > 1 then
|
||||
image:make_group_leader()
|
||||
end
|
||||
end
|
||||
end
|
||||
if dt.gui.libs.global_toolbox.grouping then
|
||||
-- toggle the grouping to make the new leader show
|
||||
toggle_global_toolbox_grouping()
|
||||
end
|
||||
end
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- D A R K T A B L E I N T E G R A T I O N
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
local function destroy()
|
||||
if dt.preferences.read(MODULE, "on_import", "bool") then
|
||||
dt.destroy_event(MODULE, "post-import-film")
|
||||
dt.destroy_event(MODULE, "post-import-image")
|
||||
end
|
||||
dt.destroy_event(MODULE .. "_collect", "shortcut")
|
||||
dt.destroy_event(MODULE .. "_select", "shortcut")
|
||||
end
|
||||
|
||||
script_data.destroy = destroy
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- E V E N T S
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
if dt.preferences.read(MODULE, "on_import", "bool") then
|
||||
dt.register_event(MODULE, "post-import-film",
|
||||
function(event, film_roll)
|
||||
-- ignore the film roll, it contains all the images, not just the imported
|
||||
local images = jgloi.images
|
||||
if #images > 0 then
|
||||
jgloi.images = {}
|
||||
make_jpg_group_leader(images)
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
dt.register_event(MODULE, "post-import-image",
|
||||
function(event, image)
|
||||
if string.lower(df.get_filetype(image.filename)) == "jpg" then
|
||||
table.insert(jgloi.images, image)
|
||||
end
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
dt.register_event(MODULE .. "_collect", "shortcut",
|
||||
function(event, shortcut)
|
||||
-- ignore the film roll, it contains all the images, not just the imported
|
||||
local images = dt.collection
|
||||
make_existing_jpg_group_leader(images)
|
||||
end,
|
||||
_("Make jpg group leader for collection")
|
||||
)
|
||||
|
||||
dt.register_event(MODULE .. "_select", "shortcut",
|
||||
function(event, shortcut)
|
||||
local images = dt.gui.selection()
|
||||
make_existing_jpg_group_leader(images)
|
||||
end,
|
||||
_("Make jpg group leader for selection")
|
||||
)
|
||||
|
||||
return script_data
|
||||
@@ -52,6 +52,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain("kml_export",dt.configuration.config_dir.."/lua/locale/")
|
||||
|
||||
105
contrib/passport_guide_germany.lua
Normal file
105
contrib/passport_guide_germany.lua
Normal file
@@ -0,0 +1,105 @@
|
||||
--[[
|
||||
German passport photo cropping guide for darktable.
|
||||
Derived from the passport cropping guide by Kåre Hampf.
|
||||
|
||||
copyright (c) 2017 Kåre Hampf
|
||||
copyright (c) 2024 Christian Sültrop
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
]]
|
||||
|
||||
--[[
|
||||
PASSPORT CROPPING GUIDE
|
||||
Guides for cropping passport and ID card ("Personalausweis") photos based on the "Passbild-Schablone"
|
||||
from the German Federal Ministry of the Interior and Community.
|
||||
(https://www.bmi.bund.de/SharedDocs/downloads/DE/veroeffentlichungen/themen/moderne-verwaltung/ausweise/passbild-schablone-erwachsene.pdf?__blob=publicationFile&v=3)
|
||||
|
||||
INSTALLATION
|
||||
* copy this file in $CONFIGDIR/lua/ where CONFIGDIR is your darktable configuration directory
|
||||
* add the following line in the file $CONFIGDIR/luarc
|
||||
require "passport_guide_germany"
|
||||
* (optional) add the line:
|
||||
"plugins/darkroom/clipping/extra_aspect_ratios/passport 35x45mm=45:35"
|
||||
to $CONFIGDIR/darktablerc
|
||||
|
||||
USAGE
|
||||
* when using the cropping tool, select "Passport Photo Germany" as guide and if you added the line in yout rc
|
||||
select "passport 35x45mm" as aspect
|
||||
]]
|
||||
|
||||
local dt = require "darktable"
|
||||
local du = require "lib/dtutils"
|
||||
local gettext = dt.gettext
|
||||
|
||||
du.check_min_api_version("2.0.0", "passport_guide_germany")
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain("passport_guide_germany",dt.configuration.config_dir.."/lua/locale/")
|
||||
|
||||
local function _(msgid)
|
||||
return gettext.dgettext("passport_guide_germany", msgid)
|
||||
end
|
||||
|
||||
dt.guides.register_guide("Passport Photo Germany",
|
||||
-- draw
|
||||
function(cairo, x, y, width, height, zoom_scale)
|
||||
local _width, _height
|
||||
|
||||
-- get the max 35x45 rectangle
|
||||
local aspect_ratio = 45 / 35
|
||||
if width * aspect_ratio > height then
|
||||
_width = height / aspect_ratio
|
||||
_height = height
|
||||
else
|
||||
_width = width
|
||||
_height = width * aspect_ratio
|
||||
end
|
||||
|
||||
cairo:save()
|
||||
|
||||
cairo:translate(x + (width - _width) / 2, y + (height - _height) / 2)
|
||||
cairo:scale(_width / 35, _height / 45)
|
||||
|
||||
-- the outer rectangle
|
||||
cairo:rectangle( 0, 0, 35, 45)
|
||||
|
||||
-- Nose position: The nose tip must be between these lines
|
||||
cairo:draw_line(15.5, 45, 15.5, 13)
|
||||
cairo:draw_line(35-15.5, 45, 35-15.5, 13)
|
||||
|
||||
-- Face height
|
||||
-- optimum face height: The upper end of the head should be between these lines
|
||||
cairo:draw_line(0, 4, 35, 4)
|
||||
cairo:draw_line(0, 8, 35, 8)
|
||||
|
||||
-- tolerated face height: The upper end of the head must not be below this line
|
||||
cairo:draw_line(6, 13, 30, 13)
|
||||
|
||||
-- Eye area: The eyes must be between these lines
|
||||
cairo:draw_line(0, 13, 35, 13)
|
||||
cairo:draw_line(0, 23, 35, 23)
|
||||
|
||||
-- Cheek line: The cheek must lie on this line
|
||||
cairo:draw_line(9, 45-5, 27, 45-5)
|
||||
|
||||
cairo:restore()
|
||||
end,
|
||||
-- gui
|
||||
function()
|
||||
return dt.new_widget("label"){label = _("Passport Photo Germany"), halign = "start"}
|
||||
end
|
||||
)
|
||||
|
||||
-- kate: tab-indents: off; indent-width 2; replace-tabs on; remove-trailing-space on; hl Lua;
|
||||
-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua
|
||||
@@ -65,6 +65,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
dt.preferences.register
|
||||
("pdf_slideshow","open with","string",
|
||||
|
||||
@@ -51,6 +51,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
|
||||
local PS = dt.configuration.running_os == "windows" and "\\" or "/"
|
||||
|
||||
@@ -51,6 +51,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
local function apply_rating(rating)
|
||||
local images = dt.gui.action_images
|
||||
|
||||
@@ -43,6 +43,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
local rt = {}
|
||||
rt.module_installed = false
|
||||
|
||||
@@ -75,6 +75,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
77
contrib/select_non_existing.lua
Normal file
77
contrib/select_non_existing.lua
Normal file
@@ -0,0 +1,77 @@
|
||||
--[[
|
||||
This file is part of darktable,
|
||||
copyright (c) 2023 Dirk Dittmar
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
]]
|
||||
--[[
|
||||
Enable selection of non-existing images in the the currently worked on images, e.g. the ones selected by the collection module.
|
||||
]]
|
||||
|
||||
local dt = require "darktable"
|
||||
local du = require "lib/dtutils"
|
||||
local df = require "lib/dtutils.file"
|
||||
|
||||
-- module name
|
||||
local MODULE = "select_non_existing"
|
||||
|
||||
du.check_min_api_version("9.1.0", MODULE)
|
||||
|
||||
-- figure out the path separator
|
||||
local PS = dt.configuration.running_os == "windows" and "\\" or "/"
|
||||
|
||||
local gettext = dt.gettext
|
||||
gettext.bindtextdomain(MODULE, dt.configuration.config_dir..PS.."lua"..PS.."locale"..PS)
|
||||
|
||||
local function _(msgid)
|
||||
return gettext.dgettext(MODULE, msgid)
|
||||
end
|
||||
|
||||
local function stop_job(job)
|
||||
job.valid = false
|
||||
end
|
||||
|
||||
local function select_nonexisting_images(event, images)
|
||||
local selection = {}
|
||||
|
||||
local job = dt.gui.create_job(_("select non existing images"), true, stop_job)
|
||||
for key,image in ipairs(images) do
|
||||
if(job.valid) then
|
||||
job.percent = (key - 1)/#images
|
||||
local filepath = image.path..PS..image.filename
|
||||
local file_exists = df.test_file(filepath, "e")
|
||||
dt.print_log(filepath.." exists? => "..tostring(file_exists))
|
||||
if (not file_exists) then
|
||||
table.insert(selection, image)
|
||||
end
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
stop_job(job)
|
||||
|
||||
return selection
|
||||
end
|
||||
|
||||
local function destroy()
|
||||
dt.gui.libs.select.destroy_selection(MODULE)
|
||||
end
|
||||
|
||||
dt.gui.libs.select.register_selection(
|
||||
MODULE,
|
||||
_("select non existing"),
|
||||
select_nonexisting_images,
|
||||
_("select all non-existing images in the current images"))
|
||||
|
||||
local script_data = {}
|
||||
script_data.destroy = destroy
|
||||
return script_data
|
||||
@@ -31,6 +31,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain("select_untagged",dt.configuration.config_dir.."/lua/locale/")
|
||||
|
||||
@@ -38,6 +38,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain("slideshowMusic",dt.configuration.config_dir.."/lua/locale/")
|
||||
|
||||
@@ -87,6 +87,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
local MKDIR_COMMAND = darktable.configuration.running_os == "windows" and "mkdir " or "mkdir -p "
|
||||
local PATH_SEPARATOR = darktable.configuration.running_os == "windows" and "\\\\" or "/"
|
||||
|
||||
@@ -48,6 +48,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
local MODULE_NAME = "video_ffmpeg"
|
||||
|
||||
|
||||
105
examples/gui_action.lua
Normal file
105
examples/gui_action.lua
Normal file
@@ -0,0 +1,105 @@
|
||||
local dt = require "darktable"
|
||||
|
||||
local NaN = 0/0
|
||||
|
||||
local wg = {}
|
||||
|
||||
wg.action = dt.new_widget("entry"){
|
||||
text = "lib/filter/view",
|
||||
placeholder = "action path",
|
||||
tooltip = "enter the full path of an action, for example 'lib/filter/view'"
|
||||
}
|
||||
|
||||
wg.instance = dt.new_widget("combobox"){
|
||||
label = "instance",
|
||||
tooltip = "the instance of an image processing module to execute action on",
|
||||
"0", "+1", "-1", "+2", "-2", "+3", "-3", "+4", "-4", "+5", "-5", "+6", "-6", "+7", "-7", "+8", "-8", "+9", "-9"
|
||||
}
|
||||
|
||||
wg.element = dt.new_widget("entry"){
|
||||
text = "",
|
||||
placeholder = "action element",
|
||||
tooltip = "enter the element of an action, for example 'selection', or leave empty for default"
|
||||
}
|
||||
|
||||
wg.effect = dt.new_widget("entry"){
|
||||
text = "next",
|
||||
placeholder = "action effect",
|
||||
tooltip = "enter the effect of an action, for example 'next', or leave empty for default"
|
||||
}
|
||||
|
||||
wg.speed = dt.new_widget("entry"){
|
||||
text = "1",
|
||||
placeholder = "action speed",
|
||||
tooltip = "enter the speed to use in action execution, or leave empty to only read state"
|
||||
}
|
||||
|
||||
wg.check = dt.new_widget("check_button"){
|
||||
label = 'perform action',
|
||||
tooltip = 'perform action or only read return',
|
||||
clicked_callback = function()
|
||||
wg.speed.sensitive = wg.check.value
|
||||
end,
|
||||
value = true
|
||||
}
|
||||
|
||||
wg.return_value = dt.new_widget("entry"){
|
||||
text = "",
|
||||
sensitive = false
|
||||
}
|
||||
|
||||
dt.register_lib(
|
||||
"execute_action", -- Module name
|
||||
"execute gui actions", -- name
|
||||
true, -- expandable
|
||||
false, -- resetable
|
||||
{[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_LEFT_CENTER", 100},
|
||||
[dt.gui.views.darkroom] = {"DT_UI_CONTAINER_PANEL_LEFT_CENTER", 100}},
|
||||
dt.new_widget("box")
|
||||
{
|
||||
orientation = "vertical",
|
||||
|
||||
dt.new_widget("box")
|
||||
{
|
||||
orientation = "horizontal",
|
||||
dt.new_widget("label"){label = "action path", halign = "start"},
|
||||
wg.action
|
||||
},
|
||||
wg.instance,
|
||||
dt.new_widget("box")
|
||||
{
|
||||
orientation = "horizontal",
|
||||
dt.new_widget("label"){label = "element", halign = "start"},
|
||||
wg.element
|
||||
},
|
||||
dt.new_widget("box")
|
||||
{
|
||||
orientation = "horizontal",
|
||||
dt.new_widget("label"){label = "effect", halign = "start"},
|
||||
wg.effect
|
||||
},
|
||||
wg.check,
|
||||
dt.new_widget("box")
|
||||
{
|
||||
orientation = "horizontal",
|
||||
dt.new_widget("label"){label = "speed", halign = "start"},
|
||||
wg.speed
|
||||
},
|
||||
dt.new_widget("button")
|
||||
{
|
||||
label = "execute action",
|
||||
tooltip = "execute the action specified in the fields above",
|
||||
clicked_callback = function(_)
|
||||
local sp = NaN
|
||||
if wg.check.value then sp = wg.speed.text end
|
||||
wg.return_value.text = dt.gui.action(wg.action.text, wg.instance.value, wg.element.text, wg.effect.text, sp)
|
||||
end
|
||||
},
|
||||
dt.new_widget("box")
|
||||
{
|
||||
orientation = "horizontal",
|
||||
dt.new_widget("label"){label = "return value:", halign = "start"},
|
||||
wg.return_value
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -42,6 +42,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
-- translation
|
||||
|
||||
|
||||
163
examples/x-touch.lua
Normal file
163
examples/x-touch.lua
Normal file
@@ -0,0 +1,163 @@
|
||||
--[[
|
||||
This file is part of darktable,
|
||||
copyright (c) 2023 Diederik ter Rahe
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
]]
|
||||
--[[
|
||||
X-Touch Mini flexible encoder shortcuts
|
||||
|
||||
This script will create virtual sliders that are mapped dynamically to
|
||||
the most relevant sliders for the currently focused processing module.
|
||||
Tailored modules are color zones, tone equalizer, color calibration and
|
||||
mask manager properties. The script can easily be amended for other
|
||||
devices or personal preferences. Virtual "toggle" buttons can be created
|
||||
as well, that dynamically change meaning depending on current status.
|
||||
|
||||
USAGE
|
||||
* require this script from your main lua file
|
||||
* restart darktable
|
||||
* create shortcuts for each of the encoders on the x-touch mini
|
||||
to a virtual slider under lua/x-touch
|
||||
or import the following shortcutsrc file in the shortcuts dialog/preferences tab:
|
||||
|
||||
None;midi:CC1=lua/x-touch/knob 1
|
||||
None;midi:CC2=lua/x-touch/knob 2
|
||||
None;midi:CC3=lua/x-touch/knob 3
|
||||
None;midi:CC4=lua/x-touch/knob 4
|
||||
None;midi:CC5=lua/x-touch/knob 5
|
||||
None;midi:CC6=lua/x-touch/knob 6
|
||||
None;midi:CC7=lua/x-touch/knob 7
|
||||
None;midi:CC8=lua/x-touch/knob 8
|
||||
midi:E0=global/modifiers
|
||||
midi:F0=global/modifiers;ctrl
|
||||
midi:F#0=global/modifiers;alt
|
||||
midi:G#-1=iop/blend/tools/show and edit mask elements
|
||||
midi:A-1=iop/colorzones;focus
|
||||
midi:A#-1=iop/toneequal;focus
|
||||
midi:B-1=iop/colorbalancergb;focus
|
||||
midi:C0=iop/channelmixerrgb;focus
|
||||
]]
|
||||
|
||||
local dt = require "darktable"
|
||||
local du = require "lib/dtutils"
|
||||
|
||||
du.check_min_api_version("9.2.0", "x-touch")
|
||||
|
||||
-- set up 8 mimic sliders with the same function
|
||||
for k = 1,8 do
|
||||
dt.gui.mimic("slider", "knob ".. k,
|
||||
function(action, element, effect, size)
|
||||
-- take the number from the mimic name
|
||||
local k = tonumber(action:sub(-1))
|
||||
|
||||
-- only operate in darkroom; return NAN otherwise
|
||||
if dt.gui.current_view() ~= dt.gui.views.darkroom then
|
||||
return 0/0
|
||||
end
|
||||
|
||||
local maskval = 0/0
|
||||
if k < 8 then
|
||||
-- first try if the mask slider at that position is active
|
||||
local s = { "opacity",
|
||||
"size",
|
||||
"feather",
|
||||
"hardness",
|
||||
"rotation",
|
||||
"curvature",
|
||||
"compression" }
|
||||
maskval = dt.gui.action("lib/masks/properties/" .. s[k],
|
||||
element, effect, size)
|
||||
end
|
||||
-- if a value different from NAN is returned, the slider was active
|
||||
if maskval == maskval then
|
||||
return maskval
|
||||
|
||||
-- try if colorzones module is focused; if so select element of graph
|
||||
elseif dt.gui.action("iop/colorzones", "focus") ~= 0 then
|
||||
which = "iop/colorzones/graph"
|
||||
local e = { "red",
|
||||
"orange",
|
||||
"yellow",
|
||||
"green",
|
||||
"aqua",
|
||||
"blue",
|
||||
"purple",
|
||||
"magenta" }
|
||||
element = e[k]
|
||||
|
||||
|
||||
-- if the sigmoid rgb primaries is focused,
|
||||
-- check sliders
|
||||
elseif dt.gui.action("iop/sigmoid", "focus") ~= 0 and k <8 then
|
||||
local e = { "red attenuation", "red rotation", "green attenuation", "green rotation", "blue attenuation", "blue rotation", "recover purity" }
|
||||
which = "iop/sigmoid/primaries/"..e[k]
|
||||
|
||||
-- if the rgb primaries is focused,
|
||||
-- check sliders
|
||||
elseif dt.gui.action("iop/primaries", "focus") ~= 0 and k >=1 then
|
||||
local e = { "red hue", "red purity", "green hue", "green purity", "blue hue", "blue purity", "tint hue", "tint purity" }
|
||||
which = "iop/primaries/" ..e[k]
|
||||
|
||||
-- if the tone equalizer is focused,
|
||||
-- select one of the sliders in the "simple" tab
|
||||
elseif dt.gui.action("iop/toneequal", "focus") ~= 0 then
|
||||
which ="iop/toneequal/simple/"..(k-9).." EV"
|
||||
|
||||
-- if color calibration is focused,
|
||||
-- the last 4 knobs are sent there
|
||||
elseif dt.gui.action("iop/channelmixerrgb", "focus") ~= 0
|
||||
and k >= 5 then
|
||||
-- knob 5 selects the active tab; pressing it resets to CAT
|
||||
if k == 5 then
|
||||
which = "iop/channelmixerrgb/page"
|
||||
element = "CAT"
|
||||
-- since the tab action is not a slider,
|
||||
-- the effects need to be translated
|
||||
if effect == "up" then effect = "next"
|
||||
elseif effect == "down" then effect = "previous"
|
||||
else effect = "activate"
|
||||
end
|
||||
else
|
||||
-- knobs 6, 7 and 8 are for the three color sliders on each tab
|
||||
which = "iop/focus/sliders"
|
||||
local e = { "1st",
|
||||
"2nd",
|
||||
"3rd" }
|
||||
element = e[k - 5]
|
||||
end
|
||||
|
||||
-- the 4th knob is contrast;
|
||||
-- either colorbalance if it is focused, or filmic
|
||||
elseif dt.gui.action("iop/colorbalancergb", "focus") ~= 0
|
||||
and k == 4 then
|
||||
which = "iop/colorbalancergb/contrast"
|
||||
|
||||
-- in all other cases use a default selection
|
||||
else
|
||||
local s = { "iop/exposure/exposure",
|
||||
"iop/filmicrgb/white relative exposure",
|
||||
"iop/filmicrgb/black relative exposure",
|
||||
"iop/filmicrgb/contrast",
|
||||
"iop/crop/left",
|
||||
"iop/crop/right",
|
||||
"iop/crop/top",
|
||||
"iop/crop/bottom" }
|
||||
which = s[k]
|
||||
end
|
||||
|
||||
-- now pass the element/effect/size to the selected slider
|
||||
return dt.gui.action(which, element, effect, size)
|
||||
end)
|
||||
end
|
||||
@@ -65,10 +65,47 @@ function dtutils.check_min_api_version(min_api, script_name)
|
||||
dt.print_error("This application is written for lua api version " .. min_api .. " or later.")
|
||||
dt.print_error("The current lua api version is " .. current_api)
|
||||
dt.print("ERROR: " .. script_name .. " failed to load. Lua API version " .. min_api .. " or later required.")
|
||||
dt.control.sleep(2000) -- allow time for the error to display before script_manager writes it's error message
|
||||
error("Minimum API " .. min_api .. " not met for " .. script_name .. ".", 0)
|
||||
end
|
||||
end
|
||||
|
||||
dtutils.libdoc.functions["check_max_api_version"] = {
|
||||
Name = [[check_max_api_version]],
|
||||
Synopsis = [[check the maximum required api version against the current api version]],
|
||||
Usage = [[local du = require "lib/dtutils"
|
||||
|
||||
local result = du.check_max_api_version(max_api, script_name)
|
||||
max_api - string - the api version that the application was written for (example: "5.0.0")
|
||||
script_name - string - the name of the script]],
|
||||
Description = [[check_max_api_version compares the maximum api required for the appllication to
|
||||
run against the current api version. This function is used when a part of the Lua API that
|
||||
the script relies on is removed. If the maximum api version is not met, then an
|
||||
error message is printed saying the script_name failed to load, then an error is thrown causing the
|
||||
program to stop executing.
|
||||
|
||||
Return_Value = [[result - true if the maximum api version is available, false if not.]],
|
||||
Limitations = [[When using the default handler on a script being executed from the luarc file, the error thrown
|
||||
will stop the luarc file from executing any remaining statements. This limitation does not apply to script_manger.]],
|
||||
Example = [[check_max_api_version("9.0.0") does nothing if the api is less than or equal to 9.0.0 otherwise an
|
||||
error message is printed and an error is thrown stopping execution of the script.]],
|
||||
See_Also = [[]],
|
||||
Reference = [[]],
|
||||
License = [[]],
|
||||
Copyright = [[]],
|
||||
}
|
||||
|
||||
function dtutils.check_max_api_version(max_api, script_name)
|
||||
local current_api = dt.configuration.api_version_string
|
||||
if current_api > max_api then
|
||||
dt.print_error("This application is written for lua api version " .. max_api .. " or earlier.")
|
||||
dt.print_error("The current lua api version is " .. current_api)
|
||||
dt.print("ERROR: " .. script_name .. " failed to load. Lua API version " .. max_api .. " or earlier required.")
|
||||
dt.control.sleep(2000) -- allow time for the error to display before script_manager writes it's error message
|
||||
error("Maximum API " .. max_api .. " not met for " .. script_name .. ".", 0)
|
||||
end
|
||||
end
|
||||
|
||||
dtutils.libdoc.functions["split"] = {
|
||||
Name = [[split]],
|
||||
Synopsis = [[split a string on a specified separator]],
|
||||
@@ -184,7 +221,8 @@ function dtutils.prequire(req_name)
|
||||
if status then
|
||||
log.msg(log.info, "Loaded " .. req_name)
|
||||
else
|
||||
log.msg(log.info, "Error loading " .. req_name)
|
||||
log.msg(log.error, "Error loading " .. req_name)
|
||||
log.msg(log.error, "Error returned is " .. lib)
|
||||
end
|
||||
return status, lib
|
||||
end
|
||||
|
||||
12
locale/de_DE/LC_MESSAGES/select_non_existing.po
Normal file
12
locale/de_DE/LC_MESSAGES/select_non_existing.po
Normal file
@@ -0,0 +1,12 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
|
||||
msgid "select non existing images"
|
||||
msgstr "nicht vorhandene Bilder auswählen"
|
||||
|
||||
msgid "select non existing"
|
||||
msgstr "nicht vorhandene auswählen"
|
||||
|
||||
msgid "select all non-existing images in the current images"
|
||||
msgstr "alle nicht vorhandenen Bilder in den aktuellen Bildern auswählen"
|
||||
@@ -21,7 +21,7 @@ a simple script that will automatically look for newer releases on github and in
|
||||
when there is something. it will only check on startup and only once a week.
|
||||
|
||||
USAGE
|
||||
* install luasec and cjson for Lua 5.2 on your system
|
||||
* install luasec and cjson for Lua 5.4 on your system
|
||||
* require this script from your main lua file
|
||||
* restart darktable
|
||||
|
||||
@@ -41,6 +41,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
-- compare two version strings of the form "major.minor.patch"
|
||||
-- returns -1, 0, 1 if the first version is smaller, equal, greater than the second version,
|
||||
|
||||
@@ -38,6 +38,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
-- set this to "false" if you don't want to overwrite metadata fields
|
||||
-- (title, description, creator, publisher and rights) that are already set
|
||||
|
||||
@@ -40,6 +40,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
dt.preferences.register("delete_long_tags", "length", "integer",
|
||||
"maximum length of tags to keep",
|
||||
|
||||
@@ -44,6 +44,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
-- deleting while iterating the tags list seems to break the iterator!
|
||||
local unused_tags = {}
|
||||
|
||||
@@ -50,6 +50,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
-- 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)
|
||||
|
||||
@@ -47,6 +47,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
dt.preferences.register("generate_image_txt",
|
||||
"enabled",
|
||||
|
||||
@@ -40,6 +40,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
local ipiu = {}
|
||||
ipiu.module_installed = false
|
||||
|
||||
@@ -45,6 +45,7 @@ local filter_dropdown = dt.new_widget("combobox")
|
||||
{
|
||||
label = "import filter",
|
||||
editable = false,
|
||||
tooltip = "import filters are applied after completion of the import dialog",
|
||||
|
||||
changed_callback = function(widget)
|
||||
dt.preferences.write("import_filter_manager", "active_filter", "string", widget.value)
|
||||
|
||||
@@ -45,6 +45,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
local buffer_count = 5
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
dt.preferences.register
|
||||
("selection_to_pdf","Open with","string",
|
||||
|
||||
@@ -41,6 +41,7 @@ local script_data = {}
|
||||
script_data.destroy = nil -- function to destory the script
|
||||
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet
|
||||
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
|
||||
script_data.show = nil -- only required for libs since the destroy_method only hides them
|
||||
|
||||
local PS = dt.configuration.running_os == "windows" and "\\" or "/"
|
||||
|
||||
@@ -105,7 +106,7 @@ local function install_module()
|
||||
"executable manager", -- Visible name
|
||||
true, -- expandable
|
||||
false, -- resetable
|
||||
{[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_LEFT_BOTTOM", 100}}, -- containers
|
||||
{[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_LEFT_BOTTOM", 600}}, -- containers
|
||||
dt.new_widget("box") -- widget
|
||||
{
|
||||
orientation = "vertical",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--[[
|
||||
This file is part of darktable,
|
||||
copyright (c) 2018, 2020 Bill Ferguson <wpferguson@gmail.com>
|
||||
copyright (c) 2018, 2020, 2023 Bill Ferguson <wpferguson@gmail.com>
|
||||
|
||||
darktable is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -60,7 +60,7 @@ local gettext = dt.gettext
|
||||
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain("script_manager",dt.configuration.config_dir.."/lua/locale/")
|
||||
dt.gettext.bindtextdomain("script_manager",dt.configuration.config_dir.."/lua/locale/")
|
||||
|
||||
local function _(msgid)
|
||||
return gettext.dgettext("script_manager", msgid)
|
||||
@@ -98,19 +98,8 @@ local LUA_API_VER = "API-" .. dt.configuration.api_version_string
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
dt.preferences.register(MODULE, "check_update", "bool",
|
||||
"check for updated scripts on start up",
|
||||
"automatically update scripts to correct version",
|
||||
true)
|
||||
|
||||
local check_for_updates = dt.preferences.read(MODULE, "check_update", "bool")
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- P R E F E R E N C E S
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
dt.preferences.register(MODULE, "check_update", "bool",
|
||||
"check for updated scripts on start up",
|
||||
"automatically update scripts to correct version",
|
||||
_("check for updated scripts on start up"),
|
||||
_("automatically update scripts to correct version"),
|
||||
true)
|
||||
|
||||
local check_for_updates = dt.preferences.read(MODULE, "check_update", "bool")
|
||||
@@ -141,6 +130,10 @@ sm.event_registered = false
|
||||
sm.widgets = {}
|
||||
sm.categories = {}
|
||||
|
||||
-- set log level for functions
|
||||
|
||||
sm.log_level = DEFAULT_LOG_LEVEL
|
||||
|
||||
--[[
|
||||
|
||||
sm.scripts is a table of tables for containing the scripts
|
||||
@@ -170,6 +163,8 @@ sm.categories = {}
|
||||
storage_name name of the exporter (in the exporter storage menu)
|
||||
has_action true if it creates an action
|
||||
action_name name on the button
|
||||
has_select true if it creates a select
|
||||
select_name name on the button
|
||||
has_event true if it creates an event handler
|
||||
event_type type of event, shortcut, post-xxx, pre-xxx
|
||||
callback name of the callback routine
|
||||
@@ -201,22 +196,42 @@ sm.run = false
|
||||
-- F U N C T I O N S
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
-------------------
|
||||
-- helper functions
|
||||
-------------------
|
||||
|
||||
local function set_log_level(level)
|
||||
local old_log_level = log.log_level()
|
||||
log.log_level(level)
|
||||
return old_log_level
|
||||
end
|
||||
|
||||
local function restore_log_level(level)
|
||||
log.log_level(level)
|
||||
end
|
||||
|
||||
local function pref_read(name, pref_type)
|
||||
local old_log_level = set_log_level(sm.log_level)
|
||||
log.msg(log.debug, "name is " .. name .. " and type is " .. pref_type)
|
||||
local val = dt.preferences.read(MODULE, name, pref_type)
|
||||
if not string.match(pref_type, "bool") then
|
||||
log.msg(log.debug, "read value " .. tostring(val))
|
||||
end
|
||||
restore_log_level(old_log_level)
|
||||
return val
|
||||
end
|
||||
|
||||
local function pref_write(name, pref_type, value)
|
||||
local old_log_level = set_log_level(sm.log_level)
|
||||
log.msg(log.debug, "writing value " .. tostring(value) .. " for name " .. name)
|
||||
dt.preferences.write(MODULE, name, pref_type, value)
|
||||
restore_log_level(old_log_level)
|
||||
end
|
||||
|
||||
----------------
|
||||
-- git interface
|
||||
----------------
|
||||
|
||||
local function get_repo_status(repo)
|
||||
local old_log_level = set_log_level(sm.log_level)
|
||||
local p = io.popen("cd " .. repo .. CS .. "git status")
|
||||
if p then
|
||||
local data = p:read("*a")
|
||||
@@ -224,10 +239,12 @@ local function get_repo_status(repo)
|
||||
return data
|
||||
end
|
||||
log.msg(log.error, "unable to get status of " .. repo)
|
||||
restore_log_level(old_log_level)
|
||||
return nil
|
||||
end
|
||||
|
||||
local function get_current_repo_branch(repo)
|
||||
local old_log_level = set_log_level(sm.log_level)
|
||||
local branch = nil
|
||||
local p = io.popen("cd " .. repo .. CS .. "git branch --all")
|
||||
if p then
|
||||
@@ -246,10 +263,12 @@ local function get_current_repo_branch(repo)
|
||||
if not branch then
|
||||
log.msg(log.error, "no current branch detected in repo_data")
|
||||
end
|
||||
restore_log_level(old_log_level)
|
||||
return nil
|
||||
end
|
||||
|
||||
local function get_repo_branches(repo)
|
||||
local old_log_level = set_log_level(sm.log_level)
|
||||
local branches = {}
|
||||
local p = io.popen("cd " .. repo .. CS .. "git pull --all" .. CS .. "git branch --all")
|
||||
if p then
|
||||
@@ -266,11 +285,12 @@ local function get_repo_branches(repo)
|
||||
end
|
||||
end
|
||||
end
|
||||
restore_log_level(old_log_level)
|
||||
return branches
|
||||
end
|
||||
|
||||
|
||||
local function is_repo_clean(repo_data)
|
||||
local old_log_level = set_log_level(sm.log_level)
|
||||
if string.match(repo_data, "\n%s-%a.-%a:%s-%a%g-\n") then
|
||||
log.msg(log.info, "repo is dirty")
|
||||
return false
|
||||
@@ -278,14 +298,22 @@ local function is_repo_clean(repo_data)
|
||||
log.msg(log.info, "repo is clean")
|
||||
return true
|
||||
end
|
||||
restore_log_level(old_log_level)
|
||||
end
|
||||
|
||||
local function checkout_repo_branch(repo, branch)
|
||||
local old_log_level = set_log_level(sm.log_level)
|
||||
log.msg(log.info, "checkout out branch " .. branch .. " from repository " .. repo)
|
||||
os.execute("cd " .. repo .. CS .. "git checkout " .. branch)
|
||||
restore_log_level(old_log_level)
|
||||
end
|
||||
|
||||
--------------------
|
||||
-- utility functions
|
||||
--------------------
|
||||
|
||||
local function update_combobox_choices(combobox, choice_table, selected)
|
||||
local old_log_level = set_log_level(sm.log_level)
|
||||
local items = #combobox
|
||||
local choices = #choice_table
|
||||
for i, name in ipairs(choice_table) do
|
||||
@@ -301,11 +329,14 @@ local function update_combobox_choices(combobox, choice_table, selected)
|
||||
end
|
||||
|
||||
combobox.value = selected
|
||||
restore_log_level(old_log_level)
|
||||
end
|
||||
|
||||
local function string_trim(str)
|
||||
local old_log_level = set_log_level(sm.log_level)
|
||||
local result = string.gsub(str, "^%s+", "")
|
||||
result = string.gsub(result, "%s+$", "")
|
||||
restore_log_level(old_log_level)
|
||||
return result
|
||||
end
|
||||
|
||||
@@ -313,15 +344,22 @@ local function string_dequote(str)
|
||||
return string.gsub(str, "['\"]", "")
|
||||
end
|
||||
|
||||
------------------
|
||||
-- script handling
|
||||
------------------
|
||||
|
||||
local function add_script_category(category)
|
||||
local old_log_level = set_log_level(sm.log_level)
|
||||
if #sm.categories == 0 or not string.match(du.join(sm.categories, " "), ds.sanitize_lua(category)) then
|
||||
table.insert(sm.categories, category)
|
||||
sm.scripts[category] = {}
|
||||
log.msg(log.debug, "created category " .. category)
|
||||
end
|
||||
restore_log_level(old_log_level)
|
||||
end
|
||||
|
||||
local function get_script_doc(script)
|
||||
local old_log_level = set_log_level(sm.log_level)
|
||||
local description = nil
|
||||
f = io.open(LUA_DIR .. PS .. script .. ".lua")
|
||||
if f then
|
||||
@@ -334,13 +372,16 @@ local function get_script_doc(script)
|
||||
log.msg(log.error, _("Cant read from " .. script))
|
||||
end
|
||||
if description then
|
||||
restore_log_level(old_log_level)
|
||||
return description
|
||||
else
|
||||
restore_log_level(old_log_level)
|
||||
return "No documentation available"
|
||||
end
|
||||
end
|
||||
|
||||
local function activate(script)
|
||||
local old_log_level = set_log_level(sm.log_level)
|
||||
local status = nil -- status of start function
|
||||
local err = nil -- error message returned if module doesn't start
|
||||
log.msg(log.info, "activating " .. script.name)
|
||||
@@ -356,7 +397,7 @@ local function activate(script)
|
||||
if err ~= true then
|
||||
log.msg(log.debug, "got lib data")
|
||||
script.data = err
|
||||
if script.data.destroy_method and script.data.destroy_method == "hide" then
|
||||
if script.data.destroy_method and script.data.destroy_method == "hide" and script.data.show and dt.gui.current_view().id == "lighttable" then
|
||||
script.data.show()
|
||||
end
|
||||
else
|
||||
@@ -373,16 +414,20 @@ local function activate(script)
|
||||
status = true
|
||||
pref_write(script.script_name, "bool", true)
|
||||
end
|
||||
restore_log_level(old_log_level)
|
||||
return status
|
||||
end
|
||||
|
||||
local function deactivate(script)
|
||||
-- presently the lua api doesn't support unloading gui elements however, we
|
||||
-- presently the lua api doesn't support unloading lib elements however, we
|
||||
-- can hide libs, so we just mark those as hidden and hide the gui
|
||||
-- can delete storage
|
||||
--therefore we just mark then inactive for the next time darktable starts
|
||||
-- can delete storages
|
||||
-- can delete actions
|
||||
-- can delete selects
|
||||
-- and mark them inactive for the next time darktable starts
|
||||
|
||||
-- deactivate it....
|
||||
local old_log_level = set_log_level(sm.log_level)
|
||||
pref_write(script.script_name, "bool", false)
|
||||
if script.data then
|
||||
script.data.destroy()
|
||||
@@ -404,9 +449,11 @@ local function deactivate(script)
|
||||
log.msg(log.info, "setting " .. script.script_name .. " to not start")
|
||||
log.msg(log.screen, script.name .. _(" will not start when darktable is restarted"))
|
||||
end
|
||||
restore_log_level(old_log_level)
|
||||
end
|
||||
|
||||
local function add_script_name(name, path, category)
|
||||
local old_log_level = set_log_level(sm.log_level)
|
||||
log.msg(log.debug, "category is " .. category)
|
||||
log.msg(log.debug, "name is " .. name)
|
||||
local script = {
|
||||
@@ -420,10 +467,14 @@ local function add_script_name(name, path, category)
|
||||
table.insert(sm.scripts[category], script)
|
||||
if pref_read(script.script_name, "bool") then
|
||||
activate(script)
|
||||
else
|
||||
pref_write(script.script_name, "bool", false)
|
||||
end
|
||||
restore_log_level(old_log_level)
|
||||
end
|
||||
|
||||
local function process_script_data(script_file)
|
||||
local old_log_level = set_log_level(sm.log_level)
|
||||
|
||||
-- the script file supplied is category/filename.filetype
|
||||
-- the following pattern splits the string into category, path, name, fileename, and filetype
|
||||
@@ -446,21 +497,53 @@ local function process_script_data(script_file)
|
||||
|
||||
-- add the script data
|
||||
local category,path,name,filename,filetype = string.match(script_file, pattern)
|
||||
|
||||
if category and name and path then
|
||||
log.msg(log.debug, "category is " .. category)
|
||||
log.msg(log.debug, "name is " .. name)
|
||||
|
||||
add_script_category(category)
|
||||
|
||||
if name then
|
||||
add_script_name(name, path, category)
|
||||
end
|
||||
|
||||
restore_log_level(old_log_level)
|
||||
end
|
||||
|
||||
local function ensure_lib_in_search_path(line)
|
||||
local old_log_level = set_log_level(sm.log_level)
|
||||
set_log_level(log.debug)
|
||||
|
||||
log.msg(log.debug, "line is " .. line)
|
||||
|
||||
if string.match(line, ds.sanitize_lua(dt.configuration.config_dir .. PS .. "lua" .. PS .. "lib")) then
|
||||
log.msg(log.debug, line .. " is already in search path, returning...")
|
||||
return
|
||||
end
|
||||
|
||||
local pattern = dt.configuration.running_os == "windows" and "(.+)\\lib\\.+lua" or "(.+)/lib/.+lua"
|
||||
local path = string.match(line, pattern)
|
||||
|
||||
log.msg(log.debug, "extracted path is " .. path)
|
||||
log.msg(log.debug, "package.path is " .. package.path)
|
||||
|
||||
if not string.match(package.path, ds.sanitize_lua(path)) then
|
||||
|
||||
log.msg(log.debug, "path isn't in package.path, adding...")
|
||||
|
||||
package.path = package.path .. ";" .. path .. "/?.lua"
|
||||
|
||||
log.msg(log.debug, "new package.path is " .. package.path)
|
||||
end
|
||||
|
||||
restore_log_level(old_log_level)
|
||||
end
|
||||
|
||||
local function scan_scripts(script_dir)
|
||||
local old_log_level = set_log_level(sm.log_level)
|
||||
local script_count = 0
|
||||
local find_cmd = "find -L " .. script_dir .. " -name \\*.lua -print | sort"
|
||||
if dt.configuration.running_os == "windows" then
|
||||
find_cmd = "dir /b/s " .. script_dir .. "\\*.lua | sort"
|
||||
find_cmd = "dir /b/s \"" .. script_dir .. "\\*.lua\" | sort"
|
||||
end
|
||||
log.msg(log.debug, _("find command is ") .. find_cmd)
|
||||
-- scan the scripts
|
||||
@@ -475,14 +558,18 @@ local function scan_scripts(script_dir)
|
||||
process_script_data(script_file)
|
||||
script_count = script_count + 1
|
||||
end
|
||||
else
|
||||
ensure_lib_in_search_path(line) -- but let's make sure libraries can be found
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
restore_log_level(old_log_level)
|
||||
return script_count
|
||||
end
|
||||
|
||||
local function update_scripts()
|
||||
local old_log_level = set_log_level(sm.log_level)
|
||||
local result = false
|
||||
|
||||
local git = sm.executables.git
|
||||
@@ -505,10 +592,16 @@ local function update_scripts()
|
||||
dt.print(_("lua scripts successfully updated"))
|
||||
end
|
||||
|
||||
restore_log_level(old_log_level)
|
||||
return result
|
||||
end
|
||||
|
||||
--------------
|
||||
-- UI handling
|
||||
--------------
|
||||
|
||||
local function update_script_update_choices()
|
||||
local old_log_level = set_log_level(sm.log_level)
|
||||
local installs = {}
|
||||
local pref_string = ""
|
||||
for i, repo in ipairs(sm.installed_repositories) do
|
||||
@@ -518,9 +611,11 @@ local function update_script_update_choices()
|
||||
update_combobox_choices(sm.widgets.update_script_choices, installs, 1)
|
||||
log.msg(log.debug, "repo pref string is " .. pref_string)
|
||||
pref_write("installed_repos", "string", pref_string)
|
||||
restore_log_level(old_log_level)
|
||||
end
|
||||
|
||||
local function scan_repositories()
|
||||
local old_log_level = set_log_level(sm.log_level)
|
||||
local script_count = 0
|
||||
local find_cmd = "find -L " .. LUA_DIR .. " -name \\*.git -print | sort"
|
||||
if dt.configuration.running_os == "windows" then
|
||||
@@ -555,15 +650,18 @@ local function scan_repositories()
|
||||
end
|
||||
end
|
||||
update_script_update_choices()
|
||||
restore_log_level(old_log_level)
|
||||
end
|
||||
|
||||
local function install_scripts()
|
||||
local old_log_level = set_log_level(sm.log_level)
|
||||
local url = sm.widgets.script_url.text
|
||||
local category = sm.widgets.new_category.text
|
||||
|
||||
if string.match(du.join(sm.categories, " "), ds.sanitize_lua(category)) then
|
||||
log.msg(log.screen, _("category ") .. category .. _(" is already in use. Please specify a different category name."))
|
||||
log.msg(log.error, "category " .. category .. " already exists, returning...")
|
||||
restore_log_level(old_log_level)
|
||||
return
|
||||
end
|
||||
|
||||
@@ -573,6 +671,7 @@ local function install_scripts()
|
||||
|
||||
if not git then
|
||||
dt.print(_("ERROR: git not found. Install or specify the location of the git executable."))
|
||||
restore_log_level(old_log_level)
|
||||
return
|
||||
end
|
||||
|
||||
@@ -614,28 +713,34 @@ local function install_scripts()
|
||||
dt.print(_("failed to download scripts"))
|
||||
end
|
||||
|
||||
restore_log_level(old_log_level)
|
||||
return result
|
||||
end
|
||||
|
||||
local function clear_button(number)
|
||||
local old_log_level = set_log_level(sm.log_level)
|
||||
local button = sm.widgets.buttons[number]
|
||||
button.label = ""
|
||||
button.tooltip = ""
|
||||
button.sensitive = false
|
||||
--button.name = ""
|
||||
--button.name = ""
|
||||
restore_log_level(old_log_level)
|
||||
end
|
||||
|
||||
local function find_script(category, name)
|
||||
local old_log_level = set_log_level(sm.log_level)
|
||||
log.msg(log.debug, "looking for script " .. name .. " in category " .. category)
|
||||
for _, script in ipairs(sm.scripts[category]) do
|
||||
if string.match(script.name, "^" .. ds.sanitize_lua(name) .. "$") then
|
||||
return script
|
||||
end
|
||||
end
|
||||
restore_log_level(old_log_level)
|
||||
return nil
|
||||
end
|
||||
|
||||
local function populate_buttons(category, first, last)
|
||||
local old_log_level = set_log_level(sm.log_level)
|
||||
log.msg(log.debug, "category is " .. category .. " and first is " .. first .. " and last is " .. last)
|
||||
local button_num = 1
|
||||
for i = first, last do
|
||||
@@ -700,9 +805,11 @@ local function populate_buttons(category, first, last)
|
||||
clear_button(i)
|
||||
end
|
||||
end
|
||||
restore_log_level(old_log_level)
|
||||
end
|
||||
|
||||
local function paginate(direction)
|
||||
local old_log_level = set_log_level(sm.log_level)
|
||||
local category = sm.page_status.category
|
||||
log.msg(log.debug, "category is " .. category)
|
||||
local num_scripts = #sm.scripts[category]
|
||||
@@ -754,9 +861,11 @@ local function paginate(direction)
|
||||
sm.widgets.page_status.label = _("Page ") .. cur_page .. _(" of ") .. max_pages
|
||||
|
||||
populate_buttons(category, first, last)
|
||||
restore_log_level(old_log_level)
|
||||
end
|
||||
|
||||
local function change_category(category)
|
||||
local old_log_level = set_log_level(sm.log_level)
|
||||
if not category then
|
||||
log.msg(log.debug "setting category to selector value " .. sm.widgets.category_selector.value)
|
||||
sm.page_status.category = sm.widgets.category_selector.value
|
||||
@@ -766,9 +875,11 @@ local function change_category(category)
|
||||
end
|
||||
|
||||
paginate(2)
|
||||
restore_log_level(old_log_level)
|
||||
end
|
||||
|
||||
local function change_num_buttons()
|
||||
local old_log_level = set_log_level(sm.log_level)
|
||||
cur_buttons = sm.page_status.num_buttons
|
||||
new_buttons = sm.widgets.num_buttons.value
|
||||
pref_write("num_buttons", "integer", new_buttons)
|
||||
@@ -799,9 +910,11 @@ local function change_num_buttons()
|
||||
log.msg(log.debug, "num_buttons set to " .. sm.page_status.num_buttons)
|
||||
paginate(2) -- force the buttons to repopulate
|
||||
sm.widgets.main_menu.selected = 3 -- jump back to start/stop scripts
|
||||
restore_log_level(old_log_level)
|
||||
end
|
||||
|
||||
local function load_preferences()
|
||||
local old_log_level = set_log_level(sm.log_level)
|
||||
-- load the prefs and update settings
|
||||
-- update_script_choices
|
||||
local pref_string = pref_read("installed_repos", "string")
|
||||
@@ -843,16 +956,18 @@ local function load_preferences()
|
||||
log.msg(log.debug, "set main menu to val " .. val .. " which is " .. sm.widgets.main_menu.value)
|
||||
|
||||
log.msg(log.debug, "set main menu to " .. sm.widgets.main_menu.value)
|
||||
restore_log_level(old_log_level)
|
||||
end
|
||||
|
||||
local function install_module()
|
||||
local old_log_level = set_log_level(sm.log_level)
|
||||
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_BOTTOM", 600}}, -- containers
|
||||
{[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_LEFT_BOTTOM", 100}}, -- containers
|
||||
sm.widgets.main_box,
|
||||
nil,-- view_enter
|
||||
nil -- view_leave
|
||||
@@ -875,6 +990,7 @@ local function install_module()
|
||||
dt.control.sleep(5000)
|
||||
dt.print_log("setting sm expanded true")
|
||||
dt.gui.libs["script_manager"].expanded = true]]
|
||||
restore_log_level(old_log_level)
|
||||
end
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
@@ -1164,6 +1280,7 @@ sm.widgets.main_box = dt.new_widget("box"){
|
||||
}
|
||||
|
||||
script_manager_running_script = nil
|
||||
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
-- D A R K T A B L E I N T E G R A T I O N
|
||||
-- - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
Reference in New Issue
Block a user