Compare commits
116 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
97dd8a1257 | ||
|
|
83fc339c4b | ||
|
|
693c535428 | ||
|
|
d74f2eba92 | ||
|
|
d0ec941009 | ||
|
|
178528508b | ||
|
|
20a31b39e0 | ||
|
|
fc252d5e7e | ||
|
|
4090266989 | ||
|
|
19b7d29483 | ||
|
|
af4e3884bb | ||
|
|
d3742bb410 | ||
|
|
75cb1a5fdd | ||
|
|
8436c878e8 | ||
|
|
63d3a34f46 | ||
|
|
6cda97c335 | ||
|
|
a40d8b8bc5 | ||
|
|
15a492cfa3 | ||
|
|
445e882579 | ||
|
|
d4b155d0c2 | ||
|
|
65f4960302 | ||
|
|
dc9e8d406d | ||
|
|
4d76006c2d | ||
|
|
731a6d0410 | ||
|
|
e4542aa451 | ||
|
|
ecc4a29be4 | ||
|
|
0f0b3d6df5 | ||
|
|
a826c1725b | ||
|
|
4e3b461fd3 | ||
|
|
d8a9dfafb2 | ||
|
|
ede621bea7 | ||
|
|
2f7da8356f | ||
|
|
d555cb2c94 | ||
|
|
750d70bfff | ||
|
|
dcc205ec4f | ||
|
|
356756286e | ||
|
|
79511d9b42 | ||
|
|
bff2df018b | ||
|
|
2562a218a0 | ||
|
|
d46b7e4aaf | ||
|
|
dee7ee1dde | ||
|
|
01fc339da5 | ||
|
|
ef46cd9b45 | ||
|
|
ac3ccb287b | ||
|
|
f52292e8d1 | ||
|
|
693c9858c2 | ||
|
|
c8d5e9d9d2 | ||
|
|
50668817db | ||
|
|
91758b61c3 | ||
|
|
39ae92a0fa | ||
|
|
95c203793c | ||
|
|
c7ac974ab9 | ||
|
|
51931d2b01 | ||
|
|
d271f6d46d | ||
|
|
efcd48f1d9 | ||
|
|
76daa583b3 | ||
|
|
3425a85fd0 | ||
|
|
9a6c1510fd | ||
|
|
44c391cb5a | ||
|
|
6085be7589 | ||
|
|
7d9bf8c729 | ||
|
|
1d72457dc1 | ||
|
|
0e32d2b1b4 | ||
|
|
75165e8838 | ||
|
|
d9536f1294 | ||
|
|
44e4c3ddc5 | ||
|
|
f67755f3b5 | ||
|
|
68d768cbd3 | ||
|
|
0be268c01f | ||
|
|
1831db530d | ||
|
|
8a32bf21d0 | ||
|
|
81c5bb4d52 | ||
|
|
93796bf4a8 | ||
|
|
4c34113f78 | ||
|
|
e4b189a06e | ||
|
|
0ebc885eb1 | ||
|
|
b4658ddf76 | ||
|
|
b38e2964ca | ||
|
|
5021e512b9 | ||
|
|
6d927540c8 | ||
|
|
6168767766 | ||
|
|
5af200a29d | ||
|
|
8b333c1ab5 | ||
|
|
d1f34ec136 | ||
|
|
c887a0d2b5 | ||
|
|
1168ba4557 | ||
|
|
e389420f07 | ||
|
|
0590beb876 | ||
|
|
d30c0d0213 | ||
|
|
eb774d37c6 | ||
|
|
cade6d5e0b | ||
|
|
19b71c5782 | ||
|
|
5f802a8179 | ||
|
|
99e1141446 | ||
|
|
3bd76b4fb5 | ||
|
|
3fb4ef34f4 | ||
|
|
f7c2abdcd7 | ||
|
|
cc6006e226 | ||
|
|
2816c2bcf5 | ||
|
|
abc8061cd7 | ||
|
|
a30c4d6be5 | ||
|
|
0bd5b6ba5d | ||
|
|
4ea3a500e8 | ||
|
|
56925c1eed | ||
|
|
71e7269927 | ||
|
|
6babff1be1 | ||
|
|
fec000086f | ||
|
|
bddf4cedb4 | ||
|
|
91c62e208b | ||
|
|
1e0424a83f | ||
|
|
c74d29e020 | ||
|
|
eadfff9cd0 | ||
|
|
93e30a8542 | ||
|
|
ae8727ad96 | ||
|
|
de823f0430 | ||
|
|
c6ced0b1ea |
@@ -1,9 +1,9 @@
|
||||
lua-scripts
|
||||
===========
|
||||
|
||||
The Lua scripts in this repository are meant to be used together with darktable. Either copy them individually to `~/.config/darktable/lua` (you might have to create that folder) or just copy/symlink the whole repository there. That allows to update all your scripts with a simple call to `git pull`.
|
||||
The Lua scripts in this repository are meant to be used together with darktable. Either copy them individually to `~/.config/darktable/lua` (Linux/Unix) or `%LOCALAPPDATA%\darktable\lua` (Windows) (you might have to create that folder) or just copy/symlink the whole repository there. That allows to update all your scripts with a simple call to `git pull`.
|
||||
|
||||
To enable one of the scripts you have to add a line like `require "official/hello_world"` to your `~/.config/darktable/luarc` file which will enable the example script in `official/hello_world.lua` (note the lack of the `.lua` suffix).
|
||||
To enable one of the scripts you have to add a line like `require "examples/hello_world"` to your: `~/.config/darktable/luarc` (Linux/Unix) or `%LOCALAPPDATA%\darktable\luarc` (Windows) file which will enable the example script in `examples/hello_world.lua` (note the lack of the `.lua` suffix).
|
||||
|
||||
Each script includes its own documentation and usage in its header, please refer to them.
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@ USAGE
|
||||
> exiftool -AutoDynamicRange XE021351.RAF
|
||||
Auto Dynamic Range : 200%
|
||||
|
||||
ADDITIONAL SOFTWARE NEEDED FOR THIS SCRIPT
|
||||
* exiftool
|
||||
|
||||
LICENSE
|
||||
GPLv2
|
||||
@@ -41,7 +43,7 @@ local darktable = require "darktable"
|
||||
local autostyle_apply_one_image,autostyle_apply_one_image_event,autostyle_apply,exiftool_attribute,capture
|
||||
|
||||
-- Tested it with darktable 1.6.1 and darktable git from 2014-01-25
|
||||
darktable.configuration.check_version(...,{2,0,2},{2,1,0},{3,0,0})
|
||||
darktable.configuration.check_version(...,{2,0,2},{2,1,0},{3,0,0},{4,0,0},{5,0,0})
|
||||
|
||||
-- Receive the event triggered
|
||||
function autostyle_apply_one_image_event(event,image)
|
||||
@@ -66,6 +68,10 @@ function autostyle_apply_one_image (image)
|
||||
darktable.print("style name not found in " .. darktable.preferences.read("autostyle","exif_tag","string"))
|
||||
return
|
||||
end
|
||||
if not checkIfBinExists("exiftool") then
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
-- First find the style (we have its name)
|
||||
local styles= darktable.styles
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
--[[
|
||||
This file is part of darktable,
|
||||
Copyright 2014-2016 by Tobias Jakobs.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
]]
|
||||
--[[
|
||||
darktable calc distance script
|
||||
|
||||
This script calcs the distance between two images using the GPS data in the metadata
|
||||
|
||||
USAGE
|
||||
* require this script from your main lua file
|
||||
* register a shortcut
|
||||
]]
|
||||
|
||||
local dt = require "darktable"
|
||||
local gettext = dt.gettext
|
||||
dt.configuration.check_version(...,{3,0,0})
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain("calcDistance",dt.configuration.config_dir.."/lua/")
|
||||
|
||||
local function _(msgid)
|
||||
return gettext.dgettext("calcDistance", msgid)
|
||||
end
|
||||
|
||||
local function calcDistance()
|
||||
local sel_images = dt.gui.selection()
|
||||
|
||||
local lat1 = 0;
|
||||
local lon1 = 0;
|
||||
local lat2 = 0;
|
||||
local lon2 = 0;
|
||||
local ele1 = 0;
|
||||
local ele2 = 0;
|
||||
|
||||
local i = 0;
|
||||
|
||||
local sel_images = dt.gui.selection()
|
||||
|
||||
for _,image in ipairs(sel_images) do
|
||||
if ((image.longitude and image.latitude) and
|
||||
(image.longitude ~= 0 and image.latitude ~= 90) -- Sometimes the north-pole but most likely just wrong data
|
||||
) then
|
||||
|
||||
i = i + 1;
|
||||
|
||||
if (i == 1) then
|
||||
lat1 = image.latitude;
|
||||
lon1 = image.longitude;
|
||||
ele1 = image.elevation;
|
||||
end
|
||||
|
||||
lat2 = image.latitude;
|
||||
lon2 = image.longitude;
|
||||
ele2 = image.elevation;
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
-- I used code from here:
|
||||
-- http://stackoverflow.com/questions/27928/how-do-i-calculate-distance-between-two-latitude-longitude-points
|
||||
|
||||
local earthRadius = 6371; -- Radius of the earth in km
|
||||
local dLat = math.rad(lat2-lat1); -- deg2rad below
|
||||
local dLon = math.rad(lon2-lon1);
|
||||
local a =
|
||||
math.sin(dLat/2) * math.sin(dLat/2) +
|
||||
math.cos(math.rad(lat1)) * math.cos(math.rad(lat2)) *
|
||||
math.sin(dLon/2) * math.sin(dLon/2)
|
||||
;
|
||||
local angle = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a));
|
||||
local distance = earthRadius * angle; -- Distance in km
|
||||
|
||||
-- Add the elevation to the calculation
|
||||
local elevation = 0;
|
||||
elevation = math.abs(ele1 - ele2) / 1000; --in km
|
||||
distance = math.sqrt(math.pow(elevation,2) + math.pow(distance,2) );
|
||||
|
||||
local distanceUnit
|
||||
if (distance < 1) then
|
||||
distance = distance * 1000
|
||||
distanceUnit = "m"
|
||||
else
|
||||
distanceUnit = "km"
|
||||
end
|
||||
dt.print(string.format("Distance: %.2f %s", distance, distanceUnit))
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
-- Register
|
||||
dt.register_event("shortcut",calcDistance,_("Calculate the distance from latitude and longitude in km"))
|
||||
@@ -42,11 +42,11 @@ local gettext = dt.gettext
|
||||
-- not a number
|
||||
local NaN = 0/0
|
||||
|
||||
dt.configuration.check_version(...,{3,0,0})
|
||||
dt.configuration.check_version(...,{3,0,0},{4,0,0})
|
||||
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain("clear_GPS",dt.configuration.config_dir.."/lua/")
|
||||
gettext.bindtextdomain("clear_GPS",dt.configuration.config_dir.."/lua/locale/")
|
||||
|
||||
local function _(msgid)
|
||||
return gettext.dgettext("clear_GPS", msgid)
|
||||
|
||||
@@ -33,15 +33,17 @@ USAGE
|
||||
darktable internal tags starting with 'darktable|' will not be touched
|
||||
* <your shortcut3> removes all expect darktable internal tags from selected images
|
||||
* <your shortcut4> replaces all tags expect darktable internals
|
||||
|
||||
* A module reset will empty the clipboard
|
||||
]]
|
||||
|
||||
local dt = require "darktable"
|
||||
local debug = require "darktable.debug"
|
||||
|
||||
local gettext = dt.gettext
|
||||
dt.configuration.check_version(...,{3,0,0},{4,0,0})
|
||||
dt.configuration.check_version(...,{3,0,0},{4,0,0},{5,0,0})
|
||||
|
||||
-- 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/")
|
||||
gettext.bindtextdomain("copy_attach_detach_tags",dt.configuration.config_dir.."/lua/locale/")
|
||||
|
||||
local function _(msgid)
|
||||
return gettext.dgettext("copy_attach_detach_tags", msgid)
|
||||
@@ -156,42 +158,57 @@ end
|
||||
taglist_label.reset_callback = mcopy_tags
|
||||
|
||||
-- create buttons and elements
|
||||
local mc_button = dt.new_widget("button") {
|
||||
label = _('multi copy tags'),
|
||||
clicked_callback = mcopy_tags}
|
||||
|
||||
local p_button = dt.new_widget("button") {
|
||||
label = _('paste tags'),
|
||||
clicked_callback = attach_tags}
|
||||
|
||||
local rep_button = dt.new_widget("button") {
|
||||
label = _('replace tags'),
|
||||
clicked_callback = replace_tags}
|
||||
|
||||
local rem_button = dt.new_widget("button") {
|
||||
label = _('remove all tags'),
|
||||
clicked_callback = detach_tags}
|
||||
|
||||
local taglabel = dt.new_widget("label") {
|
||||
label = _('tag clipboard'),
|
||||
selectable = false,
|
||||
ellipsize = "middle",
|
||||
halign = "start"}
|
||||
|
||||
local box1 = dt.new_widget("box"){
|
||||
orientation = "horizontal",
|
||||
dt.new_widget("button") {
|
||||
label = _('multi copy tags'),
|
||||
clicked_callback = mcopy_tags},
|
||||
dt.new_widget("button") {
|
||||
label = _('paste tags'),
|
||||
clicked_callback = attach_tags}
|
||||
|
||||
}
|
||||
|
||||
local box2 = dt.new_widget("box"){
|
||||
orientation = "horizontal",
|
||||
dt.new_widget("button") {
|
||||
label = _('replace tags'),
|
||||
clicked_callback = replace_tags},
|
||||
dt.new_widget("button") {
|
||||
label = _('remove all tags'),
|
||||
clicked_callback = detach_tags}
|
||||
}
|
||||
|
||||
local sep = dt.new_widget("separator"){}
|
||||
|
||||
-- pack elements into widget table for a nicer layout
|
||||
local widget_table = {}
|
||||
|
||||
widget_table[1] = box1
|
||||
widget_table[#widget_table+1] = box2
|
||||
|
||||
widget_table[#widget_table+1] = sep
|
||||
widget_table[#widget_table+1] = taglabel
|
||||
widget_table[#widget_table+1] = taglist_label
|
||||
|
||||
|
||||
-- create modul
|
||||
dt.register_lib("tagging_addon","Tagging addon",true,false,{
|
||||
dt.register_lib("tagging_addon","Tagging addon",true,true,{
|
||||
[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER",500}
|
||||
},
|
||||
dt.new_widget("box") {
|
||||
orientation = "vertical",
|
||||
mc_button,
|
||||
p_button,
|
||||
rep_button,
|
||||
rem_button,
|
||||
taglabel,
|
||||
dt.new_widget("separator"){},
|
||||
taglist_label
|
||||
-- orientation = "vertical",
|
||||
reset_callback = function()
|
||||
taglist_label.label = ""
|
||||
image_tags = {}
|
||||
end,
|
||||
table.unpack(widget_table),
|
||||
},
|
||||
nil,
|
||||
nil
|
||||
|
||||
@@ -35,7 +35,7 @@ USAGE
|
||||
local darktable = require "darktable"
|
||||
|
||||
-- Tested with darktable 2.0.1
|
||||
darktable.configuration.check_version(...,{2,0,0},{3,0,0})
|
||||
darktable.configuration.check_version(...,{2,0,0},{3,0,0},{4,0,0})
|
||||
|
||||
local queue = {}
|
||||
local processed_files = {}
|
||||
|
||||
70
contrib/fujifilm_ratings.lua
Normal file
70
contrib/fujifilm_ratings.lua
Normal file
@@ -0,0 +1,70 @@
|
||||
--[[ fujifilm_ratings-0.1
|
||||
|
||||
Support for importing Fujifilm in-camera ratings in darktable.
|
||||
|
||||
Copyright (C) 2017 Ben Mendis <ben.mendis@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 2 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, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Dependencies:
|
||||
- exiftool (https://www.sno.phy.queensu.ca/~phil/exiftool/)
|
||||
|
||||
--]]
|
||||
|
||||
local dt = require "darktable"
|
||||
local df = require "lib/dtutils.file"
|
||||
local gettext = dt.gettext
|
||||
|
||||
dt.configuration.check_version(..., {4,0,0})
|
||||
|
||||
gettext.bindtextdomain("fujifilm_ratings", dt.configuration.config_dir.."/lua/locale/")
|
||||
|
||||
local function _(msgid)
|
||||
return gettext.dgettext("fujifilm_ratings", msgid)
|
||||
end
|
||||
|
||||
local function detect_rating(event, image)
|
||||
if not df.check_if_bin_exists("exiftool") then
|
||||
dt.print_error(_("exiftool not found"))
|
||||
return
|
||||
end
|
||||
local RAF_filename = tostring(image)
|
||||
local JPEG_filename = string.gsub(RAF_filename, "%.RAF$", ".JPG")
|
||||
local command = "exiftool -Rating " .. JPEG_filename
|
||||
dt.print_error(command)
|
||||
local output = io.popen(command)
|
||||
local jpeg_result = output:read("*all")
|
||||
output:close()
|
||||
if string.len(jpeg_result) > 0 then
|
||||
jpeg_result = string.gsub(jpeg_result, "^Rating.*(%d)", "%1")
|
||||
image.rating = tonumber(jpeg_result)
|
||||
dt.print_error(_("Using JPEG Rating: ") .. tostring(jpeg_result))
|
||||
return
|
||||
end
|
||||
command = "exiftool -Rating " .. RAF_filename
|
||||
dt.print_error(command)
|
||||
output = io.popen(command)
|
||||
local raf_result = output:read("*all")
|
||||
output:close()
|
||||
if string.len(raf_result) > 0 then
|
||||
raf_result = string.gsub(raf_result, "^Rating.*(%d)", "%1")
|
||||
image.rating = tonumber(raf_result)
|
||||
dt.print_error(_("Using RAF Rating: ") .. tostring(raf_result))
|
||||
end
|
||||
end
|
||||
|
||||
dt.register_event("post-import-image", detect_rating)
|
||||
|
||||
print(_("fujifilm_ratings loaded."))
|
||||
@@ -33,13 +33,14 @@ USAGE
|
||||
]]
|
||||
|
||||
local dt = require "darktable"
|
||||
local df = require "lib/dtutils.file"
|
||||
require "official/yield"
|
||||
|
||||
local gettext = dt.gettext
|
||||
dt.configuration.check_version(...,{3,0,0})
|
||||
|
||||
dt.configuration.check_version(...,{3,0,0},{4,0,0},{5,0,0})
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain("geoJSON_export",dt.configuration.config_dir.."/lua/")
|
||||
gettext.bindtextdomain("geoJSON_export",dt.configuration.config_dir.."/lua/locale/")
|
||||
|
||||
local function _(msgid)
|
||||
return gettext.dgettext("geoJSON_export", msgid)
|
||||
@@ -73,37 +74,27 @@ local function show_status(storage, image, format, filename, number, total, high
|
||||
dt.print(string.format(_("Export Image %i/%i"), number, total))
|
||||
end
|
||||
|
||||
local function checkIfBinExists(bin)
|
||||
local handle = io.popen("which "..bin)
|
||||
local result = handle:read()
|
||||
local ret
|
||||
handle:close()
|
||||
if (not result) then
|
||||
dt.print_error(bin.." not found")
|
||||
ret = false
|
||||
end
|
||||
ret = true
|
||||
return ret
|
||||
end
|
||||
|
||||
local function create_geoJSON_file(storage, image_table, extra_data)
|
||||
|
||||
if not checkIfBinExists("mkdir") then
|
||||
if not df.check_if_bin_exists("mkdir") then
|
||||
dt.print_error(_("mkdir not found"))
|
||||
return
|
||||
end
|
||||
if not checkIfBinExists("convert") then
|
||||
if not df.check_if_bin_exists("convert") then
|
||||
dt.print_error(_("convert not found"))
|
||||
return
|
||||
end
|
||||
if not checkIfBinExists("xdg-open") then
|
||||
if not df.check_if_bin_exists("xdg-open") then
|
||||
dt.print_error(_("xdg-open not found"))
|
||||
return
|
||||
end
|
||||
if not checkIfBinExists("xdg-user-dir") then
|
||||
if not df.check_if_bin_exists("xdg-user-dir") then
|
||||
dt.print_error(_("xdg-user-dir not found"))
|
||||
return
|
||||
end
|
||||
|
||||
dt.print_error("Will try to export geoJSON file now")
|
||||
|
||||
local xportDirectory = dt.preferences.read("geoJSON_export","ExportDirectory","string")
|
||||
local exportDirectory = dt.preferences.read("geoJSON_export","ExportDirectory","string")
|
||||
|
||||
-- Creates dir if not exsists
|
||||
local imageFoldername = "files/"
|
||||
@@ -115,8 +106,8 @@ local function create_geoJSON_file(storage, image_table, extra_data)
|
||||
if ((image.longitude and image.latitude) and
|
||||
(image.longitude ~= 0 and image.latitude ~= 90) -- Sometimes the north-pole but most likely just wrong data
|
||||
) then
|
||||
local path, filename, filetype = string.match(image, "(.-)([^\\/]-%.?([^%.\\/]*))$")
|
||||
filename = string.upper(string.gsub(filename,"%.", "_"))
|
||||
local path, filename, filetype = string.match(exported_image, "(.-)([^\\/]-%.?([^%.\\/]*))$")
|
||||
filename = string.upper(string.gsub(filename,"%.%w*", ""))
|
||||
|
||||
-- convert -size 92x92 filename.jpg -resize 92x92 +profile "*" thumbnail.jpg
|
||||
-- In this example, '-size 120x120' gives a hint to the JPEG decoder that the image is going to be downscaled to
|
||||
@@ -131,8 +122,8 @@ local function create_geoJSON_file(storage, image_table, extra_data)
|
||||
dt.control.execute( concertCommand)
|
||||
end
|
||||
|
||||
-- delete the original image to not get into the kmz file
|
||||
os.remove(image)
|
||||
-- delete the original image
|
||||
os.remove(exported_image)
|
||||
|
||||
local pattern = "[/]?([^/]+)$"
|
||||
filmName = string.match(image.film.path, pattern)
|
||||
@@ -149,11 +140,24 @@ local function create_geoJSON_file(storage, image_table, extra_data)
|
||||
]]
|
||||
|
||||
for image,exported_image in pairs(image_table) do
|
||||
filename = string.upper(string.gsub(image.filename,"%.", "_"))
|
||||
--filename = string.upper(string.gsub(image.filename,"%.", "_"))
|
||||
-- Extract filename, e.g DSC9784.ARW -> DSC9784
|
||||
filename = string.upper(string.gsub(image.filename,"%.%w*", ""))
|
||||
-- Extract extension from exported image (user can choose JPG or PNG), e.g DSC9784.JPG -> .JPG
|
||||
extension = string.match(exported_image,"%.%w*$")
|
||||
|
||||
if ((image.longitude and image.latitude) and
|
||||
(image.longitude ~= 0 and image.latitude ~= 90) -- Sometimes the north-pole but most likely just wrong data
|
||||
) then
|
||||
|
||||
local image_title, image_description
|
||||
if (image.title and image.title ~= "") then
|
||||
image_title = image.title
|
||||
else
|
||||
image_title = image.filename
|
||||
end
|
||||
image_description = image.description
|
||||
|
||||
geoJSON_file = geoJSON_file..
|
||||
[[ {
|
||||
"type": "Feature",
|
||||
@@ -164,8 +168,8 @@ local function create_geoJSON_file(storage, image_table, extra_data)
|
||||
geoJSON_file = geoJSON_file..
|
||||
[[ },
|
||||
"properties": {
|
||||
"title": "]]..image.title..[[",
|
||||
"description": "]]..image.description..[[",
|
||||
"title": "]]..image_title..[[",
|
||||
"description": "]]..image_description..[[",
|
||||
"image": "]]..imageFoldername..filename..[[.jpg",
|
||||
"icon": {
|
||||
"iconUrl": "]]..imageFoldername.."thumb_"..filename..[[.jpg",
|
||||
@@ -196,7 +200,7 @@ local function create_geoJSON_file(storage, image_table, extra_data)
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8 />
|
||||
<title>2014-05-31 Rieselfelder</title>
|
||||
<title>]]..filmName..[[</title>
|
||||
<script src='https://api.tiles.mapbox.com/mapbox.js/v2.2.4/mapbox.js'></script>
|
||||
<link href='https://api.tiles.mapbox.com/mapbox.js/v2.2.4/mapbox.css' rel='stylesheet' />
|
||||
<style>
|
||||
@@ -310,6 +314,9 @@ dt.preferences.register("geoJSON_export",
|
||||
local handle = io.popen("xdg-user-dir DESKTOP")
|
||||
local result = handle:read()
|
||||
handle:close()
|
||||
if (result == nil) then
|
||||
result = ""
|
||||
end
|
||||
dt.preferences.register("geoJSON_export",
|
||||
"ExportDirectory",
|
||||
"directory",
|
||||
|
||||
687
contrib/geoToolbox.lua
Normal file
687
contrib/geoToolbox.lua
Normal file
@@ -0,0 +1,687 @@
|
||||
--[[
|
||||
This file is part of darktable,
|
||||
copyright (c) 2016 Tobias Jakobs
|
||||
|
||||
darktable is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
darktable is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with darktable. If not, see <http://www.gnu.org/licenses/>.
|
||||
]]
|
||||
--[[
|
||||
|
||||
USAGE
|
||||
* require this script from your main lua file
|
||||
To do this add this line to the file .config/darktable/luarc:
|
||||
require "geoToolbox"
|
||||
|
||||
* it creates a new geoToolbox lighttable module
|
||||
]]
|
||||
|
||||
local dt = require "darktable"
|
||||
local df = require "lib/dtutils.file"
|
||||
require "official/yield"
|
||||
local gettext = dt.gettext
|
||||
|
||||
dt.configuration.check_version(...,{3,0,0},{4,0,0},{5,0,0})
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain("geoToolbox",dt.configuration.config_dir.."/lua/locale/")
|
||||
|
||||
local function _(msgid)
|
||||
return gettext.dgettext("geoToolbox", msgid)
|
||||
end
|
||||
|
||||
-- <GUI>
|
||||
local labelDistance = dt.new_widget("label")
|
||||
labelDistance.label = _("Distance:")
|
||||
|
||||
local label_copy_gps_lat = dt.new_widget("check_button")
|
||||
{
|
||||
label = _("latitude:"),
|
||||
value = true
|
||||
}
|
||||
local label_copy_gps_lon = dt.new_widget("check_button")
|
||||
{
|
||||
label = _("longitude:"),
|
||||
value = true
|
||||
}
|
||||
local label_copy_gps_ele = dt.new_widget("check_button")
|
||||
{
|
||||
label = _("elevation:"),
|
||||
value = true
|
||||
}
|
||||
-- </GUI>
|
||||
|
||||
local function select_with_gps()
|
||||
local selection = {}
|
||||
job = dt.gui.create_job(_("GPS selection"), true, stop_selection)
|
||||
|
||||
for key,image in ipairs(dt.collection) do
|
||||
if job.valid then
|
||||
job.percent = (key-1)/#dt.collection
|
||||
|
||||
if (image.longitude and image.latitude) then
|
||||
table.insert(selection,image)
|
||||
end
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
dt.gui.selection(selection)
|
||||
job.valid = false
|
||||
end
|
||||
|
||||
local function select_without_gps()
|
||||
local selection = {}
|
||||
job = dt.gui.create_job(_("GPS selection"), true, stop_selection)
|
||||
|
||||
for key,image in ipairs(dt.collection) do
|
||||
if job.valid then
|
||||
job.percent = (key-1)/#dt.collection
|
||||
|
||||
if (not image.longitude and not image.latitude) then
|
||||
table.insert(selection,image)
|
||||
end
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
dt.gui.selection(selection)
|
||||
job.valid = false
|
||||
end
|
||||
|
||||
local function stop_selection(job)
|
||||
job.valid = false
|
||||
end
|
||||
|
||||
-- This is used for older images in the DB
|
||||
function isnan(x) return x ~= x end
|
||||
|
||||
-- Function from:
|
||||
-- https://forums.coronalabs.com/topic/29019-convert-string-to-date/
|
||||
-- This looks much scarier than it really is. The goal is to turn that string
|
||||
-- into a Unix timestamp (number of seconds since Jan 1, 1970, the standard
|
||||
-- used by most systems). So we use the string.match() method to fetch the
|
||||
-- various date and time parts into their own variables: xyear, xmonth,etc.
|
||||
function make_time_stamp(dateString)
|
||||
local convertedTimestamp
|
||||
--dt.print_error(dateString)
|
||||
if (dateString) then
|
||||
local pattern = "(%d+)%:(%d+)%:(%d+) (%d+):(%d+):(%d+)"
|
||||
local xyear, xmonth, xday, xhour, xminute, xseconds = dateString:match(pattern)
|
||||
--dt.print_error(xyear)
|
||||
convertedTimestamp = os.time({
|
||||
year = xyear,
|
||||
month = xmonth,
|
||||
day = xday,
|
||||
hour = xhour,
|
||||
min = xminute,
|
||||
sec = xseconds})
|
||||
else
|
||||
convertedTimestamp = 0
|
||||
end
|
||||
|
||||
return convertedTimestamp
|
||||
end
|
||||
|
||||
local first_have_data = false
|
||||
local first_latitude = ''
|
||||
local first_longitude = ''
|
||||
local first_elevation = ''
|
||||
local first_image_date = 0
|
||||
|
||||
local function get_first_coordinate()
|
||||
local sel_images = dt.gui.action_images
|
||||
|
||||
first_latitude = ''
|
||||
first_longitude = ''
|
||||
first_elevation = ''
|
||||
first_image_date = 0
|
||||
|
||||
for _,image in ipairs(sel_images) do
|
||||
if not image then
|
||||
first_have_data = false
|
||||
else
|
||||
image_date = image.exif_datetime_taken
|
||||
first_have_data = true
|
||||
if (image.latitude) then
|
||||
first_latitude = image.latitude
|
||||
end
|
||||
if (image.longitude) then
|
||||
first_longitude = image.longitude
|
||||
end
|
||||
if (image.elevation) then
|
||||
first_elevation = image.elevation
|
||||
end
|
||||
if (image.exif_datetime_taken) then
|
||||
first_image_date = make_time_stamp(image.exif_datetime_taken)
|
||||
--dt.print_error(image.exif_datetime_taken)
|
||||
--dt.print_error(first_image_date)
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local second_have_data = false
|
||||
local second_latitude = ''
|
||||
local second_longitude = ''
|
||||
local second_elevation = ''
|
||||
local second_image_date = 0
|
||||
|
||||
local function get_second_coordinate()
|
||||
local sel_images = dt.gui.action_images
|
||||
|
||||
second_latitude = ''
|
||||
second_longitude = ''
|
||||
second_elevation = ''
|
||||
second_image_date = 0
|
||||
|
||||
for _,image in ipairs(sel_images) do
|
||||
if not image then
|
||||
second_have_data = false
|
||||
else
|
||||
image_date = image.exif_datetime_taken
|
||||
second_have_data = true
|
||||
if (image.latitude) then
|
||||
second_latitude = image.latitude
|
||||
end
|
||||
if (image.longitude) then
|
||||
second_longitude = image.longitude
|
||||
end
|
||||
if (image.elevation) then
|
||||
second_elevation = image.elevation
|
||||
end
|
||||
if (image.exif_datetime_taken) then
|
||||
second_image_date = make_time_stamp(image.exif_datetime_taken)
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local calc_in_between_slider = dt.new_widget("slider")
|
||||
{
|
||||
label = "Position between",
|
||||
soft_min = 0, -- The soft minimum value for the slider, the slider can't go beyond this point
|
||||
soft_max = 100, -- The soft maximum value for the slider, the slider can't go beyond this point
|
||||
hard_min = -100, -- The hard minimum value for the slider, the user can't manually enter a value beyond this point
|
||||
hard_max = 200, -- The hard maximum value for the slider, the user can't manually enter a value beyond this point
|
||||
value = 50 -- The current value of the slider
|
||||
}
|
||||
|
||||
--ToDo: this needs more love
|
||||
local function calc_in_between()
|
||||
local sel_images = dt.gui.action_images
|
||||
for _,image in ipairs(sel_images) do
|
||||
if image then
|
||||
image_date = make_time_stamp(image.exif_datetime_taken)
|
||||
if (first_have_data and second_have_data) then
|
||||
local start_new = 0
|
||||
local end_new = second_image_date - first_image_date
|
||||
local image_date_new = image_date - first_image_date
|
||||
|
||||
local percent_in_between
|
||||
if (end_new == 0) then
|
||||
percent_in_between = 1
|
||||
else
|
||||
percent_in_between = image_date_new/end_new
|
||||
end
|
||||
calc_in_between_slider.value = percent_in_between * 100
|
||||
dt.print_error(percent_in_between)
|
||||
local in_between_latitude = first_latitude + (second_latitude - first_latitude) * percent_in_between
|
||||
local in_between_longitude = first_longitude + (second_longitude - first_longitude) * percent_in_between
|
||||
|
||||
if (first_elevation and second_elevation) then
|
||||
local in_between_elevation = first_elevation + (second_elevation - first_elevation) * percent_in_between
|
||||
|
||||
dt.print_error(first_image_date)
|
||||
dt.print_error(second_image_date)
|
||||
dt.print_error(image_date)
|
||||
dt.print_error(first_elevation)
|
||||
dt.print_error(second_elevation)
|
||||
dt.print_error(in_between_elevation)
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local copy_gps_have_data = false
|
||||
local copy_gps_latitude = ''
|
||||
local copy_gps_longitude = ''
|
||||
local copy_gps_elevation = ''
|
||||
|
||||
local function copy_gps()
|
||||
local sel_images = dt.gui.action_images
|
||||
|
||||
copy_gps_latitude = ''
|
||||
copy_gps_longitude = ''
|
||||
copy_gps_elevation = ''
|
||||
|
||||
for _,image in ipairs(sel_images) do
|
||||
if not image then
|
||||
copy_gps_have_data = false
|
||||
else
|
||||
copy_gps_have_data = true
|
||||
if (image.latitude and label_copy_gps_lat.value) then
|
||||
copy_gps_latitude = image.latitude
|
||||
end
|
||||
if (image.longitude and label_copy_gps_lon.value) then
|
||||
copy_gps_longitude = image.longitude
|
||||
end
|
||||
if (image.elevation and label_copy_gps_ele.value) then
|
||||
copy_gps_elevation = image.elevation
|
||||
end
|
||||
end
|
||||
|
||||
label_copy_gps_lat.label = _("latitude: ") .. copy_gps_latitude
|
||||
label_copy_gps_lon.label = _("longitude: ") ..copy_gps_longitude
|
||||
label_copy_gps_ele.label = _("elevation: ") .. copy_gps_elevation
|
||||
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local function paste_gps(image)
|
||||
local sel_images = dt.gui.action_images
|
||||
|
||||
for _,image in ipairs(sel_images) do
|
||||
if (label_copy_gps_lat.value) then
|
||||
image.latitude = copy_gps_latitude
|
||||
end
|
||||
if (label_copy_gps_lon.value) then
|
||||
image.longitude = copy_gps_longitude
|
||||
end
|
||||
if (label_copy_gps_ele.value) then
|
||||
image.elevation = copy_gps_elevation
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function open_location_in_gnome_maps()
|
||||
|
||||
if not df.check_if_bin_exists("gnome-maps") then
|
||||
dt.print_error(_("gnome-maps not found"))
|
||||
return
|
||||
end
|
||||
|
||||
local sel_images = dt.gui.action_images
|
||||
|
||||
local lat1 = 0;
|
||||
local lon1 = 0;
|
||||
local i = 0;
|
||||
|
||||
-- Use the first image with geo information
|
||||
for _,image in ipairs(sel_images) do
|
||||
if ((image.longitude and image.latitude) and
|
||||
(image.longitude ~= 0 and image.latitude ~= 90) -- Sometimes the north-pole but most likely just wrong data
|
||||
) then
|
||||
lat1 = string.gsub(image.latitude, ",", ".");
|
||||
lon1 = string.gsub(image.longitude, ",", ".");
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
local startCommand
|
||||
startCommand = "gnome-maps \"geo:" .. lat1 .. "," .. lon1 .."\""
|
||||
dt.print_error(startCommand)
|
||||
|
||||
dt.control.execute(startCommand)
|
||||
|
||||
end
|
||||
|
||||
-- Trim Funktion from: http://lua-users.org/wiki/StringTrim
|
||||
local function trim12(s)
|
||||
local from = s:match"^%s*()"
|
||||
return from > #s and "" or s:match(".*%S", from)
|
||||
end
|
||||
|
||||
local function reverse_geocode()
|
||||
|
||||
if not df.check_if_bin_exists("curl") then
|
||||
dt.print_error(_("curl not found"))
|
||||
return
|
||||
end
|
||||
|
||||
if not df.check_if_bin_exists("jq") then
|
||||
dt.print_error(_("jq not found"))
|
||||
return
|
||||
end
|
||||
|
||||
local sel_images = dt.gui.selection() --action_images
|
||||
|
||||
local lat1 = 0;
|
||||
local lon1 = 0;
|
||||
local i = 0;
|
||||
|
||||
-- Use the first image with geo information
|
||||
for _,image in ipairs(sel_images) do
|
||||
if ((image.longitude and image.latitude) and
|
||||
(image.longitude ~= 0 and image.latitude ~= 90) -- Sometimes the north-pole but most likely just wrong data
|
||||
) then
|
||||
lat1 = string.gsub(image.latitude, ",", ".");
|
||||
lon1 = string.gsub(image.longitude, ",", ".");
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
local startCommand
|
||||
|
||||
local tokan = dt.preferences.read("geoToolbox","mapBoxKey","string")
|
||||
local types = "country";
|
||||
local types = "region";
|
||||
local types = "place";
|
||||
local types = "poi";
|
||||
|
||||
-- MapBox documentation
|
||||
-- https://www.mapbox.com/api-documentation/#retrieve-places-near-a-location
|
||||
-- curl -s, --silent Silent mode (don't output anything)
|
||||
-- jq could be replaced with a Lua JSON parser
|
||||
startCommand = string.format("curl --silent \"https://api.mapbox.com/geocoding/v5/mapbox.places/%s,%s.json?types=%s&access_token=%s\" | jq '.features | .[0] | '.text''", lon1, lat1, types, tokan)
|
||||
|
||||
local handle = io.popen(startCommand)
|
||||
local result = trim12(handle:read("*a"))
|
||||
handle:close()
|
||||
|
||||
-- Errorhandling would be nice
|
||||
--dt.print_error("startCommand: "..startCommand)
|
||||
--dt.print_error("result: '"..result.."'")
|
||||
|
||||
if (result ~= "null") then
|
||||
dt.print(string.sub(result, 2, string.len(result)-2))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- I used code from here:
|
||||
-- http://stackoverflow.com/questions/27928/how-do-i-calculate-distance-between-two-latitude-longitude-points
|
||||
local function get_distance(lat1, lon1, ele1, lat2, lon2, ele2)
|
||||
|
||||
local earthRadius = 6371; -- Radius of the earth in km
|
||||
local dLat = math.rad(lat2-lat1); -- deg2rad below
|
||||
local dLon = math.rad(lon2-lon1);
|
||||
local a =
|
||||
math.sin(dLat/2) * math.sin(dLat/2) +
|
||||
math.cos(math.rad(lat1)) * math.cos(math.rad(lat2)) *
|
||||
math.sin(dLon/2) * math.sin(dLon/2)
|
||||
;
|
||||
local angle = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a));
|
||||
local distance = earthRadius * angle; -- Distance in km
|
||||
|
||||
-- Add the elevation to the calculation
|
||||
local elevation = 0
|
||||
elevation = math.abs(ele1 - ele2) / 1000; --in km
|
||||
|
||||
if (elevation > 0) then
|
||||
distance = math.sqrt(math.pow(elevation,2) + math.pow(distance,2) )
|
||||
end
|
||||
return distance
|
||||
end
|
||||
|
||||
local function calc_distance()
|
||||
|
||||
local lat1 = 0;
|
||||
local lon1 = 0;
|
||||
local lat2 = 0;
|
||||
local lon2 = 0;
|
||||
local ele1 = 0;
|
||||
local ele2 = 0;
|
||||
local i = 0;
|
||||
|
||||
local sel_images = dt.gui.selection()
|
||||
|
||||
for _,image in ipairs(sel_images) do
|
||||
if ((image.longitude and image.latitude) and
|
||||
(image.longitude ~= 0 and image.latitude ~= 90) -- Sometimes the north-pole but most likely just wrong data
|
||||
) then
|
||||
|
||||
i = i + 1;
|
||||
|
||||
if (i == 1) then
|
||||
lat1 = image.latitude
|
||||
lon1 = image.longitude
|
||||
if (image.elevation) then
|
||||
ele1 = image.elevation
|
||||
else
|
||||
ele1 = 0
|
||||
end
|
||||
end
|
||||
|
||||
lat2 = image.latitude
|
||||
lon2 = image.longitude
|
||||
if (image.elevation) then
|
||||
ele2 = image.elevation
|
||||
else
|
||||
ele2 = 0;
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
local distance = get_distance(lat1, lon1, ele1, lat2, lon2, ele2)
|
||||
|
||||
if (distance < 1) then
|
||||
distance = distance * 1000
|
||||
distanceUnit = _("m")
|
||||
else
|
||||
distanceUnit = _("km")
|
||||
end
|
||||
|
||||
return string.format(_("Distance: %.2f %s"), distance, distanceUnit)
|
||||
end
|
||||
|
||||
local function print_calc_distance()
|
||||
dt.print(calc_distance())
|
||||
end
|
||||
|
||||
local function toolbox_calc_distance()
|
||||
labelDistance.label = calc_distance()
|
||||
end
|
||||
|
||||
local altitude_file_chooser_button = dt.new_widget("file_chooser_button")
|
||||
{
|
||||
title = _("export altitude CSV"), -- The title of the window when choosing a file
|
||||
value = "", -- The currently selected file
|
||||
is_directory = true -- True if the file chooser button only allows directories to be selecte
|
||||
}
|
||||
|
||||
local altitude_filename = dt.new_widget("entry")
|
||||
{
|
||||
text = "altitude.csv",
|
||||
placeholder = "altitude.csv",
|
||||
editable = true,
|
||||
tooltip = _("Name of the exported file"),
|
||||
reset_callback = function(self) self.text = "text" end
|
||||
}
|
||||
|
||||
local function altitude_profile()
|
||||
dt.print(_("Start export"))
|
||||
local sel_images = dt.gui.action_images
|
||||
|
||||
local lat1 = 0;
|
||||
local lon1 = 0;
|
||||
local lat2 = 0;
|
||||
local lon2 = 0;
|
||||
local ele1 = 0;
|
||||
local ele2 = 0;
|
||||
local i = 0;
|
||||
local csv_file = '';
|
||||
csv_file = "km;m".."\n";
|
||||
|
||||
local distance = 0;
|
||||
local distanceFromStart = 0;
|
||||
local elevation = 0;
|
||||
local elevationAdd = 0;
|
||||
|
||||
local sel_images = dt.gui.action_images
|
||||
for _,image in ipairs(sel_images) do
|
||||
if ((not isnan(image.longitude) and not isnan(image.latitude) and not isnan(image.elevation) and image.elevation) and
|
||||
(image.longitude ~= 0 and image.latitude ~= 90) -- Sometimes the north-pole but most likely just wrong data
|
||||
) then
|
||||
|
||||
i = i + 1;
|
||||
|
||||
if (i == 1) then
|
||||
lat1 = image.latitude
|
||||
lon1 = image.longitude
|
||||
ele1 = image.elevation
|
||||
else
|
||||
lat1 = lat2
|
||||
lon1 = lon2
|
||||
ele1 = ele2
|
||||
end
|
||||
|
||||
lat2 = image.latitude
|
||||
lon2 = image.longitude
|
||||
ele2 = image.elevation
|
||||
|
||||
if (i == 1) then
|
||||
distanceFromStart = 0
|
||||
else
|
||||
local distance = get_distance(lat1, lon1, ele1, lat2, lon2, ele2)
|
||||
distanceFromStart = distanceFromStart + distance;
|
||||
end
|
||||
|
||||
csv_file = csv_file .. distanceFromStart..";"..image.elevation.."\n";
|
||||
|
||||
end
|
||||
|
||||
end --for
|
||||
|
||||
local exportDirectory = altitude_file_chooser_button.value
|
||||
local exportFilename = altitude_filename.text
|
||||
if (exportFilename == '') then
|
||||
exportFilename = altitude_filename.placeholder
|
||||
end
|
||||
file = io.open(exportDirectory.."/"..exportFilename, "w")
|
||||
file:write(csv_file)
|
||||
file:close()
|
||||
dt.print(_("File created in ")..exportDirectory)
|
||||
|
||||
end
|
||||
|
||||
|
||||
local separator = dt.new_widget("separator"){}
|
||||
local separator2 = dt.new_widget("separator"){}
|
||||
local separator3 = dt.new_widget("separator"){}
|
||||
local separator4 = dt.new_widget("separator"){}
|
||||
local separator5 = dt.new_widget("separator"){}
|
||||
|
||||
dt.register_lib(
|
||||
"geoToolbox", -- Module name
|
||||
"geo toolbox", -- name
|
||||
true, -- expandable
|
||||
false, -- resetable
|
||||
{[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, -- containers
|
||||
dt.new_widget("box")
|
||||
{
|
||||
orientation = "vertical",
|
||||
dt.new_widget("button")
|
||||
{
|
||||
label = _("select geo images"),
|
||||
tooltip = _("Select all images with GPS information"),
|
||||
clicked_callback = select_with_gps
|
||||
},
|
||||
dt.new_widget("button")
|
||||
{
|
||||
label = _("select non-geo images"),
|
||||
tooltip = _("Select all images without GPS information"),
|
||||
clicked_callback = select_without_gps
|
||||
},
|
||||
separator,--------------------------------------------------------
|
||||
dt.new_widget("button")
|
||||
{
|
||||
label = _("copy GPS data"),
|
||||
tooltip = _("Copy GPS data"),
|
||||
clicked_callback = copy_gps
|
||||
},
|
||||
label_copy_gps_lat,
|
||||
label_copy_gps_lon,
|
||||
label_copy_gps_ele,
|
||||
dt.new_widget("button")
|
||||
{
|
||||
label = _("paste GPS data"),
|
||||
tooltip = _("Paste GPS data"),
|
||||
clicked_callback = paste_gps
|
||||
},
|
||||
separator2,--------------------------------------------------------
|
||||
--ToDo: This need a better UI
|
||||
--[[
|
||||
dt.new_widget("button")
|
||||
{
|
||||
label = "get 1st coordinate",
|
||||
tooltip = "Select first image and click this button",
|
||||
clicked_callback = get_first_coordinate
|
||||
},
|
||||
dt.new_widget("button")
|
||||
{
|
||||
label = "get 2nd coordinate",
|
||||
tooltip = "Select second image and click this button",
|
||||
clicked_callback = get_second_coordinate
|
||||
},
|
||||
dt.new_widget("button")
|
||||
{
|
||||
label = "calc in between",
|
||||
tooltip = "Select third image and click this button",
|
||||
clicked_callback = calc_in_between
|
||||
},
|
||||
calc_in_between_slider,
|
||||
separator3,--------------------------------------------------------
|
||||
]]
|
||||
dt.new_widget("button")
|
||||
{
|
||||
label = _("open in Gnome Maps"),
|
||||
tooltip = _("Open location in Gnome Maps"),
|
||||
clicked_callback = open_location_in_gnome_maps
|
||||
},
|
||||
separator4,--------------------------------------------------------
|
||||
dt.new_widget("button")
|
||||
{
|
||||
label = _("reverse geocode"),
|
||||
tooltip = _("This just shows the name of the location, but doesn't add it as tag"),
|
||||
clicked_callback = reverse_geocode
|
||||
},
|
||||
separator5,--------------------------------------------------------
|
||||
dt.new_widget("label"){label = _("altitude CSV export")},
|
||||
altitude_file_chooser_button,
|
||||
altitude_filename,
|
||||
dt.new_widget("button")
|
||||
{
|
||||
label = _("export altitude CSV file"),
|
||||
tooltip = _("Create an altitude profile using the GPS data in the metadata"),
|
||||
clicked_callback = altitude_profile
|
||||
},
|
||||
labelDistance
|
||||
},
|
||||
nil,-- view_enter
|
||||
nil -- view_leave
|
||||
)
|
||||
|
||||
-- Preferences
|
||||
dt.preferences.register("geoToolbox",
|
||||
"mapBoxKey",
|
||||
"string",
|
||||
_("geoToolbox export: MapBox Key"),
|
||||
_("https://www.mapbox.com/studio/account/tokens"),
|
||||
'' )
|
||||
|
||||
-- Register
|
||||
dt.register_event("shortcut", print_calc_distance, _("Calculate the distance from latitude and longitude in km"))
|
||||
dt.register_event("mouse-over-image-changed", toolbox_calc_distance)
|
||||
|
||||
dt.register_event("shortcut", select_with_gps, _("Select all images with GPS information"))
|
||||
dt.register_event("shortcut", select_without_gps, _("Select all images without GPS information"))
|
||||
|
||||
-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua
|
||||
-- kate: hl Lua;
|
||||
@@ -1,89 +0,0 @@
|
||||
--[[
|
||||
This file is part of darktable,
|
||||
Copyright 2016 by Tobias Jakobs.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
]]
|
||||
--[[
|
||||
darktable script to open a geo uri in gnome-maps
|
||||
|
||||
ADDITIANAL SOFTWARE NEEDED FOR THIS SCRIPT
|
||||
* gnome-maps >= 3.20
|
||||
|
||||
USAGE
|
||||
* require this script from your main lua file
|
||||
* register a shortcut
|
||||
]]
|
||||
|
||||
local dt = require "darktable"
|
||||
require "official/yield"
|
||||
|
||||
local gettext = dt.gettext
|
||||
dt.configuration.check_version(...,{3,0,0})
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain("geo_uri",dt.configuration.config_dir.."/lua/")
|
||||
|
||||
local function _(msgid)
|
||||
return gettext.dgettext("geo_uri", msgid)
|
||||
end
|
||||
|
||||
local function checkIfBinExists(bin)
|
||||
local handle = io.popen("which "..bin)
|
||||
local result = handle:read()
|
||||
local ret
|
||||
handle:close()
|
||||
if (not result) then
|
||||
dt.print_error(bin.." not found")
|
||||
ret = false
|
||||
end
|
||||
ret = true
|
||||
return ret
|
||||
end
|
||||
|
||||
local function openLocationInGnomeMaps()
|
||||
if not checkIfBinExists("gnome-maps") then
|
||||
dt.print_error(_("gnome-maps not found"))
|
||||
return
|
||||
end
|
||||
|
||||
local sel_images = dt.gui.selection()
|
||||
|
||||
local lat1 = 0;
|
||||
local lon1 = 0;
|
||||
local i = 0;
|
||||
|
||||
-- Use the first image with geo information
|
||||
for _,image in ipairs(sel_images) do
|
||||
if ((image.longitude and image.latitude) and
|
||||
(image.longitude ~= 0 and image.latitude ~= 90) -- Sometimes the north-pole but most likely just wrong data
|
||||
) then
|
||||
lat1 = image.latitude;
|
||||
lon1 = image.longitude;
|
||||
break
|
||||
end
|
||||
|
||||
local startCommand
|
||||
startCommand = "gnome-maps \"geo:" .. lat1 .. "," .. lon1 .."\""
|
||||
dt.print_error(startCommand)
|
||||
|
||||
if dt.control.execute( startCommand) then
|
||||
dt.print(_("Command failed ..."))
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
-- Register
|
||||
dt.register_event("shortcut", openLocationInGnomeMaps, _("Open Location in Gnome Maps"))
|
||||
@@ -64,14 +64,14 @@
|
||||
]]
|
||||
|
||||
local dt = require "darktable"
|
||||
local df = require "lib/dtutils.file"
|
||||
require "official/yield"
|
||||
|
||||
local gettext = dt.gettext
|
||||
|
||||
dt.configuration.check_version(...,{3,0,0})
|
||||
dt.configuration.check_version(...,{3,0,0},{4,0,0},{5,0,0})
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain("gimp",dt.configuration.config_dir.."/lua/")
|
||||
gettext.bindtextdomain("gimp",dt.configuration.config_dir.."/lua/locale/")
|
||||
|
||||
local function split_filepath(str)
|
||||
local result = {}
|
||||
@@ -104,21 +104,6 @@ local function _(msgid)
|
||||
return gettext.dgettext("gimp", msgid)
|
||||
end
|
||||
|
||||
local function checkIfBinExists(bin)
|
||||
local handle = io.popen("which "..bin)
|
||||
local result = handle:read()
|
||||
local ret
|
||||
handle:close()
|
||||
if (result) then
|
||||
dt.print_error("true checkIfBinExists: "..bin)
|
||||
ret = true
|
||||
else
|
||||
dt.print_error(bin.." not found")
|
||||
ret = false
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
-- Thanks Tobias Jakobs for the idea and the correction
|
||||
function checkIfFileExists(filepath)
|
||||
local file = io.open(filepath,"r")
|
||||
@@ -199,7 +184,7 @@ end
|
||||
local function fileCopy(fromFile, toFile)
|
||||
local result = nil
|
||||
-- if cp exists, use it
|
||||
if checkIfBinExists("cp") then
|
||||
if df.check_if_bin_exists("cp") then
|
||||
result = os.execute("cp '" .. fromFile .. "' '" .. toFile .. "'")
|
||||
end
|
||||
-- if cp was not present, or if cp failed, then a pure lua solution
|
||||
@@ -230,7 +215,7 @@ local function fileMove(fromFile, toFile)
|
||||
local success = os.rename(fromFile, toFile)
|
||||
if not success then
|
||||
-- an error occurred, so let's try using the operating system function
|
||||
if checkIfBinExists("mv") then
|
||||
if df.check_if_bin_exists("mv") then
|
||||
success = os.execute("mv '" .. fromFile .. "' '" .. toFile .. "'")
|
||||
end
|
||||
-- if the mv didn't exist or succeed, then...
|
||||
@@ -249,7 +234,7 @@ local function fileMove(fromFile, toFile)
|
||||
end
|
||||
|
||||
local function gimp_edit(storage, image_table, extra_data) --finalize
|
||||
if not checkIfBinExists("gimp") then
|
||||
if not df.check_if_bin_exists("gimp") then
|
||||
dt.print_error(_("GIMP not found"))
|
||||
return
|
||||
end
|
||||
@@ -315,5 +300,3 @@ end
|
||||
dt.register_storage("module_gimp", _("Edit with GIMP"), show_status, gimp_edit)
|
||||
|
||||
--
|
||||
|
||||
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
--[[
|
||||
This file is part of darktable,
|
||||
Copyright 2014 by Tobias Jakobs.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
]]
|
||||
--[[
|
||||
darktable select images with or without GPS informations
|
||||
|
||||
USAGE
|
||||
* require this script from your main lua file
|
||||
* register a shortcuts
|
||||
]]
|
||||
|
||||
local dt = require "darktable"
|
||||
local gettext = dt.gettext
|
||||
dt.configuration.check_version(...,{2,0,1},{3,0,0})
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain("gps_select",dt.configuration.config_dir.."/lua/")
|
||||
|
||||
local function _(msgid)
|
||||
return gettext.dgettext("gps_select", msgid)
|
||||
end
|
||||
|
||||
table = require "table"
|
||||
|
||||
local function selectWithGPS()
|
||||
local selection = {}
|
||||
for _,image in ipairs(dt.database) do
|
||||
if (image.longitude and image.latitude) then
|
||||
table.insert(selection,image)
|
||||
end
|
||||
end
|
||||
dt.gui.selection(selection)
|
||||
end
|
||||
|
||||
local function selectWithoutGPS()
|
||||
local selection = {}
|
||||
for _,image in ipairs(dt.database) do
|
||||
if (not image.longitude and not image.latitude) then
|
||||
table.insert(selection,image)
|
||||
end
|
||||
end
|
||||
dt.gui.selection(selection)
|
||||
end
|
||||
|
||||
dt.register_event("shortcut", selectWithGPS, _("Select all images with GPS information"))
|
||||
dt.register_event("shortcut", selectWithoutGPS, _("Select all images without GPS information"))
|
||||
@@ -34,44 +34,27 @@ This plugin will add a new storage option and calls hugin after export.
|
||||
]]
|
||||
|
||||
local dt = require "darktable"
|
||||
local df = require "lib/dtutils.file"
|
||||
require "official/yield"
|
||||
|
||||
local gettext = dt.gettext
|
||||
|
||||
-- works with darktable API version 2.0.0 and 3.0.0
|
||||
dt.configuration.check_version(...,{2,0,0},{3,0,0})
|
||||
-- works with darktable API version from 2.0.0 to 5.0.0
|
||||
dt.configuration.check_version(...,{2,0,0},{3,0,0},{4,0,0},{5,0,0})
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain("hugin",dt.configuration.config_dir.."/lua/")
|
||||
gettext.bindtextdomain("hugin",dt.configuration.config_dir.."/lua/locale/")
|
||||
|
||||
local function _(msgid)
|
||||
return gettext.dgettext("hugin", msgid)
|
||||
end
|
||||
|
||||
local function checkIfBinExists(bin)
|
||||
local handle = io.popen("which "..bin)
|
||||
local result = handle:read()
|
||||
local ret
|
||||
handle:close()
|
||||
if (result) then
|
||||
dt.print_error("true checkIfBinExists: "..bin)
|
||||
ret = true
|
||||
else
|
||||
dt.print_error(bin.." not found")
|
||||
ret = false
|
||||
end
|
||||
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
local function show_status(storage, image, format, filename,
|
||||
number, total, high_quality, extra_data)
|
||||
dt.print("Export to Hugin "..tostring(number).."/"..tostring(total))
|
||||
end
|
||||
|
||||
local function create_panorama(storage, image_table, extra_data) --finalize
|
||||
if not checkIfBinExists("hugin") then
|
||||
if not df.check_if_bin_exists("hugin") then
|
||||
dt.print_error(_("hugin not found"))
|
||||
return
|
||||
end
|
||||
@@ -82,7 +65,7 @@ local function create_panorama(storage, image_table, extra_data) --finalize
|
||||
-- http://hugin.sourceforge.net/docs/manual/Pto_gen.html
|
||||
|
||||
local hugin_executor = false
|
||||
if (checkIfBinExists("hugin_executor") and checkIfBinExists("pto_gen")) then
|
||||
if (df.check_if_bin_exists("hugin_executor") and df.check_if_bin_exists("pto_gen")) then
|
||||
hugin_executor = true
|
||||
end
|
||||
|
||||
@@ -115,7 +98,7 @@ local function create_panorama(storage, image_table, extra_data) --finalize
|
||||
|
||||
dt.print_error(huginStartCommand)
|
||||
|
||||
if dt.control.execute( huginStartCommand)
|
||||
if not dt.control.execute(huginStartCommand)
|
||||
then
|
||||
dt.print(_("Command hugin failed ..."))
|
||||
end
|
||||
|
||||
@@ -37,13 +37,14 @@ USAGE
|
||||
]]
|
||||
|
||||
local dt = require "darktable"
|
||||
local df = require "lib/dtutils.file"
|
||||
require "official/yield"
|
||||
|
||||
local gettext = dt.gettext
|
||||
dt.configuration.check_version(...,{3,0,0})
|
||||
|
||||
dt.configuration.check_version(...,{3,0,0},{4,0,0},{5,0,0})
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain("kml_export",dt.configuration.config_dir.."/lua/")
|
||||
gettext.bindtextdomain("kml_export",dt.configuration.config_dir.."/lua/locale/")
|
||||
|
||||
local function _(msgid)
|
||||
return gettext.dgettext("kml_export", msgid)
|
||||
@@ -77,19 +78,6 @@ local function show_status(storage, image, format, filename, number, total, high
|
||||
dt.print(string.format(_("Export Image %i/%i"), number, total))
|
||||
end
|
||||
|
||||
local function checkIfBinExists(bin)
|
||||
local handle = io.popen("which "..bin)
|
||||
local result = handle:read()
|
||||
local ret
|
||||
handle:close()
|
||||
if (not result) then
|
||||
dt.print_error(bin.." not found")
|
||||
ret = false
|
||||
end
|
||||
ret = true
|
||||
return ret
|
||||
end
|
||||
|
||||
-- Strip accents from a string
|
||||
-- Copied from https://forums.coronalabs.com/topic/43048-remove-special-characters-from-string/
|
||||
function string.stripAccents( str )
|
||||
@@ -175,17 +163,20 @@ function string.escapeXmlCharacters( str )
|
||||
end
|
||||
|
||||
local function create_kml_file(storage, image_table, extra_data)
|
||||
|
||||
if not checkIfBinExists("mkdir") then
|
||||
if not df.check_if_bin_exists("mkdir") then
|
||||
dt.print_error(_("mkdir not found"))
|
||||
return
|
||||
end
|
||||
if not checkIfBinExists("convert") then
|
||||
if not df.check_if_bin_exists("convert") then
|
||||
dt.print_error(_("convert not found"))
|
||||
return
|
||||
end
|
||||
if not checkIfBinExists("xdg-open") then
|
||||
if not df.check_if_bin_exists("xdg-open") then
|
||||
dt.print_error(_("xdg-open not found"))
|
||||
return
|
||||
end
|
||||
if not checkIfBinExists("xdg-user-dir") then
|
||||
if not df.check_if_bin_exists("xdg-user-dir") then
|
||||
dt.print_error(_("xdg-user-dir not found"))
|
||||
return
|
||||
end
|
||||
|
||||
@@ -193,7 +184,8 @@ local function create_kml_file(storage, image_table, extra_data)
|
||||
|
||||
local imageFoldername
|
||||
if ( dt.preferences.read("kml_export","CreateKMZ","bool") == true ) then
|
||||
if not checkIfBinExists("zip") then
|
||||
if not df.check_if_bin_exists("zip") then
|
||||
dt.print_error(_("zip not found"))
|
||||
return
|
||||
end
|
||||
|
||||
@@ -387,6 +379,9 @@ dt.preferences.register("kml_export",
|
||||
|
||||
local handle = io.popen("xdg-user-dir DESKTOP")
|
||||
local result = handle:read()
|
||||
if (result == nil) then
|
||||
result = ""
|
||||
end
|
||||
handle:close()
|
||||
dt.preferences.register("kml_export",
|
||||
"ExportDirectory",
|
||||
|
||||
94
contrib/passport_guide.lua
Normal file
94
contrib/passport_guide.lua
Normal file
@@ -0,0 +1,94 @@
|
||||
--[[
|
||||
Passport cropping guide for darktable
|
||||
|
||||
copyright (c) 2017 Kåre Hampf
|
||||
|
||||
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 photos based on documents from the Finnish police
|
||||
(https://www.poliisi.fi/instancedata/prime_product_julkaisu/intermin/embeds/poliisiwwwstructure/38462_Passikuvaohje_EN.pdf) describing passport photo dimensions of 47x36 mm and 500x653 px for digital biometric data stored in passports. They use ISO 19794-5 standard based on ICAO 9303 regulations which should also be compliant for all of Europe.
|
||||
|
||||
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"
|
||||
* (optional) add the line:
|
||||
"plugins/darkroom/clipping/extra_aspect_ratios/passport 36x47mm=47:36"
|
||||
to $CONFIGDIR/darktablerc
|
||||
|
||||
USAGE
|
||||
* when using the cropping tool, select "passport" as guide and if you added the line in yout rc
|
||||
select "passport 36x47mm" as aspect
|
||||
]]
|
||||
|
||||
local dt = require "darktable"
|
||||
local gettext = dt.gettext
|
||||
|
||||
dt.configuration.check_version(...,{2,0,0},{3,0,0},{4,0,0},{5,0,0})
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain("passport_guide",dt.configuration.config_dir.."/lua/locale/")
|
||||
|
||||
local function _(msgid)
|
||||
return gettext.dgettext("passport_guide", msgid)
|
||||
end
|
||||
|
||||
dt.guides.register_guide("passport",
|
||||
-- draw
|
||||
function(cairo, x, y, width, height, zoom_scale)
|
||||
local _width, _height
|
||||
|
||||
-- get the max 36x47 rectangle
|
||||
local aspect_ratio = 47 / 36
|
||||
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 / 36, _height / 47)
|
||||
|
||||
-- the outer rectangle
|
||||
cairo:rectangle( 0, 0, 36, 47)
|
||||
|
||||
-- vertical bars
|
||||
cairo:draw_line(16.5, 8, 16.5, 36)
|
||||
cairo:draw_line(19.5, 8, 19.5, 36)
|
||||
|
||||
-- long horisontal bars
|
||||
cairo:draw_line(6, 4, 30, 4)
|
||||
cairo:draw_line(6, 40, 30, 40)
|
||||
|
||||
-- short horisontal bars
|
||||
cairo:draw_line(9, 6, 27, 6)
|
||||
cairo:draw_line(9, 38, 27, 38)
|
||||
|
||||
cairo:restore()
|
||||
end,
|
||||
-- gui
|
||||
function()
|
||||
return dt.new_widget("label"){label = _("ISO 19794-5/ICAO 9309 passport"), 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
|
||||
247
contrib/pdf_slideshow.lua
Normal file
247
contrib/pdf_slideshow.lua
Normal file
@@ -0,0 +1,247 @@
|
||||
--[[
|
||||
This file is part of darktable,
|
||||
copyright (c) 2017 Pascal Obry
|
||||
|
||||
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/>.
|
||||
]]
|
||||
--[[
|
||||
SELECTION_TO_PDF
|
||||
Generates a PDF slideshow (via Latex) containing all selected images
|
||||
one per slide.
|
||||
|
||||
ADDITIANAL SOFTWARE NEEDED FOR THIS SCRIPT
|
||||
* a PDF-Viewer
|
||||
* pdflatex (Latex)
|
||||
|
||||
USAGE
|
||||
* require this file from your main lua config file:
|
||||
|
||||
This plugin will add a new exporter that will allow you to generate a pdf slideshow.
|
||||
The interface will let you add:
|
||||
- a global title for the slideshow (prefix in all slide label)
|
||||
- a delay for the transition between each slide
|
||||
|
||||
Each slide will contain a single picture with a label at the bottom with the
|
||||
format (all fields can be the empty string):
|
||||
|
||||
<global title> / <image creator> / <image title>
|
||||
|
||||
]]
|
||||
local dt = require "darktable"
|
||||
local df = require "lib/dtutils.file"
|
||||
require "official/yield"
|
||||
|
||||
local gettext = dt.gettext
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain("pdf_slideshow",dt.configuration.config_dir.."/lua/locale/")
|
||||
|
||||
local function _(msgid)
|
||||
return gettext.dgettext("pdf_slideshow", msgid)
|
||||
end
|
||||
|
||||
if not df.check_if_bin_exists("pdflatex") then
|
||||
dt.print_error(_("pdflatex not found"))
|
||||
return
|
||||
end
|
||||
|
||||
dt.configuration.check_version(...,{4,0,0},{5,0,0})
|
||||
|
||||
dt.preferences.register
|
||||
("pdf_slideshow","open with","string",
|
||||
_("a pdf viewer"),
|
||||
_("can be an absolute pathname or the tool may be in the PATH"),
|
||||
"xdg-open")
|
||||
|
||||
local title_widget = dt.new_widget("entry") {
|
||||
placeholder=_("slideshow title")
|
||||
}
|
||||
local delay_widget = dt.new_widget("slider")
|
||||
{
|
||||
label = _("transition delay (s)"),
|
||||
soft_min = 1, -- The soft minimum value for the slider, the slider can't go beyond this point
|
||||
soft_max = 20, -- The soft maximum value for the slider, the slider can't go beyond this point
|
||||
hard_min = 1, -- The hard minimum value for the slider, the user can't manually enter a value beyond this point
|
||||
hard_max = 60, -- The hard maximum value for the slider, the user can't manually enter a value beyond this point
|
||||
value = 5, -- The current value of the slider
|
||||
step = 1,
|
||||
digits = 0
|
||||
}
|
||||
local check_button_title = dt.new_widget("check_button")
|
||||
{
|
||||
label = _('include image title'),
|
||||
value = true,
|
||||
tooltip = _('whether to include the image title (if defined) into the slide')
|
||||
}
|
||||
local check_button_author = dt.new_widget("check_button")
|
||||
{
|
||||
label = _('include image author'),
|
||||
value = true,
|
||||
tooltip = _('whether to include the image author (if defined) into the slide')
|
||||
}
|
||||
local widget = dt.new_widget("box") {
|
||||
orientation=horizontal,
|
||||
dt.new_widget("label"){label = _("slideshow title")},
|
||||
title_widget,
|
||||
dt.new_widget("label"){label = ""},
|
||||
delay_widget,
|
||||
check_button_author,
|
||||
check_button_title
|
||||
}
|
||||
|
||||
local ending = [[
|
||||
\end{document}
|
||||
]]
|
||||
|
||||
-- only jpeg files are supported by latex
|
||||
local function support_format(storage, format)
|
||||
fmt = string.lower(format.name)
|
||||
if string.match(fmt,"jpeg") ~= nil and string.match(fmt,"2000") == nil then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
local filename =dt.configuration.tmp_dir.."/pdfout.tex"
|
||||
|
||||
local function my_write(latexfile,arg)
|
||||
local res,errmsg = latexfile:write(arg)
|
||||
if not res then
|
||||
error(errmsg)
|
||||
end
|
||||
end
|
||||
|
||||
local function img_filename(file,i)
|
||||
local dir=string.gsub(file, "(.*)(%/.*%..*)", "%1")
|
||||
local ext=string.gsub(file, "(.*)(%..*)", "%2")
|
||||
local lfile = dir.."/slide"..i..ext
|
||||
return lfile
|
||||
end
|
||||
|
||||
local function slide(latexfile,i,image,file)
|
||||
local title = ""
|
||||
if title_widget.text ~= "" then
|
||||
title = title_widget.text
|
||||
end
|
||||
if check_button_author.value == true and image.creator ~= "" then
|
||||
if title ~= "" then
|
||||
title = title.." / "
|
||||
end
|
||||
title = title..image.creator
|
||||
end
|
||||
if check_button_title.value == true and image.title ~= "" then
|
||||
if title ~= "" then
|
||||
title = title.." / "
|
||||
end
|
||||
title = title..image.title
|
||||
end
|
||||
|
||||
-- make sure there is no non-printable characters in the title
|
||||
title = string.gsub(title, "\n", "")
|
||||
title = string.gsub(title, "\r", "")
|
||||
title = string.gsub(title, "\t", "")
|
||||
|
||||
local lfile = img_filename(file,i)
|
||||
os.rename(file, lfile)
|
||||
|
||||
my_write(latexfile,"\\begin{figure}\n")
|
||||
my_write(latexfile,"\\begin{measuredfigure}\n")
|
||||
my_write(latexfile,"\\includegraphics[height=0.92\\textheight]{"..lfile.."}\n")
|
||||
my_write(latexfile,"\\end{measuredfigure}\n")
|
||||
my_write(latexfile,"\\caption{{\\color{white}"..title.."}}\n")
|
||||
my_write(latexfile,"\\end{figure}\n")
|
||||
end
|
||||
|
||||
dt.register_storage("pdf_slideshow",_("pdf slideshow"),
|
||||
nil,
|
||||
function(storage,image_table)
|
||||
|
||||
local preamble = [[
|
||||
\documentclass[a4paper,12pt,landscape]{beamer}
|
||||
\usetheme{default}
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage{graphicx}
|
||||
\usepackage{threeparttable}
|
||||
\usepackage[space]{grffile} % needed to support filename with spaces
|
||||
\pagestyle{empty}
|
||||
\parindent0pt
|
||||
\usepackage{geometry}
|
||||
\usepackage{color}
|
||||
\pagecolor{black!100}
|
||||
\color{white}
|
||||
\geometry{a4paper,landscape,left=2mm,right=2mm, top=2mm, bottom=2mm}
|
||||
\mode<presentation>
|
||||
\transduration{]]..string.gsub(delay_widget.value, ",", ".")..[[}
|
||||
\setbeamertemplate{footline}{}
|
||||
\setbeamertemplate{headline}{}
|
||||
\setbeamertemplate{frametitle}{}
|
||||
\setbeamertemplate{navigation symbols}{}
|
||||
\setbeamercolor{background canvas}{fg=white,bg=black!100}
|
||||
\setbeamercolor{normal text}{fg=white}
|
||||
\hypersetup{pdfstartpage=1,pdfpagemode=FullScreen}
|
||||
\setbeamertemplate{caption}{\insertcaption}
|
||||
\begin{document}
|
||||
]]
|
||||
|
||||
local errmsg
|
||||
local latexfile
|
||||
latexfile,errmsg=io.open(filename,"w")
|
||||
if not latexfile then
|
||||
error(errmsg)
|
||||
end
|
||||
my_write(latexfile,preamble)
|
||||
local i = 1
|
||||
for img,file in pairs(image_table) do
|
||||
slide(latexfile,i,img,file)
|
||||
my_write(latexfile,"\n\\bigskip\n")
|
||||
i = i+1
|
||||
end
|
||||
my_write(latexfile,ending)
|
||||
latexfile:close()
|
||||
|
||||
-- convert to PDF
|
||||
local dir=string.gsub(filename, "(.*/)(.*)", "%1")
|
||||
local locfile=string.gsub(filename, "(.*/)(.*)", "%2")
|
||||
local command = "pdflatex -halt-on-error -output-directory "..dir.." "..locfile
|
||||
local result = dt.control.execute(command)
|
||||
if result ~= 0 then
|
||||
dt.print(_("problem running pdflatex")) -- this one is probably usefull to the user
|
||||
error(_("problem running ")..command)
|
||||
end
|
||||
|
||||
-- open the PDF
|
||||
local pdffile=string.gsub(filename, ".tex", ".pdf")
|
||||
command = dt.preferences.read("pdf_slideshow","open with","string")
|
||||
command = command.." "..pdffile
|
||||
local result = dt.control.execute(command)
|
||||
if result ~= 0 then
|
||||
dt.print(_("problem running pdf viewer")) -- this one is probably usefull to the user
|
||||
error(_("problem running ")..command)
|
||||
end
|
||||
|
||||
-- finally do some clean-up
|
||||
local i = 1
|
||||
for img,file in pairs(image_table) do
|
||||
local lfile = img_filename(file,i)
|
||||
os.remove(lfile)
|
||||
i = i+1
|
||||
end
|
||||
end,
|
||||
support_format,
|
||||
nil,
|
||||
widget)
|
||||
|
||||
--
|
||||
-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua
|
||||
251
contrib/quicktag.lua
Normal file
251
contrib/quicktag.lua
Normal file
@@ -0,0 +1,251 @@
|
||||
--[[
|
||||
This file is part of darktable,
|
||||
Copyright (C) 2017 by Christian Kanzian
|
||||
|
||||
Thanks to
|
||||
Copyright (C) 2016 Bill Ferguson
|
||||
Copyright (C) 2017 Tobias Jakobs
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
]]
|
||||
|
||||
--[[
|
||||
QUICKTAG
|
||||
For faster attaching your favorite tags, the script adds shortcuts and
|
||||
the module "quicktag" in lighttable mode with a changeable number of buttons.
|
||||
To each button a tag can be assigned. If the tags do not exist in your database,
|
||||
they are added to the database once they get the first time attached to an image.
|
||||
|
||||
The number of buttons/shortcuts can be changed in the lua preferences.
|
||||
Changes in the number require a restart of darktable.
|
||||
|
||||
INSTALATION
|
||||
* copy this file in $CONFIGDIR/lua/ where CONFIGDIR is your darktable configuration directory
|
||||
* add the following line in the file $CONFIGDIR/luarc require "quicktag"
|
||||
|
||||
USAGE
|
||||
* set the number of quicktags between 2 and 10 in the preferences dialog and restart darktable
|
||||
* if wanted set the shortcuts in the preferences dialog
|
||||
* to add or change a quicktag, first select the old tag with the combobox "old quicktag",
|
||||
enter a new tag in the "new quicktag" filed and press "set quicktag"
|
||||
* use a shortcut or button to attach the tag to selected images
|
||||
]]
|
||||
|
||||
|
||||
local dt = require "darktable"
|
||||
local debug = require "darktable.debug"
|
||||
|
||||
|
||||
local gettext = dt.gettext
|
||||
|
||||
dt.configuration.check_version(...,{3,0,0},{4,0,0},{5,0,0})
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain("quicktag",dt.configuration.config_dir.."/lua/locale/")
|
||||
|
||||
local function _(msgid)
|
||||
return gettext.dgettext("quicktag", msgid)
|
||||
end
|
||||
|
||||
-- maximum length of button labels
|
||||
dt.preferences.register("quickTag",
|
||||
"labellength",
|
||||
"integer", -- type
|
||||
_("max. length of button labels"), -- label
|
||||
_("may range from 15 to 60 - needs a restart"), -- tooltip
|
||||
25, -- default
|
||||
15, -- min
|
||||
60)
|
||||
|
||||
|
||||
|
||||
local max_label_length = dt.preferences.read("quickTag", "labellength", "integer")
|
||||
|
||||
-- register number of quicktags
|
||||
dt.preferences.register("quickTag",
|
||||
"quickTagnumber",
|
||||
"integer", -- type
|
||||
_("number of quicktag fields"), -- label
|
||||
_("may range from 2 to 20 - needs a restart"), -- tooltip
|
||||
5, -- default
|
||||
2, -- min
|
||||
20)
|
||||
|
||||
local qnr = dt.preferences.read("quickTag", "quickTagnumber", "integer")
|
||||
|
||||
|
||||
|
||||
-- get quicktags from the preferences
|
||||
local quicktag_table = {}
|
||||
|
||||
|
||||
local function read_pref_tags()
|
||||
for j=1,qnr do
|
||||
quicktag_table[j] = dt.preferences.read("quickTag", "quicktag"..j, "string")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local quicktag_label = {}
|
||||
|
||||
|
||||
local function abbrevate_tags(t)
|
||||
for i=1,qnr do
|
||||
local taglength = string.len(t[i])
|
||||
if taglength > max_label_length then
|
||||
local max_2 = math.floor(max_label_length/2)
|
||||
quicktag_label[i] = string.sub(t[i],0,max_2).."..."..string.sub(t[i],taglength - max_2)
|
||||
else
|
||||
quicktag_label[i] = t[i]
|
||||
end
|
||||
-- print(quicktag_label[i])
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- quicktag function to attach tags
|
||||
local function tagattach(tag,qtagnr)
|
||||
if tag == "" then
|
||||
dt.print(string.format(_("quicktag %i is empty, please set a tag"), qtagnr))
|
||||
return true
|
||||
end
|
||||
|
||||
local tagnr = dt.tags.find(tag)
|
||||
|
||||
--create tag if it does not exist
|
||||
if tagnr == nil then
|
||||
dt.tags.create(tag)
|
||||
tagnr = dt.tags.find(tag)
|
||||
end
|
||||
|
||||
local sel_images = dt.gui.action_images
|
||||
|
||||
if next(sel_images) == nil then
|
||||
dt.print(_("no images selected"))
|
||||
return true
|
||||
end
|
||||
|
||||
local counter = 0
|
||||
|
||||
for _,image in ipairs(sel_images) do
|
||||
dt.tags.attach(tagnr,image)
|
||||
counter = counter+1
|
||||
end
|
||||
dt.print(string.format(_("tag \"%s\" attached to %i image(s)"), tag, counter))
|
||||
end
|
||||
|
||||
|
||||
-- create quicktag module elements
|
||||
-- read tags from preferences for initialization
|
||||
read_pref_tags()
|
||||
abbrevate_tags(quicktag_table)
|
||||
|
||||
|
||||
local button = {}
|
||||
|
||||
-- function to create buttons with tags as labels
|
||||
for j=1,qnr do
|
||||
button[#button+1] = dt.new_widget("button") {
|
||||
label = j..": "..quicktag_table[j],
|
||||
clicked_callback = function() tagattach(tostring(quicktag_table[j]),j) end}
|
||||
end
|
||||
|
||||
|
||||
local old_quicktag = dt.new_widget("combobox"){
|
||||
label = _("old tag"),
|
||||
tooltip = _("select the quicktag to replace")
|
||||
}
|
||||
|
||||
local function update_quicktag_list()
|
||||
-- abrevate long tags for the labels
|
||||
abbrevate_tags(quicktag_table)
|
||||
for j=1,qnr do
|
||||
button[j].label = j..": "..quicktag_label[j]
|
||||
old_quicktag[j] = j..": "..quicktag_table[j]
|
||||
end
|
||||
end
|
||||
|
||||
update_quicktag_list()
|
||||
|
||||
local new_quicktag = dt.new_widget("entry"){
|
||||
text = "",
|
||||
placeholder = _("new tag"),
|
||||
is_password = true,
|
||||
editable = true,
|
||||
tooltip = _("enter your tag here")
|
||||
}
|
||||
|
||||
local set_quicktag_button = dt.new_widget("button") {
|
||||
label = _("set tag"),
|
||||
clicked_callback = function()
|
||||
local old_tag = quicktag_table[old_quicktag.selected]
|
||||
if new_quicktag.text == "" then
|
||||
dt.print(_("new quicktag is empty!"))
|
||||
else
|
||||
quicktag_table[old_quicktag.selected] = new_quicktag.text
|
||||
dt.preferences.write("quickTag", "quicktag"..old_quicktag.selected, "string", new_quicktag.text)
|
||||
dt.print(string.format(_("quicktag \"%s\" replaced by \"%s\""), old_tag, new_quicktag.text))
|
||||
update_quicktag_list()
|
||||
new_quicktag.text = ""
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
local new_qt_widget = dt.new_widget ("box") {
|
||||
orientation = "horizontal",
|
||||
dt.new_widget("label") { label = _("new tag") },
|
||||
new_quicktag,
|
||||
set_quicktag_button
|
||||
}
|
||||
|
||||
|
||||
-- back UI elements in a table
|
||||
-- thanks to wpferguson for the hint
|
||||
local widget_table = {}
|
||||
|
||||
for i=1,qnr do
|
||||
widget_table[#widget_table + 1] = button[i]
|
||||
end
|
||||
|
||||
widget_table[#widget_table + 1] = dt.new_widget("separator"){}
|
||||
widget_table[#widget_table + 1] = old_quicktag
|
||||
widget_table[#widget_table + 1] = new_qt_widget
|
||||
|
||||
|
||||
--create module
|
||||
dt.register_lib(
|
||||
"quicktag", -- Module name
|
||||
"quicktag", -- name
|
||||
true, -- expandable
|
||||
false, -- resetable
|
||||
{[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 490}},
|
||||
|
||||
dt.new_widget("box"){
|
||||
orientation = "vertical",
|
||||
table.unpack(widget_table),
|
||||
|
||||
},
|
||||
nil,-- view_enter
|
||||
nil -- view_leave
|
||||
)
|
||||
|
||||
-- create shortcuts
|
||||
for i=1,qnr do
|
||||
dt.register_event("shortcut",
|
||||
function(event, shortcut) tagattach(tostring(quicktag_table[i])) end,
|
||||
string.format(_("quicktag %i"),i))
|
||||
end
|
||||
|
||||
-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua
|
||||
-- kate: tab-indents: off; indent-width 2; replace-tabs on; remove-trailing-space on;
|
||||
@@ -40,6 +40,9 @@
|
||||
|
||||
local dt = require "darktable"
|
||||
|
||||
-- added version check
|
||||
dt.configuration.check_version(...,{3,0,0},{4,0,0})
|
||||
|
||||
local function apply_rating(rating)
|
||||
local images = dt.gui.action_images
|
||||
for _, i in ipairs(images) do
|
||||
|
||||
114
contrib/rename-tags.lua
Normal file
114
contrib/rename-tags.lua
Normal file
@@ -0,0 +1,114 @@
|
||||
--[[
|
||||
Rename tags
|
||||
|
||||
AUTHOR
|
||||
Sebastian Witt (se.witt@gmx.net)
|
||||
|
||||
INSTALLATION
|
||||
* copy this file in $CONFIGDIR/lua/ where CONFIGDIR
|
||||
is your darktable configuration directory
|
||||
* add the following line in the file $CONFIGDIR/luarc
|
||||
require "rename-tags"
|
||||
|
||||
USAGE
|
||||
* In lighttable there is a new entry: 'rename tag'
|
||||
* Enter old tag (this one gets deleted!)
|
||||
* Enter new tag name
|
||||
|
||||
LICENSE
|
||||
GPLv2
|
||||
|
||||
]]
|
||||
|
||||
local darktable = require "darktable"
|
||||
local debug = require "darktable.debug"
|
||||
|
||||
-- GUI entries
|
||||
local old_tag = darktable.new_widget("entry") { tooltip = "Enter old tag" }
|
||||
local new_tag = darktable.new_widget("entry") { tooltip = "Enter new tag" }
|
||||
|
||||
-- This function does the renaming
|
||||
local function rename_tags(widget)
|
||||
-- If entries are empty, return
|
||||
if old_tag.text == '' then
|
||||
darktable.print ("Old tag can't be empty")
|
||||
return
|
||||
end
|
||||
if new_tag.text == '' then
|
||||
darktable.print ("New tag can't be empty")
|
||||
return
|
||||
end
|
||||
|
||||
local Count = 0
|
||||
|
||||
-- Check if old tag exists
|
||||
local ot = darktable.tags.find (old_tag.text)
|
||||
|
||||
if not ot then
|
||||
darktable.print ("Old tag does not exist")
|
||||
return
|
||||
end
|
||||
|
||||
-- Show job
|
||||
local job = darktable.gui.create_job ("Renaming tag", true)
|
||||
|
||||
old_tag.editable = false
|
||||
new_tag.editable = false
|
||||
|
||||
-- Create if it does not exists
|
||||
local nt = darktable.tags.create (new_tag.text)
|
||||
|
||||
-- Search images for old tag
|
||||
dbcount = #darktable.database
|
||||
for i,image in ipairs(darktable.database) do
|
||||
-- Update progress bar
|
||||
job.percent = i / dbcount
|
||||
|
||||
local tags = image:get_tags ()
|
||||
for _,t in ipairs (tags) do
|
||||
if t.name == old_tag.text then
|
||||
-- Found it, attach new tag
|
||||
image:attach_tag (nt)
|
||||
Count = Count + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Delete old tag, this removes it from all images
|
||||
darktable.tags.delete (ot)
|
||||
|
||||
job.valid = false
|
||||
darktable.print ("Renamed tags for " .. Count .. " images")
|
||||
old_tag.editable = true
|
||||
new_tag.editable = true
|
||||
end
|
||||
|
||||
-- GUI
|
||||
local old_widget = darktable.new_widget ("box") {
|
||||
orientation = "horizontal",
|
||||
darktable.new_widget("label") { label = "Old tag" },
|
||||
old_tag
|
||||
}
|
||||
|
||||
local new_widget = darktable.new_widget ("box") {
|
||||
orientation = "horizontal",
|
||||
darktable.new_widget("label") { label = "New tag" },
|
||||
new_tag
|
||||
}
|
||||
|
||||
local function rename_reset(widget)
|
||||
old_tag.text = ''
|
||||
new_tag.text = ''
|
||||
end
|
||||
|
||||
local rename_widget = darktable.new_widget ("box") {
|
||||
orientation = "vertical",
|
||||
reset_callback = rename_reset,
|
||||
old_widget,
|
||||
new_widget,
|
||||
darktable.new_widget("button") { label = "Go", clicked_callback = rename_tags }
|
||||
}
|
||||
|
||||
|
||||
darktable.register_lib ("rename_tags", "rename tag", true, true, {[darktable.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 20},}, rename_widget, nil, nil)
|
||||
|
||||
64
contrib/select_untagged.lua
Normal file
64
contrib/select_untagged.lua
Normal file
@@ -0,0 +1,64 @@
|
||||
--[[
|
||||
This file is part of darktable,
|
||||
copyright (c) 2017 Jannis_V
|
||||
|
||||
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 untagged images (darktable|* tags are ignored)
|
||||
]]
|
||||
|
||||
local dt = require "darktable"
|
||||
local gettext = dt.gettext
|
||||
|
||||
dt.configuration.check_version(...,{3,0,0},{4,0,0},{5,0,0})
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain("select_untagged",dt.configuration.config_dir.."/lua/locale/")
|
||||
|
||||
local function _(msgid)
|
||||
return gettext.dgettext("select_untagged", msgid)
|
||||
end
|
||||
|
||||
local function stop_job(job)
|
||||
job.valid = false
|
||||
end
|
||||
|
||||
local function select_untagged_images()
|
||||
job = dt.gui.create_job(_("select untagged images"), true, stop_job)
|
||||
|
||||
local selection = {}
|
||||
|
||||
for key,image in ipairs(dt.collection) do
|
||||
if(job.valid) then
|
||||
job.percent = (key-1)/#dt.collection
|
||||
local tags = dt.tags.get_tags(image)
|
||||
local hasTags = false
|
||||
for _,tag in ipairs(tags) do
|
||||
if not string.match(tag.name,"darktable|") then
|
||||
hasTags = true
|
||||
end
|
||||
end
|
||||
if hasTags == false then
|
||||
table.insert(selection,image)
|
||||
end
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
job.valid = false
|
||||
dt.gui.selection(selection)
|
||||
end
|
||||
|
||||
dt.gui.libs.select.register_selection(_("select untagged"),select_untagged_images,_("select all images containing no tags or only tags added by darktable"))
|
||||
@@ -25,38 +25,27 @@ USAGE
|
||||
]]
|
||||
|
||||
local dt = require "darktable"
|
||||
local df = require "lib/dtutils.file"
|
||||
require "official/yield"
|
||||
|
||||
local gettext = dt.gettext
|
||||
dt.configuration.check_version(...,{2,0,2},{3,0,0})
|
||||
|
||||
dt.configuration.check_version(...,{2,0,2},{3,0,0},{4,0,0})
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain("slideshowMusic",dt.configuration.config_dir.."/lua/")
|
||||
gettext.bindtextdomain("slideshowMusic",dt.configuration.config_dir.."/lua/locale/")
|
||||
|
||||
local function _(msgid)
|
||||
return gettext.dgettext("slideshowMusic", msgid)
|
||||
end
|
||||
|
||||
local function checkIfBinExists(bin)
|
||||
local handle = io.popen("which "..bin)
|
||||
local result = handle:read()
|
||||
local ret
|
||||
handle:close()
|
||||
if (not result) then
|
||||
dt.print_error(bin.." not found")
|
||||
ret = false
|
||||
end
|
||||
ret = true
|
||||
return ret
|
||||
end
|
||||
|
||||
local function playSlideshowMusic(_, old_view, new_view)
|
||||
local filename, playMusic
|
||||
|
||||
filename = dt.preferences.read("slideshowMusic","SlideshowMusic","string")
|
||||
playMusic = dt.preferences.read("slideshowMusic","PlaySlideshowMusic","bool")
|
||||
|
||||
if not checkIfBinExists("rhythmbox-client") then
|
||||
if not df.check_if_bin_exists("rhythmbox-client") then
|
||||
dt.print_error(_("rhythmbox-client not found"))
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
@@ -31,38 +31,34 @@ USAGE
|
||||
]]
|
||||
|
||||
local dt = require "darktable"
|
||||
local df = require "lib/dtutils.file"
|
||||
require "official/yield"
|
||||
local gettext = dt.gettext
|
||||
|
||||
dt.configuration.check_version(...,{2,0,1})
|
||||
dt.configuration.check_version(...,{2,0,1},{3,0,0},{4,0,0},{5,0,0})
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain("video_mencoder",dt.configuration.config_dir.."/lua/locale/")
|
||||
|
||||
local function _(msgid)
|
||||
return gettext.dgettext("video_mencoder", msgid)
|
||||
end
|
||||
|
||||
local function show_status(storage, image, format, filename, number, total, high_quality, extra_data)
|
||||
dt.print("Export Image "..tostring(number).."/"..tostring(total))
|
||||
end
|
||||
|
||||
local function checkIfBinExists(bin)
|
||||
local handle = io.popen("which "..bin)
|
||||
local result = handle:read()
|
||||
local ret
|
||||
handle:close()
|
||||
if (result) then
|
||||
--dt.print_error("true checkIfBinExists: "..bin)
|
||||
ret = true
|
||||
else
|
||||
dt.print_error(bin.." not found")
|
||||
ret = false
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
local function create_video_mencoder(storage, image_table, extra_data)
|
||||
if not checkIfBinExists("mencoder") then
|
||||
if not df.check_if_bin_exists("mencoder") then
|
||||
dt.print_error(_("mencoder not found"))
|
||||
return
|
||||
end
|
||||
if not checkIfBinExists("xdg-open") then
|
||||
if not df.check_if_bin_exists("xdg-open") then
|
||||
dt.print_error(_("xdg-open not found"))
|
||||
return
|
||||
end
|
||||
if not checkIfBinExists("xdg-user-dir") then
|
||||
if not df.check_if_bin_exists("xdg-user-dir") then
|
||||
dt.print_error(_("xdg-user-dir not found"))
|
||||
return
|
||||
end
|
||||
|
||||
@@ -111,6 +107,9 @@ dt.preferences.register("video_mencoder", "OpenVideo", "bool", "Video exort (MEn
|
||||
local handle = io.popen("xdg-user-dir VIDEOS")
|
||||
local result = handle:read()
|
||||
handle:close()
|
||||
if (result == nil) then
|
||||
result = ""
|
||||
end
|
||||
dt.preferences.register("video_mencoder", "ExportDirectory", "directory", "Video exort (MEncoder): Video export directory","A directory that will be used to export a Video",result)
|
||||
|
||||
-- Get the MEncoder codec list with: mencoder -ovc help
|
||||
|
||||
@@ -53,7 +53,7 @@ LUA ERROR Hallo Welt!
|
||||
|
||||
]]
|
||||
local dt = require "darktable"
|
||||
dt.configuration.check_version(...,{3,0,0})
|
||||
dt.configuration.check_version(...,{3,0,0},{4,0,0},{5,0,0}))
|
||||
|
||||
-- Not translated Text
|
||||
dt.print_error("Hello World!")
|
||||
@@ -64,7 +64,7 @@ dt.print_error(gettext.gettext("image"))
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
|
||||
gettext.bindtextdomain("gettextExample",dt.configuration.config_dir.."/lua/")
|
||||
gettext.bindtextdomain("gettextExample",dt.configuration.config_dir.."/lua/locale/")
|
||||
-- Translate a string using the specified textdomain
|
||||
dt.print_error(gettext.dgettext("gettextExample", 'Hello World!'))
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ USAGE
|
||||
|
||||
]]
|
||||
local dt = require "darktable"
|
||||
dt.configuration.check_version(...,{2,0,0},{3,0,0})
|
||||
dt.configuration.check_version(...,{2,0,0},{3,0,0},{4,0,0},{5,0,0})
|
||||
|
||||
dt.print("hello, world")
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ https://www.darktable.org/lua-api/index.html.php#darktable_new_widget
|
||||
|
||||
local dt = require "darktable"
|
||||
|
||||
dt.configuration.check_version(...,{3,0,0})
|
||||
dt.configuration.check_version(...,{3,0,0},{4,0,0},{5,0,0})
|
||||
|
||||
-- add a new lib
|
||||
local check_button = dt.new_widget("check_button"){label = "MyCheck_button", value = true}
|
||||
@@ -70,7 +70,42 @@ local slider = dt.new_widget("slider")
|
||||
value = 52 -- The current value of the slider
|
||||
}
|
||||
|
||||
dt.register_lib(
|
||||
if (dt.configuration.api_version_major >= 6) then
|
||||
local section_label = dt.new_widget("section_label")
|
||||
{
|
||||
label = "MySectionLabel"
|
||||
}
|
||||
|
||||
dt.register_lib(
|
||||
"exampleModule", -- Module name
|
||||
"exampleModule", -- name
|
||||
true, -- expandable
|
||||
false, -- resetable
|
||||
{[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, -- containers
|
||||
dt.new_widget("box") -- widget
|
||||
{
|
||||
orientation = "vertical",
|
||||
dt.new_widget("button")
|
||||
{
|
||||
label = "MyButton",
|
||||
clicked_callback = function (_)
|
||||
dt.print("Button clicked")
|
||||
end
|
||||
},
|
||||
check_button,
|
||||
combobox,
|
||||
entry,
|
||||
file_chooser_button,
|
||||
label,
|
||||
separator,
|
||||
slider,
|
||||
section_label
|
||||
},
|
||||
nil,-- view_enter
|
||||
nil -- view_leave
|
||||
)
|
||||
else
|
||||
dt.register_lib(
|
||||
"exampleModule", -- Module name
|
||||
"exampleModule", -- name
|
||||
true, -- expandable
|
||||
@@ -96,7 +131,8 @@ dt.register_lib(
|
||||
},
|
||||
nil,-- view_enter
|
||||
nil -- view_leave
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua
|
||||
-- kate: hl Lua;
|
||||
|
||||
@@ -22,7 +22,7 @@ USAGE
|
||||
* require this script from your main lua file
|
||||
]]
|
||||
local dt = require "darktable"
|
||||
dt.configuration.check_version(...,{2,0,1},{3,0,0})
|
||||
dt.configuration.check_version(...,{2,0,1},{3,0,0},{4,0,0},{5,0,0})
|
||||
|
||||
dt.preferences.register("preferenceExamples", -- script: This is a string used to avoid name collision in preferences (i.e namespace). Set it to something unique, usually the name of the script handling the preference.
|
||||
"preferenceExamplesString", -- name
|
||||
|
||||
40
examples/printExamples.lua
Normal file
40
examples/printExamples.lua
Normal file
@@ -0,0 +1,40 @@
|
||||
--[[
|
||||
This file is part of darktable,
|
||||
copyright (c) 2017 Tobias Jakobs
|
||||
darktable is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
darktable is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with darktable. If not, see <http://www.gnu.org/licenses/>.
|
||||
]]
|
||||
|
||||
--[[
|
||||
Print Examples
|
||||
prints "hello world when DT starts
|
||||
USAGE
|
||||
* require this file from your main lua config file:
|
||||
]]
|
||||
local dt = require "darktable"
|
||||
dt.configuration.check_version(...,{5,0,0})
|
||||
|
||||
-- Will print a string to the darktable control log (the long
|
||||
-- overlayed window that appears over the main panel).
|
||||
dt.print("print")
|
||||
|
||||
-- This function will print its parameter if the Lua logdomain is
|
||||
-- activated. Start darktable with the "-d lua" command line option
|
||||
-- to enable the Lua logdomain.
|
||||
dt.print_error("print error")
|
||||
|
||||
-- This function will print its parameter if the Lua logdomain is
|
||||
-- activated. Start darktable with the "-d lua" command line option
|
||||
-- to enable the Lua logdomain.
|
||||
dt.print_log("print log")
|
||||
|
||||
--
|
||||
-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua
|
||||
34
examples/running_os.lua
Normal file
34
examples/running_os.lua
Normal file
@@ -0,0 +1,34 @@
|
||||
--[[
|
||||
This file is part of darktable,
|
||||
copyright (c) 2017 Tobias Jakobs
|
||||
|
||||
darktable is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
darktable is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with darktable. If not, see <http://www.gnu.org/licenses/>.
|
||||
]]
|
||||
--[[
|
||||
|
||||
USAGE
|
||||
* require this script from your main lua file
|
||||
To do this add this line to the file .config/darktable/luarc:
|
||||
require "running_os"
|
||||
|
||||
prints the operating system
|
||||
|
||||
]]
|
||||
local dt = require "darktable"
|
||||
dt.configuration.check_version(...,{5,0,0})
|
||||
|
||||
dt.print("You are running: "..dt.configuration.running_os)
|
||||
|
||||
--
|
||||
-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua
|
||||
@@ -32,7 +32,7 @@ local dt = require "darktable"
|
||||
|
||||
local log = require "lib/dtutils.log"
|
||||
|
||||
dt.configuration.check_version(...,{3,0,0})
|
||||
dt.configuration.check_version(...,{3,0,0},{4,0,0},{5,0,0})
|
||||
|
||||
dtutils.libdoc.functions["split"] = {
|
||||
Name = [[split]],
|
||||
|
||||
@@ -23,7 +23,7 @@ dtutils_file.libdoc = {
|
||||
|
||||
local gettext = dt.gettext
|
||||
|
||||
dt.configuration.check_version(...,{3,0,0})
|
||||
dt.configuration.check_version(...,{3,0,0},{4,0,0},{5,0,0})
|
||||
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain("dtutils.file",dt.configuration.config_dir.."/lua/locale/")
|
||||
|
||||
84
locale/de_DE/LC_MESSAGES/quicktag.po
Normal file
84
locale/de_DE/LC_MESSAGES/quicktag.po
Normal file
@@ -0,0 +1,84 @@
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Christian Kanzian <christian.kanzian@gmx.at>, 2017.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-02-20 17:38+0100\n"
|
||||
"PO-Revision-Date: 2017-02-20 17:50+0100\n"
|
||||
"Last-Translator: Christian Kanzian <christian.kanzian@gmx.at>\n"
|
||||
"Language-Team: German <kde-i18n-de@kde.org>\n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Lokalize 1.5\n"
|
||||
|
||||
#: quicktag.lua:64
|
||||
msgid "max. length of button labels"
|
||||
msgstr "Max. Länge der Schaltflächen-Beschriftung"
|
||||
|
||||
#: quicktag.lua:65
|
||||
msgid "may range from 15 to 60 - needs a restart"
|
||||
msgstr "Bereich von 15 bis 60 möglich - Neustart erforderlich"
|
||||
|
||||
#: quicktag.lua:78
|
||||
msgid "number of quicktag fields"
|
||||
msgstr "Anzahl von quicktag Feldern"
|
||||
|
||||
#: quicktag.lua:79
|
||||
msgid "may range from 2 to 20 - needs a restart"
|
||||
msgstr "Bereich von 2 bis 20 möglich - Neustart erforderlich"
|
||||
|
||||
#: quicktag.lua:119
|
||||
#, lua-format
|
||||
msgid "quicktag %i is empty, please set a tag"
|
||||
msgstr "quicktag %i ist leer - bitte Tag eingeben"
|
||||
|
||||
#: quicktag.lua:134
|
||||
msgid "no images selected"
|
||||
msgstr "keine Bilder ausgewählt"
|
||||
|
||||
#: quicktag.lua:144
|
||||
#, lua-format
|
||||
msgid "tag \"%s\" attached to %i image(s)"
|
||||
msgstr "Tag \"%s\" an %i Bild(er) angehängt"
|
||||
|
||||
#: quicktag.lua:165
|
||||
msgid "old quicktag"
|
||||
msgstr "Alter quicktag"
|
||||
|
||||
#: quicktag.lua:166
|
||||
msgid "select the quicktag to replace"
|
||||
msgstr "Wähle den quicktag der ersetzt werden soll"
|
||||
|
||||
#: quicktag.lua:182 quicktag.lua:206
|
||||
msgid "new quicktag"
|
||||
msgstr "Neuer quicktag"
|
||||
|
||||
#: quicktag.lua:185
|
||||
msgid "enter your tag here"
|
||||
msgstr "Bitte Tag hier eingeben"
|
||||
|
||||
#: quicktag.lua:189
|
||||
msgid "set quicktag"
|
||||
msgstr "Setze Tag"
|
||||
|
||||
#: quicktag.lua:193
|
||||
msgid "new quicktag is empty!"
|
||||
msgstr "Neuer Tag ist leer!"
|
||||
|
||||
#: quicktag.lua:197
|
||||
#, lua-format
|
||||
msgid "quicktag \"%s\" replaced by \"%s\""
|
||||
msgstr "quicktag \"%s\" ersetzt durch \"%s\" "
|
||||
|
||||
#: quicktag.lua:246
|
||||
#, lua-format
|
||||
msgid "quicktag %i"
|
||||
msgstr "quicktag %i"
|
||||
|
||||
|
||||
BIN
locale/de_DE/LC_MESSAGES/select_untagged.mo
Normal file
BIN
locale/de_DE/LC_MESSAGES/select_untagged.mo
Normal file
Binary file not shown.
27
locale/de_DE/LC_MESSAGES/select_untagged.po
Normal file
27
locale/de_DE/LC_MESSAGES/select_untagged.po
Normal file
@@ -0,0 +1,27 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"POT-Creation-Date: 2017-09-14 12:18+0200\n"
|
||||
"PO-Revision-Date: 2017-09-14 12:23+0200\n"
|
||||
"Last-Translator: Jannis_V\n"
|
||||
"Language-Team: \n"
|
||||
"Language: de_DE\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 1.8.7.1\n"
|
||||
"X-Poedit-Basepath: ../../../contrib\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Poedit-SearchPath-0: select_untagged.lua\n"
|
||||
|
||||
#: select_untagged.lua:38
|
||||
msgid "select untagged images"
|
||||
msgstr "Auswahl von Bildern ohne Tags"
|
||||
|
||||
#: select_untagged.lua:64
|
||||
msgid "select untagged"
|
||||
msgstr "Ohne Tags"
|
||||
|
||||
#: select_untagged.lua:64
|
||||
msgid "select all images containing no tags or only tags added by darktable"
|
||||
msgstr "Wähle alle Bilder der aktuellen Sammlung aus, die keine Tags oder nur automatisch durch darktable erzeugte Tags enthalten"
|
||||
70
locale/fr_FR/LC_MESSAGES/pdf_slideshow.po
Normal file
70
locale/fr_FR/LC_MESSAGES/pdf_slideshow.po
Normal file
@@ -0,0 +1,70 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-04-10 09:30+0200\n"
|
||||
"PO-Revision-Date: 2017-04-10 09:48+0200\n"
|
||||
"Language: fr_FR\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Last-Translator: Pascal Obry <pascal@obry.net>\n"
|
||||
"Language-Team: \n"
|
||||
"X-Generator: Poedit 1.8.11\n"
|
||||
|
||||
#: pdf_slideshow.lua:55
|
||||
msgid "pdflatex not found"
|
||||
msgstr "pdflatex non trouvé"
|
||||
|
||||
#: pdf_slideshow.lua:63
|
||||
msgid "a pdf viewer"
|
||||
msgstr "lecteur pdf"
|
||||
|
||||
#: pdf_slideshow.lua:64
|
||||
msgid "can be an absolute pathname or the tool may be in the PATH"
|
||||
msgstr "peut être un chemin absolu où l'outil peut être dans le chemin par défaut"
|
||||
|
||||
#: pdf_slideshow.lua:68 pdf_slideshow.lua:95
|
||||
msgid "slideshow title"
|
||||
msgstr "titre du diaporama"
|
||||
|
||||
#: pdf_slideshow.lua:72
|
||||
msgid "transition delay (s)"
|
||||
msgstr "temporisation (s) entre diapositives"
|
||||
|
||||
#: pdf_slideshow.lua:83
|
||||
msgid "include image title"
|
||||
msgstr "inclus le titre de l'image"
|
||||
|
||||
#: pdf_slideshow.lua:85
|
||||
msgid "whether to include the image title (if defined) into the slide"
|
||||
msgstr "indique si le titre de l'image (si défini) doit être inclus dans la diapositive"
|
||||
|
||||
#: pdf_slideshow.lua:89
|
||||
msgid "include image author"
|
||||
msgstr "inclus l'auteur de l'image"
|
||||
|
||||
#: pdf_slideshow.lua:91
|
||||
msgid "whether to include the image author (if defined) into the slide"
|
||||
msgstr "indique si l'auteur de l'image (si défini) doit être inclus dans la diapositive"
|
||||
|
||||
#: pdf_slideshow.lua:167
|
||||
msgid "pdf slideshow"
|
||||
msgstr "diaporama pdf"
|
||||
|
||||
#: pdf_slideshow.lua:220
|
||||
msgid "problem running pdflatex"
|
||||
msgstr "impossible d'exécuter pdflatex"
|
||||
|
||||
#: pdf_slideshow.lua:221 pdf_slideshow.lua:231
|
||||
msgid "problem running "
|
||||
msgstr "impossible d'exécuter "
|
||||
|
||||
#: pdf_slideshow.lua:230
|
||||
msgid "problem running pdf viewer"
|
||||
msgstr "impossible d'exécuter le lecteur pdf"
|
||||
BIN
locale/fr_FR/LC_MESSAGES/select_untagged.mo
Normal file
BIN
locale/fr_FR/LC_MESSAGES/select_untagged.mo
Normal file
Binary file not shown.
27
locale/fr_FR/LC_MESSAGES/select_untagged.po
Normal file
27
locale/fr_FR/LC_MESSAGES/select_untagged.po
Normal file
@@ -0,0 +1,27 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"POT-Creation-Date: 2017-09-14 15:42+0200\n"
|
||||
"PO-Revision-Date: 2017-09-14 15:52+0200\n"
|
||||
"Last-Translator: Jannis_V\n"
|
||||
"Language-Team: \n"
|
||||
"Language: fr_FR\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 1.8.7.1\n"
|
||||
"X-Poedit-Basepath: ../../../contrib\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
"X-Poedit-SearchPath-0: select_untagged.lua\n"
|
||||
|
||||
#: select_untagged.lua:38
|
||||
msgid "select untagged images"
|
||||
msgstr "sélection des images sans mots-clés"
|
||||
|
||||
#: select_untagged.lua:64
|
||||
msgid "select untagged"
|
||||
msgstr "sans mots-clés"
|
||||
|
||||
#: select_untagged.lua:64
|
||||
msgid "select all images containing no tags or only tags added by darktable"
|
||||
msgstr "sélection des images sans mots-clés ou seulement avec les mots-clés ajoutés par darktable"
|
||||
@@ -31,7 +31,7 @@ local dt = require "darktable"
|
||||
local https = require "ssl.https"
|
||||
local cjson = require "cjson"
|
||||
|
||||
dt.configuration.check_version(...,{2,0,0},{3,0,0})
|
||||
dt.configuration.check_version(...,{2,0,0},{3,0,0},{4,0,0})
|
||||
|
||||
-- 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,
|
||||
|
||||
@@ -27,7 +27,7 @@ USAGE
|
||||
|
||||
local dt = require "darktable"
|
||||
|
||||
dt.configuration.check_version(...,{3,0,0})
|
||||
dt.configuration.check_version(...,{3,0,0},{4,0,0})
|
||||
|
||||
-- set this to "false" if you don't want to overwrite metadata fields
|
||||
-- (title, description, creator, publisher and rights) that are already set
|
||||
|
||||
@@ -29,7 +29,7 @@ all tags longer than the given length will be automatically deleted at every res
|
||||
]]
|
||||
|
||||
local dt = require "darktable"
|
||||
dt.configuration.check_version(...,{2,0,0},{3,0,0})
|
||||
dt.configuration.check_version(...,{2,0,0},{3,0,0},{4,0,0})
|
||||
|
||||
dt.preferences.register("delete_long_tags", "length", "integer",
|
||||
"maximum length of tags to keep",
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
]]
|
||||
--[[
|
||||
RUN ENFUSE ON THE SELECTED IMAGES
|
||||
This script uses enfuse to merge the selected images into one HDR and imports the result.
|
||||
This script uses enfuse to merge the selected images into one tonemapped image and imports the result.
|
||||
It only works on ldr images (like, JPEG).
|
||||
|
||||
USAGE
|
||||
@@ -33,30 +33,22 @@ TODO
|
||||
]]
|
||||
|
||||
local dt = require "darktable"
|
||||
local df = require "lib/dtutils.file"
|
||||
require "official/yield"
|
||||
local gettext = dt.gettext
|
||||
|
||||
dt.configuration.check_version(...,{3,0,0},{4,0,0})
|
||||
|
||||
dt.configuration.check_version(...,{3,0,0})
|
||||
-- Tell gettext where to find the .mo file translating messages for a particular domain
|
||||
gettext.bindtextdomain("enfuse",dt.configuration.config_dir.."/lua/locale/")
|
||||
|
||||
-- thanks Tobias Jakobs for this function (taken from contrib/hugin.lua)
|
||||
local function checkIfBinExists(bin)
|
||||
local handle = io.popen("which "..bin)
|
||||
local result = handle:read()
|
||||
local ret
|
||||
handle:close()
|
||||
if (result) then
|
||||
dt.print_error("true checkIfBinExists: "..bin)
|
||||
ret = true
|
||||
else
|
||||
dt.print_error(bin.." not found")
|
||||
ret = false
|
||||
end
|
||||
return ret
|
||||
local function _(msgid)
|
||||
return gettext.dgettext("enfuse", msgid)
|
||||
end
|
||||
|
||||
-- add a new lib
|
||||
-- is enfuse installed?
|
||||
local enfuse_installed = checkIfBinExists("enfuse")
|
||||
local enfuse_installed = df.check_if_bin_exists("enfuse")
|
||||
|
||||
-- initialize exposure_mu value and depth setting in config to sane defaults (would be 0 otherwise)
|
||||
if dt.preferences.read("enfuse", "depth", "integer") == 0 then
|
||||
|
||||
@@ -38,7 +38,7 @@ local dt = require "darktable"
|
||||
require "darktable.debug"
|
||||
require "official/yield"
|
||||
|
||||
dt.configuration.check_version(...,{2,1,0},{3,0,0})
|
||||
dt.configuration.check_version(...,{2,1,0},{3,0,0},{4,0,0})
|
||||
|
||||
dt.preferences.register("generate_image_txt",
|
||||
"enabled",
|
||||
|
||||
@@ -29,7 +29,7 @@ This plugin will add a widget at the bottom of the left column in lighttable mod
|
||||
|
||||
]]
|
||||
local dt = require "darktable"
|
||||
dt.configuration.check_version(...,{2,0,0},{3,0,0})
|
||||
dt.configuration.check_version(...,{2,0,0},{3,0,0},{4,0,0})
|
||||
|
||||
local main_label = dt.new_widget("label"){selectable = true, ellipsize = "middle", halign = "start"}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ increase it if you need more temporary selection buffers
|
||||
|
||||
]]
|
||||
local dt = require "darktable"
|
||||
dt.configuration.check_version(...,{2,0,0},{3,0,0})
|
||||
dt.configuration.check_version(...,{2,0,0},{3,0,0},{4,0,0})
|
||||
|
||||
local buffer_count = 5
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ Plugin allows you to choose how many thumbnails you need per row
|
||||
local dt = require "darktable"
|
||||
require "official/yield"
|
||||
|
||||
dt.configuration.check_version(...,{2,0,0},{3,0,0})
|
||||
dt.configuration.check_version(...,{2,0,0},{3,0,0},{4,0,0})
|
||||
|
||||
dt.preferences.register
|
||||
("selection_to_pdf","Open with","string",
|
||||
|
||||
@@ -25,21 +25,6 @@ USAGE
|
||||
local dt = require "darktable"
|
||||
local yield_orig = coroutine.yield
|
||||
|
||||
-- ToDo: Test with dt master
|
||||
--[[
|
||||
if (dt.configuration.api_version_major >= 4) then
|
||||
coroutine.yield = function(yield_type, command)
|
||||
if (yield_type == "RUN_COMMAND") then
|
||||
dt.control.execute(command)
|
||||
elseif (yield_type == "FILE_READABLE") then
|
||||
dt.control.read(command)
|
||||
elseif (yield_type == "WAIT_MS") then
|
||||
dt.control.sleep(command)
|
||||
end
|
||||
end
|
||||
end
|
||||
]]
|
||||
|
||||
if (dt.configuration.api_version_major < 4) then
|
||||
dt.control = {}
|
||||
dt.control.execute = function(command)
|
||||
|
||||
Reference in New Issue
Block a user