168 Commits

Author SHA1 Message Date
supertobi
85ccc663c8 Merge pull request #74 from wpferguson/libraries
Libraries
2016-10-25 13:30:37 +02:00
Bill Ferguson
dab02823ff Fixed log bug in dprint function 2016-10-24 19:23:04 -04:00
Bill Ferguson
4fccfbf51d Added checks for binaries used to generate the pdf man pages 2016-10-24 12:09:04 -04:00
Boucman
b04e322df8 Merge pull request #77 from wpferguson/include_yield
require official/yield in scripts using dt.control.execute()
2016-10-21 21:17:25 +02:00
Bill Ferguson
f550822943 Added require "official/yield" to scripts that use dt.control.execute() so that they work correctly if you haven't required official/yield somewhere else. 2016-10-21 13:25:40 -04:00
Bill Ferguson
564fd20f23 Moved lib/libLog.lua to lib/dtutils/log.lua. Rewrote most of it to make it more configurable and easier to use. Updated doc format to a fixed list of fields. Did away with the comment blocks and just relying on the libdoc comments. Update doc tools to use new formats. Moved dtutils/extensions.lua to dtutils/string.lua. Pulled dtutils/processor.lua back for now since there is no context for it. Removed unneeded functions and cleaned up others. 2016-10-20 01:19:54 -04:00
supertobi
45e38a9a2d Merge pull request #75 from chrik5/tagging_translation
copy attach detach add translation submitted by Holger Klemm
2016-10-18 16:18:11 +02:00
chrik5
e51f1e0a82 copy_attach_detach_tags small updates on german translation 2016-10-18 15:37:54 +02:00
chrik5
b4b82906ea copy_attach_detach_tags make script translateable and added german translation by Holger Klemm 2016-10-18 15:30:45 +02:00
Bill Ferguson
a254ac87f7 Created libraries from commonly used functions. Moved official/debug-helpers.lua into lib/dtutils/debug.lua. Created a logging library to provide various levels of logging. Documented all libraries and functions. Created tools to extract documentation in text, man page, and pdf formats. 2016-10-15 01:47:43 -04:00
supertobi
e76a883053 Merge pull request #71 from chrik5/tagging
Tagging some code clean up
2016-10-04 16:35:18 +02:00
chrik5
f967e96aa5 exit attach tags function if there are no tags to attach 2016-10-04 16:03:35 +02:00
chrik5
c8713a7f38 cleanup the code and create UI elements before 2016-10-04 13:54:49 +02:00
supertobi
73e274cf0b Merge pull request #70 from TurboGit/contrib-fr_FR
Initial fr_FR translation of the contribution lua scripts.
2016-10-04 11:10:23 +02:00
Pascal Obry
c75c3d0734 Initial fr_FR translation of the contribution lua scripts. 2016-10-03 17:24:36 +02:00
supertobi
e74b253f64 Update clear_GPS.po
better german
2016-09-08 11:31:56 +02:00
Boucman
45009aedff Merge pull request #68 from wpferguson/clear_gps_data
clear GPS data
2016-09-08 07:42:13 +02:00
Bill Ferguson
870ba65662 Missed an edit in the _() function 2016-09-07 22:56:11 -04:00
Bill Ferguson
80ace33af1 Created clear_GPS to clear GPS data from selected images. 2016-09-07 22:53:51 -04:00
supertobi
f69455bdb7 Merge pull request #65 from wpferguson/master
Added fileCopy and fileMove functions to replace os.rename which does…
2016-09-06 10:18:03 +02:00
supertobi
4ed6dc276e Merge pull request #66 from wpferguson/geo_uri
geo_uri
2016-09-06 10:16:23 +02:00
Bill Ferguson
3dd415697a Removed extra end statement 2016-09-05 13:56:22 -04:00
Bill Ferguson
f7ce368b28 Reverted contrib/geo_uri.lua to previous version so that I can add it in it's own pull request. 2016-09-05 13:49:47 -04:00
Bill Ferguson
168236780d Incorporated supertobi's correction to the translations 2016-09-04 11:42:27 -04:00
Bill Ferguson
549e9ccd0b Changed fileMove per discussion to use os.rename first, os.execute(mv... second, and a lua solution third. The lua solution includes fileCopy with attempts os.execute(cp... first, then does a pure lua copy if that doesn't succeed 2016-08-31 20:18:29 -04:00
Bill Ferguson
21f31b403b Recoded fileMove to use os.execute and the system mv command. Removed fileCopy as it was no longer needed. 2016-08-25 22:49:59 -04:00
Bill Ferguson
3b42503bd3 Removed extra end statement 2016-08-23 21:14:39 -04:00
Bill Ferguson
95e15fc40c Changed poorly translated message to that suggested by supertobi, and took care of spacing issue. 2016-08-23 21:13:11 -04:00
Bill Ferguson
74e546c2ce Added fileCopy and fileMove functions to replace os.rename which doesn't work across filesystems. Added an error message if the move isn't accomplished so that the user knows what happened. Updated translations to reflect changes. 2016-08-23 00:09:27 -04:00
supertobi
0c0f97560e Merge pull request #50 from tejovanthn/master
Enables custom number of thumbnails per row
2016-06-29 09:33:11 +02:00
tejovanthn
8392f6f5a6 enables custom number of thumbnails per row
Changes the thumbs_per_line from a text field to a slider
2016-06-29 03:19:20 +05:30
supertobi
9a5ede0e6d Merge pull request #62 from elman22/master
Fix for issues #58 and #59 - Issue with exporting RAW images
2016-04-29 21:38:35 +02:00
elman
33417454ed Reverted back to dt.control.execute() 2016-04-29 18:59:05 +02:00
supertobi
d79237958f Create yield.lua
darktable yield compatibility script
2016-04-28 23:20:37 +02:00
elman
6ef06467b6 Added comments 2016-04-28 19:44:51 +02:00
supertobi
a85d2222eb Merge pull request #61 from spaceChRiS/import-filters-fix
Import filters fix
2016-04-28 10:47:00 +02:00
Christian Mandel
2325d24d6f Comments added for import-filters fix. 2016-04-28 10:27:25 +02:00
Christian Mandel
4397e07d7f Fix accidentally deleted first image during import. Lua is very picky about sparse table handling. 2016-04-28 00:43:21 +02:00
elman
f5a624cfb2 Remove exported image if it has no GPS data 2016-04-27 19:35:44 +02:00
elman
d2762fae73 Fixed issue with exporting RAW images 2016-04-27 19:25:03 +02:00
supertobi
22d7107305 Merge pull request #60 from chrik5/tagging_helpers
adding a modul to the UI with buttons and a replace function
2016-04-21 18:11:04 +02:00
chrik5
e22df23bc9 Tagging add label before clipboard list and make small enhancements 2016-04-21 17:08:44 +02:00
chrik5
200ef9a45e Tagging added new function replace and a modul 2016-04-21 15:54:59 +02:00
Jérémy Rosen
783194e253 update to newest API change in master 2016-04-17 20:46:32 +02:00
supertobi
204868d733 Use a file list instead of * to zip the images
kml_export - packs to kmz all files from dt.configuration.tmp_dir #53 
https://github.com/darktable-org/lua-scripts/issues/53
2016-04-17 12:33:39 +02:00
supertobi
f61a710e9b Merge pull request #55 from wpferguson/master
External editing with GIMP
2016-04-17 09:59:10 +02:00
Bill Ferguson
457731700c gimp doesn't like filenames with spaces in them, so added sanitize_filename to escape them. Updated gimp.po to reflect the changed line numbers. 2016-04-16 21:44:24 -04:00
Bill Ferguson
3dcb08cca3 Replaced checkIfFileExists with supertobi's fix and capitalized GIMP in gimp.po where I missed it. 2016-04-16 21:10:58 -04:00
supertobi
e3f1ff7d70 Strip accents from the filename, because GoogleEarth can't open them 2016-04-16 23:36:58 +02:00
Bill Ferguson
623b506691 Added check to see if the export would overwrite an existing file. If it would, the filename was incremented with _XX where XX was an increment starting at 01 and ending at 99. gimp.po line numbers adjusted to reflect the changes in code. 2016-04-15 23:58:33 -04:00
Bill Ferguson
6e5dbc0b83 Incorporated supertobi's suggestions. Replaced file and path splitting code with a regular expression (thanks Tobias Jakobs) to ensure filenames were handled correctly. Used the image data in the image table pairs instead of darktable.gui.action_images to ensure there were no mismatches as well as clean up the code nicely. Updated gimp.po to reflect the line number changes due to code refactoring. 2016-04-15 00:38:00 -04:00
Bill Ferguson
9c40a22c50 Removed gimp.lua from the top level 2016-04-14 22:21:32 -04:00
Bill Ferguson
9dbd1d9bda Incorporated supertobi's comments. Changed os.execute to os.rename to handle spaces and special characters. Capitalized GIMP in all print strings. Added de_DE translation. 2016-04-14 16:34:37 -04:00
Bill Ferguson
9693b017c4 Changed back to string.format in show_status but coded it correctly this time. 2016-04-10 16:27:49 -04:00
supertobi
670915ab36 fixed typo: will will -> will 2016-04-10 00:05:34 +02:00
Bill Ferguson
8224913b01 replaced string.format in show_status with the string and concatenation since string.format was having problems with the arguments. 2016-04-09 01:37:54 -04:00
supertobi
2b577f9755 improved the entry and file_chooser_button examples 2016-04-07 23:29:08 +02:00
Bill Ferguson
4556c9a055 Incorporated comments from supertobi, marking string for translation on line 128 and expanding variable names for lines 157-165 2016-04-07 11:59:41 -04:00
Bill Ferguson
679ce8b6ab Created gimp.lua to export an image to gimp for editing, then return the result and group it with the original image 2016-04-06 22:21:13 -04:00
Bill Ferguson
59eeb60594 Merge remote-tracking branch 'upstream/master' 2016-04-06 22:16:11 -04:00
Tobias Ellinghaus
6c4f9b2c03 Add script to copy & paste metadata between images
This not only takes care of tags (we already have a script for that in
contrib) but also color labels, rating and the things from the metadata
module.
2016-03-29 20:11:19 +02:00
Tobias Ellinghaus
f6e2037a1b Fix formatting of copyright header 2016-03-29 19:52:31 +02:00
supertobi
0c9d4a5de4 added tooltip to new_widget("entry") 2016-03-23 10:32:16 +01:00
supertobi
5006c9d6ea Added missing elevation vars, improved short distance view 2016-03-22 22:34:53 +01:00
supertobi
17a8c4f3d5 naming changes _ -> exported_image 2016-03-20 22:59:18 +01:00
supertobi
98cb1c2315 Merge pull request #52 from supertobi/patch-2
concertToThumbCommand -> convertToThumbCommand
2016-03-20 22:41:20 +01:00
supertobi
6cc5aa08e3 Merge pull request #49 from supertobi/patch-1
A geoJSON expor like the KML export
2016-03-20 22:40:45 +01:00
supertobi
ebda3865dc Update geoJSON_export.lua 2016-03-20 22:36:58 +01:00
supertobi
fb171a459e Update geoJSON_export.lua 2016-03-20 22:21:40 +01:00
supertobi
027a249837 _ -> exported_image 2016-03-20 22:03:41 +01:00
supertobi
2a2bb7199e concertToThumbCommand -> convertToThumbCommand 2016-03-20 21:51:26 +01:00
supertobi
f64892d010 concertToThumbCommand -> convertToThumbCommand 2016-03-20 21:50:25 +01:00
Boucman
d023d7f3e4 Merge pull request #51 from supertobi/patch-2
marked vars as local
2016-03-18 11:11:18 +01:00
supertobi
ef96bfa98c marked vars as local 2016-03-17 22:35:47 +01:00
supertobi
b2ee46804b marked vars as local, changed gettext domain 2016-03-17 22:33:27 +01:00
supertobi
7c9c277cf8 A geoJSON expor like the KML export 2016-03-15 22:31:04 +01:00
houz
3e376ebc74 Merge pull request #48 from supertobi/patch-3
Create moduleExample.lua
2016-03-14 12:08:44 +01:00
supertobi
102ea2da7a Added comment
This is an alternative way to the "{}" syntax to set a property
2016-03-13 21:11:04 +01:00
supertobi
e1a2fbfaa6 Copy past error in the copyright line 2016-03-13 21:07:32 +01:00
houz
c1aecf2b37 Merge pull request #47 from supertobi/patch-2
Update kml_export.lua
2016-03-12 14:26:25 +01:00
supertobi
b2754e3036 Create moduleExample.lua
lua_gui_example
2016-03-12 00:09:37 +01:00
supertobi
abbb740753 Update kml_export.lua
small changes (comments and spacing)
2016-03-11 23:57:13 +01:00
Boucman
7504224c2f Merge pull request #46 from marco44/master
Bump autostyle as 3.0.0 compatible
2016-03-08 10:28:14 +01:00
marco44
57b990409a Mark autostyle as 3.0.0 compatible 2016-03-07 18:07:04 +01:00
Boucman
cff5e06d62 Merge pull request #45 from gRuGo/patch-1
Update cr2hdr.lua
2016-03-05 22:23:26 +01:00
gRuGo
a543b409cb Update cr2hdr.lua
for darktable 2.0
2016-03-05 20:21:42 +01:00
Jérémy Rosen
e57d2f4afa force check for 3.0.0 since this is the version the repo is compatible with 2016-03-05 11:20:17 +01:00
Jérémy Rosen
9da0173e05 mark save-selection as 3.0.0 compatible 2016-03-05 10:51:12 +01:00
Tobias Ellinghaus
a21b171d96 Add a script that allows running enfuse on images 2016-03-02 14:42:38 +01:00
Boucman
2569e7ed8e Merge pull request #44 from supertobi/patch-1
Move api_version.lua into examples
2016-02-16 14:43:59 +01:00
supertobi
25d2eade8c Move api_version.lua into examples
As this script is more usable for developers then for 'normal' users I moved it into examples.
2016-02-16 13:09:16 +01:00
houz
43b949966d Merge pull request #43 from supertobi/master
Translations
2016-02-03 12:26:52 +01:00
supertobi
08205b96cd Update hugin.po
zusammenzufügen
2016-02-02 14:54:09 +01:00
supertobi
e2e63bbfc8 Update gps_select.po
GPS Informationen -> GPS-Informationen
2016-02-02 14:51:19 +01:00
supertobi
24d1a7dd67 Update calcDistance.po
2x "mit"
2016-02-02 14:48:45 +01:00
supertobi
9b4e46b625 Update gps_select.po
GPS Informationen -> GPS-Informationen
2016-02-02 14:48:17 +01:00
supertobi
e47a335dec Update calcDistance.lua
translations
2016-01-31 23:27:34 +01:00
supertobi
d46f7023d5 Update geo_uri.lua
translations
2016-01-31 23:27:00 +01:00
supertobi
19bef60752 Update gps_select.lua
translate
2016-01-31 23:26:23 +01:00
supertobi
5ff73657e1 Update hugin.lua
translations
2016-01-31 23:25:49 +01:00
supertobi
fb8da04a18 Update slideshowMusic.lua
translations
2016-01-31 23:25:18 +01:00
supertobi
3ee50a290f Create slideshowMusic.po 2016-01-31 23:23:45 +01:00
supertobi
71ea05598f Create hugin.po 2016-01-31 23:22:45 +01:00
supertobi
96d5c71e0d Create gps_select.po 2016-01-31 23:21:51 +01:00
supertobi
07318eb7aa Create geo_uri.po 2016-01-31 23:20:27 +01:00
supertobi
2ef235dddd Create calcDistance.po 2016-01-31 23:19:30 +01:00
Boucman
f7cc9865cc Merge pull request #42 from supertobi/patch-3
Update kml_export.lua - use os.remove(image)
2016-01-31 22:07:56 +01:00
supertobi
c323ce6cbb Update kml_export.lua
use os.remove(image)
2016-01-31 00:57:43 +01:00
Boucman
5d2ddc490a Merge pull request #41 from supertobi/patch-1
Update gettextExample.lua
2016-01-30 10:26:37 +01:00
Boucman
40463290a6 Merge pull request #39 from supertobi/master
added gettext to kml_export.lua
2016-01-30 10:26:27 +01:00
supertobi
6b4faac2cb Update kml_export.lua
function _(msgid)
2016-01-29 23:09:32 +01:00
supertobi
077a7de605 Update gettextExample.lua
function _(msgid)
2016-01-29 23:01:05 +01:00
supertobi
180bc06c06 Update kml_export.lua 2016-01-29 22:35:57 +01:00
supertobi
72a97ecbd6 Update gettextExample.lua 2016-01-29 22:18:54 +01:00
supertobi
87a6ed3e46 Update gettextExample.lua
bindtextdomain changed: ~/
2016-01-29 14:26:31 +01:00
supertobi
95d8e777db Update gettextExample.lua 2016-01-29 14:21:46 +01:00
supertobi
d028ecfc55 Update gettextExample.lua
improved readability
2016-01-26 22:40:36 +01:00
supertobi
225da821e4 Update kml_export.po
Added 
msgid "KML/KMZ Export"
msgstr "KML/KMZ Expor
2016-01-22 23:34:29 +01:00
supertobi
7cd4023f5c Update kml_export.lua
gettext bugfix
2016-01-22 23:30:58 +01:00
supertobi
2379832cc2 Create kml_export.po 2016-01-22 15:41:07 +01:00
supertobi
cb46e090dd Update kml_export.lua
small bugfix CreatePath
2016-01-22 15:34:51 +01:00
supertobi
a656f0f304 Update kml_export.lua
add gettext
2016-01-22 15:15:33 +01:00
Boucman
564fa313f1 Merge pull request #38 from supertobi/master
Move example scripts in a new folder to seperate them from the 'usefull' scripts
2016-01-22 10:09:31 +01:00
supertobi
47cd618bf4 Delete gettextExample.mo
No binary or generated files in git
2016-01-22 09:52:05 +01:00
supertobi
ae709a1d9b Rename contrib/de_DE/LC_MESSAGES/gettextExample.po to examples/de_DE/LC_MESSAGES/gettextExample.po 2016-01-22 09:49:22 +01:00
supertobi
0812d96068 Rename contrib/gettextExample.lua to examples/gettextExample.lua 2016-01-22 09:48:23 +01:00
supertobi
86911933db Rename contrib/preferenceExamples.lua to examples/preferenceExamples.lua 2016-01-22 09:47:19 +01:00
supertobi
69d5c139f6 Rename official/hello_world.lua to examples/hello_world.lua 2016-01-22 09:46:39 +01:00
supertobi
405b9a19f9 Merge pull request #5 from darktable-org/master
changes from master
2016-01-13 13:43:53 +01:00
Boucman
c4a696cbc4 Merge pull request #36 from supertobi/master
Update from my fork
2016-01-11 13:54:26 +01:00
Boucman
bb0e4997de Merge pull request #37 from supertobi/patch-3
Update kml_export.lua
2016-01-11 13:51:24 +01:00
supertobi
bc1b908063 Update kml_export.lua
- support of image.title and image.description
- support of image.elevation
- don't add to many images to the kmz file
2016-01-10 22:28:53 +01:00
Tobias Jakobs
29c522484c gettextExample.lua with po and mo files 2016-01-07 22:01:51 +01:00
Boucman
5b6585b115 Merge pull request #32 from supertobi/patch-3
Update calcDistance.lua
2016-01-07 17:09:45 +01:00
Boucman
3715c69c02 Merge pull request #29 from supertobi/patch-2
Update hugin.lua
2016-01-07 17:07:36 +01:00
Boucman
3d3b457c92 Merge pull request #28 from supertobi/patch-1
Update gps_select.lua
2016-01-07 17:07:14 +01:00
houz
e4f5d44658 Merge pull request #31 from wpferguson/wpferguson-patch-1
Update selection_to_pdf.lua
2016-01-07 12:30:33 +01:00
Tobias Ellinghaus
fc7a25ca4d Mark most official scripts as compatible with dt2 2016-01-07 11:23:34 +01:00
supertobi
1d3a44a157 Update calcDistance.lua
Add the elevation to the calculation of the distance
2016-01-07 09:08:35 +01:00
wpferguson
319b44f153 Merge pull request #1 from wpferguson/wpferguson-patch-1
Update selection_to_pdf.lua
2016-01-06 10:54:16 -05:00
wpferguson
98a4144403 Update selection_to_pdf.lua
Added API version 3.0.0 for compatibility with Darktable 2.0.  Tested with Darktable 2.0.
2016-01-06 10:51:56 -05:00
supertobi
a819140c88 Update hugin.lua
Tested with darktable 2.0
2016-01-05 22:12:57 +01:00
supertobi
cba5c65608 Update gps_select.lua
Tested with darktable 2.0
2016-01-05 22:05:18 +01:00
supertobi
eff4a3abcb Update geo_uri.lua
removed the old warning
2016-01-05 10:28:31 +01:00
supertobi
2e0ccef3f5 Update geo_uri.lua
Changes suggested from Boucman
2016-01-05 10:22:47 +01:00
Boucman
429a157715 Merge pull request #26 from supertobi/patch-2
Update kml_export.lua
2016-01-05 09:18:35 +01:00
Boucman
76065ee93f Merge pull request #27 from supertobi/patch-3
Update preferenceExamples.lua
2016-01-05 09:18:23 +01:00
Boucman
97def2240f Merge pull request #25 from supertobi/patch-1
Update calcDistance.lua
2016-01-05 09:18:02 +01:00
supertobi
15cd18a5c4 Update preferenceExamples.lua
Tested with darktable 2.0
2016-01-04 23:02:01 +01:00
supertobi
0b3b095eac Update kml_export.lua
Tested with darktable 2.0
2016-01-04 23:00:33 +01:00
supertobi
38bda12c4b Update calcDistance.lua
Tested with darktable 2.0
2016-01-04 22:59:18 +01:00
supertobi
d2a34226a6 Update slideshowMusic.lua
Tested with darktable 2.0
2016-01-04 22:53:10 +01:00
supertobi
92dcb29010 Update slideshowMusic.lua
Test if old_view is nil
2016-01-04 22:52:31 +01:00
supertobi
d4cc869227 Merge pull request #4 from darktable-org/master
Merge with master
2016-01-04 22:49:38 +01:00
houz
291ff86686 Merge pull request #22 from spaceChRiS/import-filters-fix
Take care for code in for loop to be run even for the last image.
2016-01-04 17:23:33 +01:00
Tobias Ellinghaus
895ad62757 Fix line endings 2016-01-04 14:49:12 +01:00
houz
4acfa36b57 Merge pull request #21 from ribmo/master
Shortcuts to rate/reject all images within a group
2016-01-04 14:47:38 +01:00
spaceChRiS
fe18256c25 Remove extra line from image list. 2016-01-04 10:44:41 +01:00
spaceChRiS
39531eb4f0 Take care for code in for loop to be run even for the last image.
The problem: If the last image is a jpeg/raw pair, the code to remove the jpeg from the import list is not run since it is the last image. This is solved by adding an empty line to the images array. It will be counted as new base and therefore the jpeg removal code will be run one more time. I don't know if this is a good solution but I think it solves the problem without adding complexity.
2016-01-03 10:44:14 +01:00
ribmo
28d73b44a6 Shortcuts to rate/reject all images within a group 2016-01-02 13:01:50 +00:00
Boucman
3983a8a1ba Merge pull request #20 from mali/fix-typo
Fix some typos
2015-12-31 10:03:35 +01:00
Laurent Navet
08151e7e21 Fix some typos 2015-12-30 22:02:18 +01:00
Boucman
446927f947 Merge pull request #19 from chrik5/tagging
make check_api_version work with API 3
2015-12-29 10:56:49 +01:00
chrik5
5d72904849 make check_api_version work with API 3 2015-12-27 14:52:21 +01:00
Jérémy Rosen
ff1f076536 Revert "disable image_path_in_ui since it relies on a disabled feature"
This reverts commit 1dc1f5f9ef.
2015-12-23 15:21:38 +01:00
supertobi
c56766ef85 Fixed spaces 2015-12-16 13:51:35 +01:00
supertobi
eff8953207 Create geo_uri.lua
Maps in 3.20 will be able to handle the 'geo' URI scheme. That means that if you enter the shortcut Gnome Maps will present the current window if there is one and go to location, and start a new instance of maps if there is none.
2015-12-15 10:41:10 +01:00
supertobi
2ba1ae7a23 Merge pull request #3 from darktable-org/master
changes from master
2015-09-29 21:52:24 +02:00
56 changed files with 4101 additions and 452 deletions

View File

@@ -41,7 +41,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})
darktable.configuration.check_version(...,{2,0,2},{2,1,0},{3,0,0})
-- Receive the event triggered
function autostyle_apply_one_image_event(event,image)
@@ -118,8 +118,7 @@ end
function get_stdout(cmd)
-- Open the command, for reading
local fd = assert(io.popen(cmd, 'r'))
-- yield to other lua threads until data is ready to be read
coroutine.yield("FILE_READABLE",fd)
dt.control.read(fd)
-- slurp the whole file
local data = assert(fd:read('*a'))

View File

@@ -1,6 +1,6 @@
--[[
This file is part of darktable,
Copyright 2014 by Tobias Jakobs.
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
@@ -26,7 +26,15 @@ USAGE
]]
local dt = require "darktable"
dt.configuration.check_version(...,{2,0,1})
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()
@@ -35,6 +43,9 @@ local function calcDistance()
local lon1 = 0;
local lat2 = 0;
local lon2 = 0;
local ele1 = 0;
local ele2 = 0;
local i = 0;
local sel_images = dt.gui.selection()
@@ -49,10 +60,12 @@ local function calcDistance()
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
@@ -71,10 +84,23 @@ local function calcDistance()
local angle = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a));
local distance = earthRadius * angle; -- Distance in km
dt.print(distance.." 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")
dt.register_event("shortcut",calcDistance,_("Calculate the distance from latitude and longitude in km"))

75
contrib/clear_GPS.lua Normal file
View File

@@ -0,0 +1,75 @@
--[[
clear_GPS.lua - export and edit with GIMP
Copyright (C) 2016 Bill Ferguson <wpferguson@gmail.com>.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
]]
--[[
clear_GPS - clear GPS data from selected image(s)
This shortcut removes the GPS coordinate data from the selected images.
ADDITIONAL SOFTWARE NEEDED FOR THIS SCRIPT
* None
USAGE
* require this script from your main lua file
* select an image or images
* click the shortcut, clear GPS data
BUGS, COMMENTS, SUGGESTIONS
* Send to Bill Ferguson, wpferguson@gmail.com
CHANGES
]]
local dt = require "darktable"
local gettext = dt.gettext
-- not a number
local NaN = 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("clear_GPS",dt.configuration.config_dir.."/lua/")
local function _(msgid)
return gettext.dgettext("clear_GPS", msgid)
end
local function clear_GPS(images)
for _, image in ipairs(images) do
-- set the location information to Not a Number (NaN) so it displays correctly
image.elevation = NaN
image.latitude = NaN
image.longitude = NaN
end
end
dt.gui.libs.image.register_action(
_("clear GPS data"),
function(event, images) clear_GPS(images) end,
"clear GPS data"
)
dt.register_event(
"shortcut",
function(event, shortcut) clear_GPS(dt.gui.action_images) end,
"clear GPS data"
)

View File

@@ -1,6 +1,7 @@
--[[
This file is part of darktable,
copyright 2014-2015 by Christian Kanzian.
Copyright 2014-2016 by Christian Kanzian
Copyright 2016 by Holger Klemm
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
@@ -17,8 +18,9 @@
]]
--[[
(MULTI-)COPY ATTACH DETACH TAG
A simple script that will create three shortcuts to copy, attach and detach image tags.
(MULTI-)COPY ATTACH DETACH REPLACE TAGS
This script that will create four shortcuts and add a modul in lighttable mode to copy,
paste, replace and remove tags from images.
INSTALATION
* copy this file in $CONFIGDIR/lua/ where CONFIGDIR is your darktable configuration directory
@@ -27,17 +29,31 @@ INSTALATION
USAGE
* set the shortcuts for copy, attach and detach in the preferences dialog
* <your shortcut1> copy will create a list of tags from all selected images
* <your shortcut2> attaches copied tags to selected images, whereby
* <your shortcut2> paste copied tags to selected images, whereby
darktable internal tags starting with 'darktable|' will not be touched
* <your shortcut3> detach removes all expect darktable internal tags from selected images
* <your shortcut3> removes all expect darktable internal tags from selected images
* <your shortcut4> replaces all tags expect darktable internals
]]
local dt = require "darktable"
dt.configuration.check_version(...,{2,0,0})
local gettext = dt.gettext
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("copy_attach_detach_tags",dt.configuration.config_dir.."/lua/")
local function _(msgid)
return gettext.dgettext("copy_attach_detach_tags", msgid)
end
local image_tags = {}
local taglist_label = dt.new_widget("label"){selectable = true, ellipsize = "middle", halign = "start"}
taglist_label.label = ""
local function mcopy_tags()
local sel_images = dt.gui.action_images
local tag_list_tmp = {}
@@ -65,15 +81,30 @@ local function mcopy_tags()
end
end
dt.print("Image tags copied ...")
return(image_tags)
dt.print(_('Image tags copied ...'))
--create UI tag list
local taglist = ""
for _,tag in ipairs(image_tags) do
if taglist == "" then
taglist = tostring(tag)
else
taglist = taglist.."\n"..tostring(tag)
end
end
taglist_label.label = taglist
return(image_tags)
end
-- attach copied tags to all selected images
local function attach_tags()
if next(image_tags) == nil then
dt.print("No tags to attached, please copy tags first.")
dt.print(_('No tags to attached, please copy tags first.'))
return true
end
local sel_images = dt.gui.action_images
@@ -96,12 +127,9 @@ local function attach_tags()
end
end
end
dt.print("Tags attached ...")
dt.print(_('Tags attached ...'))
end
local function detach_tags()
local sel_images = dt.gui.action_images
@@ -115,24 +143,80 @@ local function detach_tags()
end
end
end
dt.print("Tags removed from image(s).")
dt.print(_('Tags removed from image(s).'))
end
local function replace_tags()
detach_tags()
attach_tags()
dt.print(_('Tags replaced'))
end
-- create modul Tagging addons
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"}
-- create modul
dt.register_lib("tagging_addon","Tagging addon",true,false,{
[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
},
nil,
nil
)
-- shortcut for copy
dt.register_event("shortcut",
mcopy_tags,
"copy tags from selected image(s)")
_('copy tags from selected image(s)'))
-- shortcut for attach
dt.register_event("shortcut",
attach_tags,
"attach tags to selected image(s)")
_('paste tags to selected image(s)'))
-- shortcut for detaching tags
dt.register_event("shortcut",
detach_tags,
"detach tags to selected image(s)")
_('remove tags from selected image(s)'))
-- shortcut for replace tags
dt.register_event("shortcut",
replace_tags,
_('replace tags from selected image(s)'))
-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua
-- kate: tab-indents: off; indent-width 2; replace-tabs on; remove-trailing-space on;

View File

@@ -34,8 +34,8 @@ USAGE
local darktable = require "darktable"
-- Tested with darktable 1.6.2
darktable.configuration.check_version(...,{2,0,2})
-- Tested with darktable 2.0.1
darktable.configuration.check_version(...,{2,0,0},{3,0,0})
local queue = {}
local processed_files = {}
@@ -60,7 +60,7 @@ end
local function convert_image(image)
if string.sub(image.filename, -3) == "CR2" then
local filename = image.path .. "/" .. image.filename
local result = coroutine.yield("RUN_COMMAND", "cr2hdr " .. filename)
local result = dt.control.execute( "cr2hdr " .. filename)
local out_filename = string.gsub(filename, ".CR2", ".DNG")
local file = io.open(out_filename)
if file then

View File

@@ -0,0 +1,22 @@
# 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: 2016-01-31 22:57+0100\n"
"PO-Revision-Date: 2016-01-31 23:02+0100\n"
"Language: de_DE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Last-Translator: Tobias Jakobs <tobias.jakobs@gmail.com>\n"
"Language-Team: \n"
"X-Generator: Poedit 1.8.4\n"
#: calcDistance.lua:93
msgid "Calculate the distance from latitude and longitude in km"
msgstr "Errechne die Entfernung mit Hilfe des Längen- und Breitengrads in km"

View File

@@ -0,0 +1,28 @@
# 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.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-09-07 22:25-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Bill Ferguson <wpferguson@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.5.4\n"
"Language: de_DE\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-KeywordsList: gettext;dgettext:2;dcgettext:2ngettext:1,2;"
"dngettext:2,3\n"
"X-Poedit-Basepath: .\n"
#: clear_GPS.lua:62
msgid "clear GPS data"
msgstr "GPS-Daten löschen"

View File

@@ -0,0 +1,75 @@
# Holger Klemm, 2016.
# Christian Kanzian <christian.kanzian@gmx.at>, 2016.
msgid ""
msgstr ""
"Project-Id-Version: Lua image path\n"
"POT-Creation-Date: 2016-01-07 20:33+0100\n"
"PO-Revision-Date: 2016-10-18 15:34+0200\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"
"X-Generator: Lokalize 1.5\n"
"X-Poedit-Basepath: .\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Poedit-KeywordsList: \n"
"X-Poedit-SearchPath-0: .\n"
#: copy_attach_detach_tags.lua:10
msgid "Image tags copied ..."
msgstr "Bild Tags kopiert ..."
#: copy_attach_detach_tags.lua:10
msgid "No tags to attached, please copy tags first."
msgstr "Es wurden keine Tags eingefügt. Bitte zuerst die Tags kopieren."
#: copy_attach_detach_tags.lua:10
msgid "Tags attached ..."
msgstr "Tags anhängen ..."
#: copy_attach_detach_tags.lua:10
msgid "Tags removed from image(s)."
msgstr "Tags von Bildern wurden gelöscht."
#: copy_attach_detach_tags.lua:10
msgid "Tags replaced"
msgstr "Tag ersetzen"
#: copy_attach_detach_tags.lua:10
msgid "multi copy tags"
msgstr "Tags kopieren"
#: copy_attach_detach_tags.lua:10
msgid "paste tags"
msgstr "Tags anhängen"
#: copy_attach_detach_tags.lua:10
msgid "replace tags"
msgstr "Tags ersetzen"
#: copy_attach_detach_tags.lua:10
msgid "remove all tags"
msgstr "Tags löschen"
#: copy_attach_detach_tags.lua:10
msgid "tag clipboard"
msgstr "Zwischenablage"
#: copy_attach_detach_tags.lua:10
msgid "copy tags from selected image(s)"
msgstr "Tags von ausgewählten Bildern kopieren"
#: copy_attach_detach_tags.lua:10
msgid "paste tags to selected image(s)"
msgstr "Tags an ausgewählte Bilder anhängen"
#: copy_attach_detach_tags.lua:10
msgid "remove tags from selected image(s)"
msgstr "Tags von ausgewählten Bildern löschen"
#: copy_attach_detach_tags.lua:10
msgid "replace tags from selected image(s)"
msgstr "Tags von ausgewählten Bildern ersetzen"

View File

@@ -0,0 +1,30 @@
# 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: 2016-01-31 22:58+0100\n"
"PO-Revision-Date: 2016-01-31 23:13+0100\n"
"Language: de_DE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Last-Translator: Tobias Jakobs <tobias.jakobs@gmail.com>\n"
"Language-Team: \n"
"X-Generator: Poedit 1.8.4\n"
#: geo_uri.lua:55
msgid "gnome-maps not found"
msgstr "gnome-maps wurde nicht gefunden"
#: geo_uri.lua:81
msgid "Command failed ..."
msgstr "Aufruf fehlgeschlagen ..."
#: geo_uri.lua:88
msgid "Open Location in Gnome Maps"
msgstr "Öffnet den Ort in Gnome Maps"

View File

@@ -0,0 +1,43 @@
# 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: gimp\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-04-13 23:50-0400\n"
"PO-Revision-Date: 2016-04-14 00:11-0500\n"
"Last-Translator: Bill Ferguson <wpferguson@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.5.4\n"
"Language: de_DE\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-KeywordsList: gettext;dgettext:2;dcgettext:2ngettext:1,2;"
"dngettext:2,3\n"
"X-Poedit-Basepath: .\n"
#: gimp.lua:194
#, lua-format
msgid "Export Image %i/%i"
msgstr "Exportiere Bild %i/%i"
#: gimp.lua:242
msgid "Unable to move edited file into collection. Leaving it as %s"
msgstr "Die bearbeitete Datei kann nicht in die Sammlung aufgenommen werden. Bearbeitete Datei ist %s"
#: gimp.lua:251
msgid "GIMP not found"
msgstr "GIMP nicht gefunden"
#: gimp.lua:266
msgid "Launching GIMP..."
msgstr "Starten von GIMP"
#: gimp.lua:313
msgid "Edit with GIMP"
msgstr "Bearbeiten mit GIMP"

View File

@@ -0,0 +1,26 @@
# 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: 2016-01-31 22:58+0100\n"
"PO-Revision-Date: 2016-01-31 23:05+0100\n"
"Language: de_DE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Last-Translator: Tobias Jakobs <tobias.jakobs@gmail.com>\n"
"Language-Team: \n"
"X-Generator: Poedit 1.8.4\n"
#: gps_select.lua:59
msgid "Select all images with GPS information"
msgstr "Markiert alle Bilder mit GPS-Informationen"
#: gps_select.lua:60
msgid "Select all images without GPS information"
msgstr "Markiert alle Bilder ohne GPS-Informationen"

View File

@@ -0,0 +1,42 @@
# 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: 2016-01-31 22:59+0100\n"
"PO-Revision-Date: 2016-01-31 23:09+0100\n"
"Language: de_DE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Last-Translator: Tobias Jakobs <tobias.jakobs@gmail.com>\n"
"Language-Team: \n"
"X-Generator: Poedit 1.8.4\n"
#: hugin.lua:73
msgid "hugin not found"
msgstr "Hugin wurde nicht gefunden"
#: hugin.lua:97
msgid "Will try to stitch now"
msgstr "Versuche Bilder zusammenzufügen"
#: hugin.lua:102
msgid "Creating pto file"
msgstr "Erzeuge pto Datei"
#: hugin.lua:105
msgid "Running Assistent"
msgstr "Starte den Assistenten"
#: hugin.lua:118
msgid "Command hugin failed ..."
msgstr "Aufruf von hugin fehlgeschlagen ..."
#: hugin.lua:124
msgid "Hugin Panorama"
msgstr "Hugin Panorama"

View File

@@ -0,0 +1,46 @@
msgid ""
msgstr ""
"Project-Id-Version: Lua gettextTest\n"
"POT-Creation-Date: 2016-01-22 15:33+0100\n"
"PO-Revision-Date: 2016-01-22 23:28+0100\n"
"Last-Translator: Tobias Jakobs <tobias.jakobs@gmail.com>\n"
"Language-Team: \n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.4\n"
"X-Poedit-Basepath: .\n"
"Plural-Forms: nplurals=2;t" plural=(n != 1);\n"
"X-Poedit-KeywordsList: gettext;dgettext:2;dcgettext:2;ngettext:1,2;dngettext:2,3\n"
"X-Poedit-SearchPath-0: .\n"
msgid "KML/KMZ Export"
msgstr "KML/KMZ Expor
msgid "Export Image %i/%i"
msgstr "Exportiere Bild %i/%i"
msgid "KML export: Open KML/KMZ file after export"
msgstr "KML export: KML/KMZ-Datei nach dem exportieren öffnen"
msgid "Opens the KML file after the export with the standard programm for KML files"
msgstr "Öffnet die KML-Datei mit dem Standardprogram für KML-Dateien"
msgid "KML export: Export directory"
msgstr "KML export: Export-Verzeichnis"
msgid "A directory that will be used to export the KML/KMZ files"
msgstr "Verzeichnis in das die KML/KMZ-Dateien exportiert werden"
msgid "KML export: Connect images with path"
msgstr "KML export: Bilder mit einer Linie verbinden"
msgid "connect all images with a path"
msgstr "Verbinde alle Bilder mit einer Linie"
msgid "KML export: Create KMZ file"
msgstr "KML export: KMZ-Datei erstellen"
msgid "Compress all imeges to one KMZ file"
msgstr "Alle Bilder in einer KMZ-Datei komprimieren"

View File

@@ -0,0 +1,30 @@
# 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: 2016-01-31 22:59+0100\n"
"PO-Revision-Date: 2016-01-31 23:13+0100\n"
"Language: de_DE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Last-Translator: Tobias Jakobs <tobias.jakobs@gmail.com>\n"
"Language-Team: \n"
"X-Generator: Poedit 1.8.4\n"
#: slideshowMusic.lua:80
msgid "Slideshow background music file"
msgstr "Diashow Hintergrundmusik-Datei"
#: slideshowMusic.lua:84
msgid "Play slideshow background music"
msgstr "Diashow Hintergrundmusik abspielen"
#: slideshowMusic.lua:85
msgid "Plays music with rhythmbox if a slideshow starts"
msgstr "Musik mit Rhythmbox abspielen, wenn die Diashow beginnt"

View File

@@ -0,0 +1,22 @@
# 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: 2016-01-31 22:57+0100\n"
"PO-Revision-Date: 2016-10-03 14:58+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.9\n"
#: calcDistance.lua:93
msgid "Calculate the distance from latitude and longitude in km"
msgstr "Calcule la distance en km entre les positions GPS de deux images"

View File

@@ -0,0 +1,27 @@
# 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: 2016-09-07 22:25-0400\n"
"PO-Revision-Date: 2016-10-03 14:55+0200\n"
"Last-Translator: Pascal Obry <pascal@obry.net>\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.9\n"
"Language: fr_FR\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-KeywordsList: gettext;dgettext:2;dcgettext:2ngettext:1,2;"
"dngettext:2,3\n"
"X-Poedit-Basepath: .\n"
"Language-Team: \n"
#: clear_GPS.lua:62
msgid "clear GPS data"
msgstr "effacer données GPS"

View File

@@ -0,0 +1,30 @@
# 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: 2016-01-31 22:58+0100\n"
"PO-Revision-Date: 2016-10-03 15:05+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.9\n"
#: geo_uri.lua:55
msgid "gnome-maps not found"
msgstr "gnome-maps non disponible"
#: geo_uri.lua:81
msgid "Command failed ..."
msgstr "La commande a échouée ..."
#: geo_uri.lua:88
msgid "Open Location in Gnome Maps"
msgstr "Ouvre la position dans Gnome Maps"

View File

@@ -0,0 +1,42 @@
# 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: gimp\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-04-13 23:50-0400\n"
"PO-Revision-Date: 2016-10-03 15:06+0200\n"
"Last-Translator: Pascal Obry <pascal@obry.net>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.9\n"
"Language: fr_FR\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-KeywordsList: gettext;dgettext:2;dcgettext:2ngettext:1,2;dngettext:2,3\n"
"X-Poedit-Basepath: .\n"
"Language-Team: \n"
#: gimp.lua:194
#, lua-format
msgid "Export Image %i/%i"
msgstr "Export image %i/%i"
#: gimp.lua:242
msgid "Unable to move edited file into collection. Leaving it as %s"
msgstr "Impossible de déplacer l'image modifiée dans la collection. L'image est %s"
#: gimp.lua:251
msgid "GIMP not found"
msgstr "GIMP n'est pas trouvé"
#: gimp.lua:266
msgid "Launching GIMP..."
msgstr "Lancement de GIMP..."
#: gimp.lua:313
msgid "Edit with GIMP"
msgstr "Éditer avec GIMP"

View File

@@ -0,0 +1,26 @@
# 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: 2016-01-31 22:58+0100\n"
"PO-Revision-Date: 2016-10-03 15:03+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.9\n"
#: gps_select.lua:59
msgid "Select all images with GPS information"
msgstr "Sélectionner toutes les images avec des informations GPS"
#: gps_select.lua:60
msgid "Select all images without GPS information"
msgstr "Sélectionner toutes les images sans information GPS"

View File

@@ -0,0 +1,42 @@
# 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: 2016-01-31 22:59+0100\n"
"PO-Revision-Date: 2016-10-03 15:08+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.9\n"
#: hugin.lua:73
msgid "hugin not found"
msgstr "hugin non disponible"
#: hugin.lua:97
msgid "Will try to stitch now"
msgstr "essayer de coller maintenant"
#: hugin.lua:102
msgid "Creating pto file"
msgstr "création du fichier pto"
#: hugin.lua:105
msgid "Running Assistent"
msgstr "lancement assistant"
#: hugin.lua:118
msgid "Command hugin failed ..."
msgstr "hugin a retourné une erreur"
#: hugin.lua:124
msgid "Hugin Panorama"
msgstr "panorama hugin"

View File

@@ -0,0 +1,46 @@
msgid ""
msgstr ""
"Project-Id-Version: Lua gettextTest\n"
"POT-Creation-Date: 2016-01-22 15:33+0100\n"
"PO-Revision-Date: 2016-10-03 15:15+0200\n"
"Last-Translator: Pascal Obry <pascal@obry.net>\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.9\n"
"X-Poedit-Basepath: .\n"
"Plural-Forms: nplurals=2;t\" plural=(n != 1);\n"
"X-Poedit-KeywordsList: gettext;dgettext:2;dcgettext:2;ngettext:1,2;dngettext:2,3\n"
"X-Poedit-SearchPath-0: .\n"
msgid "KML/KMZ Export"
msgstr "export kml/kmz"
msgid "Export Image %i/%i"
msgstr "export image %i/%i"
msgid "KML export: Open KML/KMZ file after export"
msgstr "export kml: ouvrir le fichier kml/kmz après l'export"
msgid "Opens the KML file after the export with the standard programm for KML files"
msgstr "ouvrir le fichier kml après l'export avec le lecteur kml par défaut"
msgid "KML export: Export directory"
msgstr "export kml : répertoire pour l'export"
msgid "A directory that will be used to export the KML/KMZ files"
msgstr "Le répertoire utiliser pour les fichiers d'export kml/kmz"
msgid "KML export: Connect images with path"
msgstr "export kml: connecter les images avec un chemin"
msgid "connect all images with a path"
msgstr "connecter toutes les images avec un chemin"
msgid "KML export: Create KMZ file"
msgstr "export kml: créer un fichier kmz"
msgid "Compress all imeges to one KMZ file"
msgstr "compresser les images en un fichier kmz"

View File

@@ -0,0 +1,30 @@
# 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: 2016-01-31 22:59+0100\n"
"PO-Revision-Date: 2016-10-03 15:10+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.9\n"
#: slideshowMusic.lua:80
msgid "Slideshow background music file"
msgstr "musique pour le diaporama"
#: slideshowMusic.lua:84
msgid "Play slideshow background music"
msgstr "jouer la musique du diaporama"
#: slideshowMusic.lua:85
msgid "Plays music with rhythmbox if a slideshow starts"
msgstr "jouer la musique avec rhythmbox lorsque le diaporama démarre"

321
contrib/geoJSON_export.lua Normal file
View File

@@ -0,0 +1,321 @@
--[[
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 geoJSON export script
ADDITIONAL SOFTWARE NEEDED FOR THIS SCRIPT
* mkdir
* convert (ImageMagick)
* xdg-open
* xdg-user-dir
WARNING
This script is only tested with Linux
USAGE
* require this script from your main Lua file
]]
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("geoJSON_export",dt.configuration.config_dir.."/lua/")
local function _(msgid)
return gettext.dgettext("geoJSON_export", msgid)
end
-- Sort a table
local function spairs(_table, order) -- Code copied from http://stackoverflow.com/questions/15706270/sort-a-table-in-lua
-- collect the keys
local keys = {}
for _key in pairs(_table) do keys[#keys + 1] = _key end
-- if order function given, sort by it by passing the table and keys a, b,
-- otherwise just sort the keys
if order then
table.sort(keys, function(a,b) return order(_table, a, b) end)
else
table.sort(keys)
end
-- return the iterator function
local i = 0
return function()
i = i + 1
if keys[i] then
return keys[i], _table[keys[i]]
end
end
end
local function show_status(storage, image, format, filename, number, total, high_quality, extra_data)
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
return
end
if not checkIfBinExists("convert") then
return
end
if not checkIfBinExists("xdg-open") then
return
end
if not checkIfBinExists("xdg-user-dir") then
return
end
dt.print_error("Will try to export geoJSON file now")
local xportDirectory = dt.preferences.read("geoJSON_export","ExportDirectory","string")
-- Creates dir if not exsists
local imageFoldername = "files/"
local mkdirCommand = "mkdir -p "..exportDirectory.."/"..imageFoldername
dt.control.execute( mkdirCommand)
-- Create the thumbnails
for image,exported_image in pairs(image_table) 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
local path, filename, filetype = string.match(image, "(.-)([^\\/]-%.?([^%.\\/]*))$")
filename = string.upper(string.gsub(filename,"%.", "_"))
-- 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
-- 120x120, allowing it to run faster by avoiding returning full-resolution images to GraphicsMagick for the
-- subsequent resizing operation. The '-resize 120x120' specifies the desired dimensions of the output image. It
-- will be scaled so its largest dimension is 120 pixels. The '+profile "*"' removes any ICM, EXIF, IPTC, or other
-- profiles that might be present in the input and aren't needed in the thumbnail.
local convertToThumbCommand = "convert -size 96x96 "..exported_image.." -resize 92x92 -mattecolor \"#FFFFFF\" -frame 2x2 +profile \"*\" "..exportDirectory.."/"..imageFoldername.."thumb_"..filename..".jpg"
dt.control.execute( convertToThumbCommand)
local concertCommand = "convert -size 438x438 "..exported_image.." -resize 438x438 +profile \"*\" "..exportDirectory.."/"..imageFoldername..filename..".jpg"
dt.control.execute( concertCommand)
end
-- delete the original image to not get into the kmz file
os.remove(image)
local pattern = "[/]?([^/]+)$"
filmName = string.match(image.film.path, pattern)
end
local exportgeoJSONFilename = filmName..".geoJSON"
local exportMapBoxHTMLFilename = filmName..".html"
-- Create the geoJSON file
local geoJSON_file = [[
{
"type": "FeatureCollection",
"features": [
]]
for image,exported_image in pairs(image_table) do
filename = string.upper(string.gsub(image.filename,"%.", "_"))
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
geoJSON_file = geoJSON_file..
[[ {
"type": "Feature",
"geometry": {
"type": "Point",
]]
geoJSON_file = geoJSON_file.." \"coordinates\": ["..string.gsub(tostring(image.longitude),",", ".")..","..string.gsub(tostring(image.latitude),",", ".").."]\n"
geoJSON_file = geoJSON_file..
[[ },
"properties": {
"title": "]]..image.title..[[",
"description": "]]..image.description..[[",
"image": "]]..imageFoldername..filename..[[.jpg",
"icon": {
"iconUrl": "]]..imageFoldername.."thumb_"..filename..[[.jpg",
"iconSize": [96, 65],
"iconAnchor": [48, 32],
"popupAnchor": [0, -32],
"className": "dot"
}
}
}
,]]
end
end
geoJSON_file = geoJSON_file:sub(0,geoJSON_file:len()-1)
geoJSON_file = geoJSON_file..
[[
]
}
]]
--HTML
if ( dt.preferences.read("geoJSON_export","CreateMapBoxHTMLFile","bool") == true ) then
local mapBoxKey = dt.preferences.read("geoJSON_export","mapBoxKey","string")
local mapBoxHTML_file = [[
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>2014-05-31 Rieselfelder</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>
body { margin:0; padding:0; }
.map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<div id='map-tooltips-js' class='map'> </div>
<script>
L.mapbox.accessToken = ']]..mapBoxKey..[[';
var mapTooltipsJS = L.mapbox.map('map-tooltips-js', 'mapbox.light')
.setView([0,0], 5);
var myLayer = L.mapbox.featureLayer()
.loadURL(']]..exportgeoJSONFilename..[[')
.addTo(mapTooltipsJS);
// Set a custom icon on each marker based on feature properties.
myLayer.on('layeradd', function(e) {
var marker = e.layer,
feature = marker.feature;
marker.setIcon(L.icon(feature.properties.icon));
var content = '<h2>'+ feature.properties.title+'<\/h2>' + '<p>'+ feature.properties.description+'<\/p>' + '<img src="'+feature.properties.image+'" alt="">';
marker.bindPopup(content,{minWidth: 457});
});
// Center on click
myLayer.on('click', function(e) {
mapTooltipsJS.panTo(e.layer.getLatLng());
});
// https://www.mapbox.com/mapbox.js/example/v1.0.0/fit-map-to-markers/
// Especially with dynamic data, it's useful to automatically fit all markers
// in the map bounds instead of guessing and checking center and zoom values
// Since this layer is loaded with the asynchronous method loadURL, that uses
// AJAX in the background, we wait for all of the markers to be loaded by
// waiting for the ready event. If you don't load your markers with an async
// method and instead set them with setGeoJSON or similar, you don't need
// to do this.
myLayer.on('ready', function() {
// featureLayer.getBounds() returns the corners of the furthest-out markers,
// and map.fitBounds() makes sure that the map contains these.
mapTooltipsJS.fitBounds(myLayer.getBounds());
});
// Lines
// https://www.mapbox.com/mapbox.js/example/v1.0.0/line-marker/
myLayer.on('ready', function(e) {
var line = [];
this.eachLayer(function(marker) {
line.push(marker.getLatLng());
});
var polyline_options = {
color: '#FF0000'
};
var polyline = L.polyline(line, polyline_options).addTo(mapTooltipsJS);
});
</script>
</body>
</html>
]]
local file = io.open(exportDirectory.."/"..exportMapBoxHTMLFilename, "w")
file:write(mapBoxHTML_file)
file:close()
end
local file = io.open(exportDirectory.."/"..exportgeoJSONFilename, "w")
file:write(geoJSON_file)
file:close()
dt.print("geoJSON file created in "..exportDirectory)
-- Open the file with the standard programm
if ( dt.preferences.read("geoJSON_export","OpengeoJSONFile","bool") == true ) then
local geoJSONFileOpenCommand
geoJSONFileOpenCommand = "xdg-open "..exportDirectory.."/\""..exportgeoJSONFilename.."\""
dt.control.execute( geoJSONFileOpenCommand)
end
end
-- Preferences
dt.preferences.register("geoJSON_export",
"CreateMapBoxHTMLFile",
"bool",
_("geoJSON export: Create an additional HTML file"),
_("Creates a HTML file, that loads the geoJASON file. (Needs a MapBox key"),
false )
dt.preferences.register("geoJSON_export",
"mapBoxKey",
"string",
_("geoJSON export: MapBox Key"),
_("https://www.mapbox.com/studio/account/tokens"),
'' )
dt.preferences.register("geoJSON_export",
"OpengeoJSONFile",
"bool",
_("geoJSON export: Open geoJSON file after export"),
_("Opens the geoJSON file after the export with the standard program for geoJSON files"),
false )
local handle = io.popen("xdg-user-dir DESKTOP")
local result = handle:read()
handle:close()
dt.preferences.register("geoJSON_export",
"ExportDirectory",
"directory",
_("geoJSON export: Export directory"),
_("A directory that will be used to export the geoJSON files"),
result )
-- Register
dt.register_storage("geoJSON_export", "geoJSON Export", nil, create_geoJSON_file)

89
contrib/geo_uri.lua Normal file
View File

@@ -0,0 +1,89 @@
--[[
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"))

319
contrib/gimp.lua Normal file
View File

@@ -0,0 +1,319 @@
--[[
gimp.lua - export and edit with GIMP
Copyright (C) 2016 Bill Ferguson <wpferguson@gmail.com>.
Portions are lifted from hugin.lua and thus are
Copyright (c) 2014 Wolfgang Goetz
Copyright (c) 2015 Christian Kanzian
Copyright (c) 2015 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/>.
]]
--[[
gimp - export an image and open with GIMP for editing
This script provides another storage (export target) for darktable. Selected
images are exported in the specified format to temporary storage. GIMP is launched
and opens the files. After editing, the exported images are overwritten to save the
changes. When GIMP exits, the exported files are moved into the current collection
and imported into the database. The imported files then show up grouped with the
originally selected images.
ADDITIONAL SOFTWARE NEEDED FOR THIS SCRIPT
* GIMP - http://www.gimp.org
USAGE
* require this script from your main lua file
* select an image or images for editing with GIMP
* in the export dialog select "Edit with GIMP" and select the format and bit depth for the
exported image
* Press "export"
* Edit the image with GIMP then save the changes with File->Overwrite....
* Exit GIMP
* The edited image will be imported and grouped with the original image
CAVEATS
* Developed and tested on Ubuntu 14.04 LTS with darktable 2.0.3 and GIMP 2.9.3 (development version with
> 8 bit color)
* There is no provision for dealing with the xcf files generated by GIMP, since darktable doesn't deal with
them. You may want to save the xcf file if you intend on doing further edits to the image or need to save
the layers used. Where you save them is up to you.
BUGS, COMMENTS, SUGGESTIONS
* Send to Bill Ferguson, wpferguson@gmail.com
CHANGES
* 20160823 - os.rename doesn't work across filesystems. Added fileCopy and fileMove functions to move the file
from the temporary location to the collection location irregardless of what filesystem it is on. If an
issue is encountered, a message is printed back to the UI so the user isn't left wondering what happened.
]]
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("gimp",dt.configuration.config_dir.."/lua/")
local function split_filepath(str)
local result = {}
-- Thank you Tobias Jakobs for the awesome regular expression, which I tweaked a little
result["path"], result["filename"], result["basename"], result["filetype"] = string.match(str, "(.-)(([^\\/]-)%.?([^%.\\/]*))$")
return result
end
local function get_path(str)
local parts = split_filepath(str)
return parts["path"]
end
local function get_filename(str)
local parts = split_filepath(str)
return parts["filename"]
end
local function get_basename(str)
local parts = split_filepath(str)
return parts["basename"]
end
local function get_filetype(str)
local parts = split_filepath(str)
return parts["filetype"]
end
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")
local ret
if file ~= nil then
io.close(file)
dt.print_error("true checkIfFileExists: "..filepath)
ret = true
else
dt.print_error(filepath.." not found")
ret = false
end
return ret
end
local function filename_increment(filepath)
-- break up the filepath into parts
local path = get_path(filepath)
local basename = get_basename(filepath)
local filetype = get_filetype(filepath)
-- check to see if we've incremented before
local increment = string.match(basename, "_(%d-)$")
if increment then
-- we do 2 digit increments so make sure we didn't grab part of the filename
if string.len(increment) > 2 then
-- we got the filename so set the increment to 01
increment = "01"
else
increment = string.format("%02d", tonumber(increment) + 1)
basename = string.gsub(basename, "_(%d-)$", "")
end
else
increment = "01"
end
local incremented_filepath = path .. basename .. "_" .. increment .. "." .. filetype
dt.print_error("original file was " .. filepath)
dt.print_error("incremented file is " .. incremented_filepath)
return incremented_filepath
end
local function groupIfNotMember(img, new_img)
local image_table = img:get_group_members()
local is_member = false
for _,image in ipairs(image_table) do
dt.print_error(image.filename .. " is a member")
if image.filename == new_img.filename then
is_member = true
dt.print_error("Already in group")
end
end
if not is_member then
dt.print_error("group leader is "..img.group_leader.filename)
new_img:group_with(img.group_leader)
dt.print_error("Added to group")
end
end
local function sanitize_filename(filepath)
local path = get_path(filepath)
local basename = get_basename(filepath)
local filetype = get_filetype(filepath)
local sanitized = string.gsub(basename, " ", "\\ ")
return path .. sanitized .. "." .. filetype
end
local function show_status(storage, image, format, filename,
number, total, high_quality, extra_data)
dt.print(string.format(_("Export Image %i/%i"), number, total))
end
local function fileCopy(fromFile, toFile)
local result = nil
-- if cp exists, use it
if checkIfBinExists("cp") then
result = os.execute("cp '" .. fromFile .. "' '" .. toFile .. "'")
end
-- if cp was not present, or if cp failed, then a pure lua solution
if not result then
local fileIn, err = io.open(fromFile, 'rb')
if fileIn then
local fileOut, errr = io.open(toFile, 'w')
if fileOut then
local content = fileIn:read(4096)
while content do
fileOut:write(content)
content = fileIn:read(4096)
end
result = true
fileIn:close()
fileOut:close()
else
dt.print_error("fileCopy Error: " .. errr)
end
else
dt.print_error("fileCopy Error: " .. err)
end
end
return result
end
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
success = os.execute("mv '" .. fromFile .. "' '" .. toFile .. "'")
end
-- if the mv didn't exist or succeed, then...
if not success then
-- pure lua solution
success = fileCopy(fromFile, toFile)
if success then
os.remove(fromFile)
else
dt.print_error("fileMove Error: Unable to move " .. fromFile .. " to " .. toFile .. ". Leaving " .. fromFile .. " in place.")
dt.print(string.format(_("Unable to move edited file into collection. Leaving it as %s"), fromFile))
end
end
end
return success -- nil on error, some value if success
end
local function gimp_edit(storage, image_table, extra_data) --finalize
if not checkIfBinExists("gimp") then
dt.print_error(_("GIMP not found"))
return
end
-- list of exported images
local img_list
-- reset and create image list
img_list = ""
for _,exp_img in pairs(image_table) do
exp_img = sanitize_filename(exp_img)
img_list = img_list ..exp_img.. " "
end
dt.print(_("Launching GIMP..."))
local gimpStartCommand
gimpStartCommand = "gimp "..img_list
dt.print_error(gimpStartCommand)
dt.control.execute( gimpStartCommand)
-- for each of the image, exported image pairs
-- move the exported image into the directory with the original
-- then import the image into the database which will group it with the original
-- and then copy over any tags other than darktable tags
for image,exported_image in pairs(image_table) do
local myimage_name = image.path .. "/" .. get_filename(exported_image)
while checkIfFileExists(myimage_name) do
myimage_name = filename_increment(myimage_name)
-- limit to 99 more exports of the original export
if string.match(get_basename(myimage_name), "_(d-)$") == "99" then
break
end
end
dt.print_error("moving " .. exported_image .. " to " .. myimage_name)
local result = fileMove(exported_image, myimage_name)
if result then
dt.print_error("importing file")
local myimage = dt.database.import(myimage_name)
groupIfNotMember(image, myimage)
for _,tag in pairs(dt.tags.get_tags(image)) do
if not (string.sub(tag.name,1,9) == "darktable") then
dt.print_error("attaching tag")
dt.tags.attach(tag,myimage)
end
end
end
end
end
-- Register
dt.register_storage("module_gimp", _("Edit with GIMP"), show_status, gimp_edit)
--

View File

@@ -24,7 +24,16 @@ USAGE
]]
local dt = require "darktable"
dt.configuration.check_version(...,{2,0,1})
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()
@@ -47,5 +56,5 @@ local function selectWithoutGPS()
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")
dt.register_event("shortcut", selectWithGPS, _("Select all images with GPS information"))
dt.register_event("shortcut", selectWithoutGPS, _("Select all images without GPS information"))

View File

@@ -1,119 +1,129 @@
--[[
Hugin storage for darktable
copyright (c) 2014 Wolfgang Goetz
copyright (c) 2015 Christian Kanzian
copyright (c) 2015 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/>.
]]
--[[
HUGIN
Add a new storage option to send images to hugin.
Images are exported to darktable tmp dir first.
ADDITIANAL SOFTWARE NEEDED FOR THIS SCRIPT
* hugin
USAGE
* require this file from your main luarc config file.
This plugin will add a new storage option and calls hugin after export.
]]
local dt = require "darktable"
-- should work with darktable API version 2.0.0
dt.configuration.check_version(...,{2,0,0})
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
darktable.print_error("hugin not found")
return
end
-- Since Hugin 2015.0.0 hugin provides a command line tool to start the assistant
-- http://wiki.panotools.org/Hugin_executor
-- We need pto_gen to create pto file for hugin_executor
-- http://hugin.sourceforge.net/docs/manual/Pto_gen.html
local hugin_executor = false
if (checkIfBinExists("hugin_executor") and checkIfBinExists("pto_gen")) then
hugin_executor = true
end
-- list of exported images
local img_list
-- reset and create image list
img_list = ""
for _,v in pairs(image_table) do
img_list = img_list ..v.. " "
end
dt.print("Will try to stitch now")
local huginStartCommand
if (hugin_executor) then
huginStartCommand = "pto_gen "..img_list.." -o "..dt.configuration.tmp_dir.."/project.pto"
dt.print("Creating pto file")
coroutine.yield("RUN_COMMAND", huginStartCommand)
dt.print("Running Assistent")
huginStartCommand = "hugin_executor --assistant "..dt.configuration.tmp_dir.."/project.pto"
coroutine.yield("RUN_COMMAND", huginStartCommand)
huginStartCommand = "hugin "..dt.configuration.tmp_dir.."/project.pto"
else
huginStartCommand = "hugin "..img_list
end
dt.print_error(huginStartCommand)
if coroutine.yield("RUN_COMMAND", huginStartCommand)
then
dt.print("Command hugin failed ...")
end
end
-- Register
dt.register_storage("module_hugin", "Hugin Panorama", show_status, create_panorama)
--
-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua
--[[
Hugin storage for darktable
copyright (c) 2014 Wolfgang Goetz
copyright (c) 2015 Christian Kanzian
copyright (c) 2015 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/>.
]]
--[[
HUGIN
Add a new storage option to send images to hugin.
Images are exported to darktable tmp dir first.
ADDITIONAL SOFTWARE NEEDED FOR THIS SCRIPT
* hugin
USAGE
* require this file from your main luarc config file.
This plugin will add a new storage option and calls hugin after export.
]]
local dt = require "darktable"
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})
-- Tell gettext where to find the .mo file translating messages for a particular domain
gettext.bindtextdomain("hugin",dt.configuration.config_dir.."/lua/")
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
dt.print_error(_("hugin not found"))
return
end
-- Since Hugin 2015.0.0 hugin provides a command line tool to start the assistant
-- http://wiki.panotools.org/Hugin_executor
-- We need pto_gen to create pto file for hugin_executor
-- http://hugin.sourceforge.net/docs/manual/Pto_gen.html
local hugin_executor = false
if (checkIfBinExists("hugin_executor") and checkIfBinExists("pto_gen")) then
hugin_executor = true
end
-- list of exported images
local img_list
-- reset and create image list
img_list = ""
for _,v in pairs(image_table) do
img_list = img_list ..v.. " "
end
dt.print(_("Will try to stitch now"))
local huginStartCommand
if (hugin_executor) then
huginStartCommand = "pto_gen "..img_list.." -o "..dt.configuration.tmp_dir.."/project.pto"
dt.print(_("Creating pto file"))
dt.control.execute( huginStartCommand)
dt.print(_("Running Assistent"))
huginStartCommand = "hugin_executor --assistant "..dt.configuration.tmp_dir.."/project.pto"
dt.control.execute( huginStartCommand)
huginStartCommand = "hugin "..dt.configuration.tmp_dir.."/project.pto"
else
huginStartCommand = "hugin "..img_list
end
dt.print_error(huginStartCommand)
if dt.control.execute( huginStartCommand)
then
dt.print(_("Command hugin failed ..."))
end
end
-- Register
dt.register_storage("module_hugin", _("Hugin Panorama"), show_status, create_panorama)
--
-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua

View File

@@ -1,6 +1,7 @@
--[[
This file is part of darktable,
Copyright 2014 by Tobias Jakobs.
Copyright 2016 by Tobias Jakobs.
Copyright 2016 by Erik Augustin.
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
@@ -18,7 +19,7 @@
--[[
darktable KML export script
ADDITIANAL SOFTWARE NEEDED FOR THIS SCRIPT
ADDITIONAL SOFTWARE NEEDED FOR THIS SCRIPT
* mkdir
* zip (only if you create KMZ files)
* convert (ImageMagick)
@@ -26,15 +27,29 @@ ADDITIANAL SOFTWARE NEEDED FOR THIS SCRIPT
* xdg-user-dir
WARNING
This script is only testet with Linux
This script is only tested with Linux
USAGE
* require this script from your main lua file
* require script "official/yield" from your main Lua file in the first line
* require this script from your main Lua file
* when choosing file format, pick JPEG or PNG as Google Earth doesn't support other formats
]]
local dt = require "darktable"
dt.configuration.check_version(...,{2,0,1})
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("kml_export",dt.configuration.config_dir.."/lua/")
local function _(msgid)
return gettext.dgettext("kml_export", msgid)
end
-- Sort a table
local function spairs(_table, order) -- Code copied from http://stackoverflow.com/questions/15706270/sort-a-table-in-lua
-- collect the keys
local keys = {}
@@ -59,7 +74,7 @@ local function spairs(_table, order) -- Code copied from http://stackoverflow.co
end
local function show_status(storage, image, format, filename, number, total, high_quality, extra_data)
dt.print("Export Image "..tostring(number).."/"..tostring(total))
dt.print(string.format(_("Export Image %i/%i"), number, total))
end
local function checkIfBinExists(bin)
@@ -74,6 +89,90 @@ local function checkIfBinExists(bin)
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 )
local tableAccents = {}
tableAccents["à"] = "a"
tableAccents["á"] = "a"
tableAccents["â"] = "a"
tableAccents["ã"] = "a"
tableAccents["ä"] = "a"
tableAccents["ç"] = "c"
tableAccents["è"] = "e"
tableAccents["é"] = "e"
tableAccents["ê"] = "e"
tableAccents["ë"] = "e"
tableAccents["ì"] = "i"
tableAccents["í"] = "i"
tableAccents["î"] = "i"
tableAccents["ï"] = "i"
tableAccents["ñ"] = "n"
tableAccents["ò"] = "o"
tableAccents["ó"] = "o"
tableAccents["ô"] = "o"
tableAccents["õ"] = "o"
tableAccents["ö"] = "o"
tableAccents["ù"] = "u"
tableAccents["ú"] = "u"
tableAccents["û"] = "u"
tableAccents["ü"] = "u"
tableAccents["ý"] = "y"
tableAccents["ÿ"] = "y"
tableAccents["À"] = "A"
tableAccents["Á"] = "A"
tableAccents["Â"] = "A"
tableAccents["Ã"] = "A"
tableAccents["Ä"] = "A"
tableAccents["Ç"] = "C"
tableAccents["È"] = "E"
tableAccents["É"] = "E"
tableAccents["Ê"] = "E"
tableAccents["Ë"] = "E"
tableAccents["Ì"] = "I"
tableAccents["Í"] = "I"
tableAccents["Î"] = "I"
tableAccents["Ï"] = "I"
tableAccents["Ñ"] = "N"
tableAccents["Ò"] = "O"
tableAccents["Ó"] = "O"
tableAccents["Ô"] = "O"
tableAccents["Õ"] = "O"
tableAccents["Ö"] = "O"
tableAccents["Ù"] = "U"
tableAccents["Ú"] = "U"
tableAccents["Û"] = "U"
tableAccents["Ü"] = "U"
tableAccents["Ý"] = "Y"
local normalizedString = ""
for strChar in string.gmatch(str, "([%z\1-\127\194-\244][\128-\191]*)") do
if tableAccents[strChar] ~= nil then
normalizedString = normalizedString..tableAccents[strChar]
else
normalizedString = normalizedString..strChar
end
end
return normalizedString
end
-- Escape XML characters
-- Keep &amp; first, otherwise it will double escape other characters
-- https://stackoverflow.com/questions/1091945/what-characters-do-i-need-to-escape-in-xml-documents
function string.escapeXmlCharacters( str )
str = string.gsub(str,"&", "&amp;")
str = string.gsub(str,"\"", "&quot;")
str = string.gsub(str,"'", "&apos;")
str = string.gsub(str,"<", "&lt;")
str = string.gsub(str,">", "&gt;")
return str
end
local function create_kml_file(storage, image_table, extra_data)
@@ -92,10 +191,12 @@ local function create_kml_file(storage, image_table, extra_data)
dt.print_error("Will try to export KML file now")
local imageFoldername
if ( dt.preferences.read("kml_export","CreateKMZ","bool") == true ) then
if not checkIfBinExists("zip") then
return
end
exportDirectory = dt.configuration.tmp_dir
imageFoldername = ""
else
@@ -104,37 +205,45 @@ local function create_kml_file(storage, image_table, extra_data)
-- Creates dir if not exsists
imageFoldername = "files/"
local mkdirCommand = "mkdir -p "..exportDirectory.."/"..imageFoldername
coroutine.yield("RUN_COMMAND", mkdirCommand)
dt.control.execute(mkdirCommand)
end
-- Create the thumbnails
for _,image in pairs(image_table) do
local path, filename, filetype = string.match(image, "(.-)([^\\/]-%.?([^%.\\/]*))$")
filename = string.upper(string.gsub(filename,"%.", "_"))
-- 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
-- 120x120, allowing it to run faster by avoiding returning full-resolution images to GraphicsMagick for the
-- subsequent resizing operation. The '-resize 120x120' specifies the desired dimensions of the output image. It
-- will be scaled so its largest dimension is 120 pixels. The '+profile "*"' removes any ICM, EXIF, IPTC, or other
-- profiles that might be present in the input and aren't needed in the thumbnail.
for image,exported_image in pairs(image_table) 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
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
-- 120x120, allowing it to run faster by avoiding returning full-resolution images to GraphicsMagick for the
-- subsequent resizing operation. The '-resize 120x120' specifies the desired dimensions of the output image. It
-- will be scaled so its largest dimension is 120 pixels. The '+profile "*"' removes any ICM, EXIF, IPTC, or other
-- profiles that might be present in the input and aren't needed in the thumbnail.
local concertToThumbCommand = "convert -size 96x96 "..image.." -resize 92x92 -mattecolor \"#FFFFFF\" -frame 2x2 +profile \"*\" "..exportDirectory.."/"..imageFoldername.."thumb_"..filename..".jpg"
-- USE coroutine.yield. It does not block the UI
coroutine.yield("RUN_COMMAND", concertToThumbCommand)
local concertCommand = "convert -size 438x438 "..image.." -resize 438x438 +profile \"*\" "..exportDirectory.."/"..imageFoldername..filename..".jpg"
coroutine.yield("RUN_COMMAND", concertCommand)
local convertToThumbCommand = "convert -size 96x96 "..exported_image.." -resize 92x92 -mattecolor \"#FFFFFF\" -frame 2x2 +profile \"*\" "..exportDirectory.."/"..imageFoldername.."thumb_"..filename..".jpg"
dt.control.execute(convertToThumbCommand)
else
-- Remove exported image if it has no GPS data
os.remove(exported_image)
end
local pattern = "[/]?([^/]+)$"
filmName = string.match(_.film.path, pattern)
filmName = string.match(image.film.path, pattern)
-- Strip accents from the filename, because GoogleEarth can't open them
-- https://github.com/darktable-org/lua-scripts/issues/54
filmName = string.stripAccents(filmName)
end
exportKMLFilename = filmName..".kml"
exportKMZFilename = filmName..".kmz"
-- Create the KML file
kml_file = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
local kml_file = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
kml_file = kml_file.."<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n"
kml_file = kml_file.."<Document>\n"
@@ -142,16 +251,28 @@ local function create_kml_file(storage, image_table, extra_data)
kml_file = kml_file.."<name>"..filmName.."</name>\n"
kml_file = kml_file.." <description>Exported from darktable</description>\n"
for image,_ in pairs(image_table) do
filename = string.upper(string.gsub(image.filename,"%.", "_"))
for image,exported_image in pairs(image_table) do
-- 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
kml_file = kml_file.." <Placemark>\n"
kml_file = kml_file.." <name>"..image.filename.."</name>\n"
--kml_file = kml_file.." <description></description>\n"
local image_title, image_description
if (image.title and image.title ~= "") then
image_title = string.escapeXmlCharacters(image.title)
else
image_title = image.filename
end
-- Characters should not be escaped in CDATA, but we are using HTML fragment, so we must escape them
image_description = string.escapeXmlCharacters(image.description)
kml_file = kml_file.." <name>"..image_title.."</name>\n"
kml_file = kml_file.." <description>"..image_description.."</description>\n"
kml_file = kml_file.." <Style>\n"
kml_file = kml_file.." <IconStyle>\n"
kml_file = kml_file.." <Icon>\n"
@@ -159,7 +280,7 @@ local function create_kml_file(storage, image_table, extra_data)
kml_file = kml_file.." </Icon>\n"
kml_file = kml_file.." </IconStyle>\n"
kml_file = kml_file.." <BalloonStyle>\n"
kml_file = kml_file.." <text><![CDATA[<img src=\""..imageFoldername..filename..".jpg\"><br/>]]></text>\n"
kml_file = kml_file.." <text><![CDATA[<p><b>"..image_title.."</b></p><img src=\""..imageFoldername..filename..extension.."\"><p>"..image_description.."</p>]]></text>\n"
kml_file = kml_file.." <textColor>ff000000</textColor>\n"
kml_file = kml_file.." <displayMode>default</displayMode>\n"
kml_file = kml_file.." </BalloonStyle>\n"
@@ -193,11 +314,15 @@ local function create_kml_file(storage, image_table, extra_data)
kml_file = kml_file.." <LineString>\n"
kml_file = kml_file.." <coordinates>\n"
for image,_ in spairs(image_table, function(t,a,b) return t[b] < t[a] end) do
for image,exported_image in spairs(image_table, function(t,a,b) return t[b] < t[a] end) 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
kml_file = kml_file.." "..string.gsub(tostring(image.longitude),",", ".")..","..string.gsub(tostring(image.latitude),",", ".")..",0\n"
local altitude = 0;
if (image.elevation) then
altitude = image.elevation;
end
kml_file = kml_file.." "..string.gsub(tostring(image.longitude),",", ".")..","..string.gsub(tostring(image.latitude),",", ".")..",altitude\n"
end
end
kml_file = kml_file.." </coordinates>\n"
@@ -209,7 +334,7 @@ local function create_kml_file(storage, image_table, extra_data)
kml_file = kml_file.."</Document>\n"
kml_file = kml_file.."</kml>"
file = io.open(exportDirectory.."/"..exportKMLFilename, "w")
local file = io.open(exportDirectory.."/"..exportKMLFilename, "w")
file:write(kml_file)
file:close()
@@ -218,11 +343,23 @@ local function create_kml_file(storage, image_table, extra_data)
-- Compress the files to create a KMZ file
if ( dt.preferences.read("kml_export","CreateKMZ","bool") == true ) then
exportDirectory = dt.preferences.read("kml_export","ExportDirectory","string")
-- USE coroutine.yield. It does not block the UI
local createKMZCommand = "zip --test --move --junk-paths "
createKMZCommand = createKMZCommand .."\""..exportDirectory.."/"..exportKMZFilename.."\" "
createKMZCommand = createKMZCommand .."\""..dt.configuration.tmp_dir.."/"..exportKMLFilename.."\" \""..dt.configuration.tmp_dir.."/"..imageFoldername.."\"*"
coroutine.yield("RUN_COMMAND", createKMZCommand)
createKMZCommand = createKMZCommand .."\""..exportDirectory.."/"..exportKMZFilename.."\" " -- KMZ filename
createKMZCommand = createKMZCommand .."\""..dt.configuration.tmp_dir.."/"..exportKMLFilename.."\" " -- KML file
for image,exported_image in pairs(image_table) 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
local filename = string.upper(string.gsub(image.filename,"%.%w*", ""))
createKMZCommand = createKMZCommand .."\""..dt.configuration.tmp_dir.."/"..imageFoldername.."thumb_"..filename..".jpg\" " -- thumbnails
createKMZCommand = createKMZCommand .."\""..exported_image.."\" " -- images
end
end
dt.control.execute(createKMZCommand)
end
-- Open the file with the standard programm
@@ -234,22 +371,42 @@ local function create_kml_file(storage, image_table, extra_data)
else
kmlFileOpenCommand = "xdg-open "..exportDirectory.."/\""..exportKMLFilename.."\""
end
coroutine.yield("RUN_COMMAND", kmlFileOpenCommand)
dt.control.execute(kmlFileOpenCommand)
end
end
-- Preferences
dt.preferences.register("kml_export", "OpenKmlFile", "bool", "KML export: Open KML/KMZ file after export", "Opens the KML file after the export with the standard programm for KML files", false )
dt.preferences.register("kml_export",
"OpenKmlFile",
"bool",
_("KML export: Open KML/KMZ file after export"),
_("Opens the KML file after the export with the standard program for KML files"),
false )
local handle = io.popen("xdg-user-dir DESKTOP")
local result = handle:read()
handle:close()
dt.preferences.register("kml_export", "ExportDirectory", "directory", "KML export: Export directory", "A directory that will be used to export the KML/KMZ files", result )
dt.preferences.register("kml_export",
"ExportDirectory",
"directory",
_("KML export: Export directory"),
_("A directory that will be used to export the KML/KMZ files"),
result )
dt.preferences.register("kml_export", "CreatePath", "bool", "KML export: Connect images with path", "connect all images with a path", false )
dt.preferences.register("kml_export", "CreateKMZ", "bool", "KML export: Create KMZ file", "Compress all imeges to one KMZ file", true )
dt.preferences.register("kml_export",
"CreatePath",
"bool",
_("KML export: Connect images with path"),
_("connect all images with a path"),
false )
dt.preferences.register("kml_export",
"CreateKMZ",
"bool",
_("KML export: Create KMZ file"),
_("Compress all imeges to one KMZ file"),
true )
-- Register
dt.register_storage("kml_export", "KML/KMZ Export", nil, create_kml_file)
dt.register_storage("kml_export", _("KML/KMZ Export"), nil, create_kml_file)

84
contrib/rate_group.lua Normal file
View File

@@ -0,0 +1,84 @@
--[[
Rate Group:
Script to provide shortcuts for rating or rejecting all images within a group;
particularly useful for RAW+JPEG shooters employing a star rating workflow
like the below:
http://blog.chasejarvis.com/blog/2011/03/photo-editing-101/
Installation and usage:
1. Copy this file into ~/.config/darktable/lua/
2. Add `require "rate_group"` to new line in ~/.config/darktable/luarc
3. Restart darktable
4. Assign a keyboard shortcut to each action via settings > shortcuts > lua
I use the following shortcuts:
* Reject group: Ctrl+R
* Rate group 1: Ctrl+1
* Rate group 2: Ctrl+2
* Rate group 3: Ctrl+3
* Rate group 4: Ctrl+4
* Rate group 5: Ctrl+5
* Rate group 0: Ctrl+0
Author: Dom H (dom@hxy.io)
License: GPLv2
This script is based on Thibault Jouannic's `reject_group` script:
http://redmine.darktable.org/issues/8968#note-20
]]
local dt = require "darktable"
local function apply_rating(rating)
local images = dt.gui.action_images
for _, i in ipairs(images) do
local members = i:get_group_members()
for _, m in ipairs(members) do
m.rating = rating
end
end
if rating < 0 then
dt.print("rejecting group(s)")
else
dt.print("applying rating " ..rating.. " to group(s)")
end
end
dt.register_event("shortcut",function(event, shortcut)
apply_rating(-1)
end, "Reject group")
dt.register_event("shortcut",function(event, shortcut)
apply_rating(0)
end, "Rate group 0")
dt.register_event("shortcut",function(event, shortcut)
apply_rating(1)
end, "Rate group 1")
dt.register_event("shortcut",function(event, shortcut)
apply_rating(2)
end, "Rate group 2")
dt.register_event("shortcut",function(event, shortcut)
apply_rating(3)
end, "Rate group 3")
dt.register_event("shortcut",function(event, shortcut)
apply_rating(4)
end, "Rate group 4")
dt.register_event("shortcut",function(event, shortcut)
apply_rating(5)
end, "Rate group 5")

View File

@@ -25,7 +25,17 @@ USAGE
]]
local dt = require "darktable"
dt.configuration.check_version(...,{2,0,2})
require "official/yield"
local gettext = dt.gettext
dt.configuration.check_version(...,{2,0,2},{3,0,0})
-- Tell gettext where to find the .mo file translating messages for a particular domain
gettext.bindtextdomain("slideshowMusic",dt.configuration.config_dir.."/lua/")
local function _(msgid)
return gettext.dgettext("slideshowMusic", msgid)
end
local function checkIfBinExists(bin)
local handle = io.popen("which "..bin)
@@ -57,24 +67,24 @@ local function playSlideshowMusic(_, old_view, new_view)
playCommand = 'rhythmbox-client --play-uri="'..filename..'"'
--dt.print_error(playCommand)
coroutine.yield("RUN_COMMAND", playCommand)
dt.control.execute( playCommand)
else
if (old_view.id == "slideshow") then
if (old_view and old_view.id == "slideshow") then
stopCommand = "rhythmbox-client --pause"
--dt.print_error(stopCommand)
coroutine.yield("RUN_COMMAND", stopCommand)
dt.control.execute( stopCommand)
end
end
end
end
-- Preferences
dt.preferences.register("slideshowMusic", "SlideshowMusic", "file", "Slideshow background music file", "", "")
dt.preferences.register("slideshowMusic", "SlideshowMusic", "file", _("Slideshow background music file"), "", "")
dt.preferences.register("slideshowMusic",
"PlaySlideshowMusic",
"bool",
"Play slideshow background music",
"Plays music with rhythmbox if a slideshow starts",
_("Play slideshow background music"),
_("Plays music with rhythmbox if a slideshow starts"),
true)
-- Register
dt.register_event("view-changed",playSlideshowMusic)

View File

@@ -1,120 +1,120 @@
--[[
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 video export script
ADDITIANAL SOFTWARE NEEDED FOR THIS SCRIPT
* mencoder (MEncoder is from the MPlayer Team)
* xdg-open
* xdg-user-dir
WARNING
This script is only testet with Linux
USAGE
* require this script from your main lua file
]]
local dt = require "darktable"
dt.configuration.check_version(...,{2,0,1})
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
return
end
if not checkIfBinExists("xdg-open") then
return
end
if not checkIfBinExists("xdg-user-dir") then
return
end
exportDirectory = dt.preferences.read("video_mencoder","ExportDirectory","string")
exportFilename = "output.avi"
framsePerSecond = dt.preferences.read("video_mencoder","FramesPerSecond","integer")
dt.print_error("Will try to create video now")
-- Set the codec
local codec = ""
local codecPreferences = ""
codecPreferences = dt.preferences.read("video_mencoder","Codec","string")
if (codecPreferences == "H.264 encoding") then
codec = 'x264'
end
if (codecPreferences == "XviD encoding") then
codec = 'xvid'
end
if not codecPreferences then
codec = 'x264'
end
-- Create the command
local command = "mencoder -idx -nosound -noskip -ovc "..codec.." -lavcopts vcodec=mjpeg -o "..exportDirectory.."/"..exportFilename.." -mf fps="..framsePerSecond .." mf://"
for _,v in pairs(image_table) do
command = command..v..","
end
dt.print_error("this is the command: "..command)
-- USE coroutine.yield. It does not block the UI
coroutine.yield("RUN_COMMAND", command)
dt.print("Video created in "..exportDirectory)
if ( dt.preferences.read("video_mencoder","OpenVideo","bool") == true ) then
-- USE coroutine.yield. It does not block the UI
local playVideoCommand = "xdg-open "..exportDirectory.."/"..exportFilename
coroutine.yield("RUN_COMMAND", playVideoCommand)
end
end
-- Preferences
dt.preferences.register("video_mencoder", "FramesPerSecond", "float", "Video exort (MEncoder): Frames per second", "Frames per Second in the Video export", 15, 1, 99, 0.1 )
dt.preferences.register("video_mencoder", "OpenVideo", "bool", "Video exort (MEncoder): Open video after export", "Opens the Video after the export with the standard video player", false )
local handle = io.popen("xdg-user-dir VIDEOS")
local result = handle:read()
handle:close()
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
dt.preferences.register("video_mencoder", "Codec", "enum", "Video exort (MEncoder): Codec","Video codec","H.264 encoding","H.264 encoding","XviD encoding")
-- Register
dt.register_storage("video_mencoder", "Video Export (MEncoder)", show_status, create_video)
--[[
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 video export script
ADDITIONAL SOFTWARE NEEDED FOR THIS SCRIPT
* mencoder (MEncoder is from the MPlayer Team)
* xdg-open
* xdg-user-dir
WARNING
This script is only tested with Linux
USAGE
* require this script from your main lua file
]]
local dt = require "darktable"
require "official/yield"
dt.configuration.check_version(...,{2,0,1})
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
return
end
if not checkIfBinExists("xdg-open") then
return
end
if not checkIfBinExists("xdg-user-dir") then
return
end
exportDirectory = dt.preferences.read("video_mencoder","ExportDirectory","string")
exportFilename = "output.avi"
framsePerSecond = dt.preferences.read("video_mencoder","FramesPerSecond","integer")
dt.print_error("Will try to create video now")
-- Set the codec
local codec = ""
local codecPreferences = ""
codecPreferences = dt.preferences.read("video_mencoder","Codec","string")
if (codecPreferences == "H.264 encoding") then
codec = 'x264'
end
if (codecPreferences == "XviD encoding") then
codec = 'xvid'
end
if not codecPreferences then
codec = 'x264'
end
-- Create the command
local command = "mencoder -idx -nosound -noskip -ovc "..codec.." -lavcopts vcodec=mjpeg -o "..exportDirectory.."/"..exportFilename.." -mf fps="..framsePerSecond .." mf://"
for _,v in pairs(image_table) do
command = command..v..","
end
dt.print_error("this is the command: "..command)
dt.control.execute( command)
dt.print("Video created in "..exportDirectory)
if ( dt.preferences.read("video_mencoder","OpenVideo","bool") == true ) then
local playVideoCommand = "xdg-open "..exportDirectory.."/"..exportFilename
dt.control.execute( playVideoCommand)
end
end
-- Preferences
dt.preferences.register("video_mencoder", "FramesPerSecond", "float", "Video exort (MEncoder): Frames per second", "Frames per Second in the Video export", 15, 1, 99, 0.1 )
dt.preferences.register("video_mencoder", "OpenVideo", "bool", "Video exort (MEncoder): Open video after export", "Opens the Video after the export with the standard video player", false )
local handle = io.popen("xdg-user-dir VIDEOS")
local result = handle:read()
handle:close()
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
dt.preferences.register("video_mencoder", "Codec", "enum", "Video exort (MEncoder): Codec","Video codec","H.264 encoding","H.264 encoding","XviD encoding")
-- Register
dt.register_storage("video_mencoder", "Video Export (MEncoder)", show_status, create_video)

View File

@@ -0,0 +1,20 @@
msgid ""
msgstr ""
"Project-Id-Version: Lua gettextTest\n"
"POT-Creation-Date: 2016-01-07 20:33+0100\n"
"PO-Revision-Date: 2016-01-07 21:32+0100\n"
"Last-Translator: Tobias Jakobs <tobias.jakobs@gmail.com>\n"
"Language-Team: \n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.4\n"
"X-Poedit-Basepath: .\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Poedit-KeywordsList: gettext;dgettext:2;dcgettext:2;ngettext:1,2;dngettext:2,3\n"
"X-Poedit-SearchPath-0: .\n"
#: gettextExample.lua:36
msgid "Hello World!"
msgstr "Hallo Welt!"

View File

@@ -0,0 +1,76 @@
--[[
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 show how translations works
To create the .po file run:
xgettext -l lua gettextExample.lua
xgettext is not a lua tool, it knows (almost) nothing about Lua, and not
enough to do a proper parsing. It takes a text file (In our case a Lua
file) and recognises a few (language dependant) keyword in there.
It matches those keywords with internal description on how functions are
called and creates the .po file accordingly. (For example, it knows that
the first argument of gettext() is the translated string, but that it's
the second argument for dgettext)
This is important because it means that if you use some neat Lua tricks
(like renaming functions) xgettext won't recognize those calls and won't
extract the string to the .po file.
So, this is why we create a local variagle gettext = dt.gettext, so
xgettext recognises gettext.gettext as a function but not dt.gettext.gettext
To create a .mo file run:
msgfmt -v gettextExample.po -o gettextExample.mo
USAGE
* require this script from your main lua file (Add 'require "gettextExample"' to luarc.)
* copy the script to: .config/darktable/lua/
* copy the gettextExample.mo to .config/darktable/lua/de_DE/LC_MESSAGES
You need to start darktable with the Lua debug option: darktable -d lua
$LANG must set to: de_DE
The script run on darktable startup and should output this three lines:
LUA ERROR Hello World!
LUA ERROR Bild
LUA ERROR Hallo Welt!
]]
local dt = require "darktable"
dt.configuration.check_version(...,{3,0,0})
-- Not translated Text
dt.print_error("Hello World!")
local gettext = dt.gettext
-- Translate a string using the darktable textdomain
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/")
-- Translate a string using the specified textdomain
dt.print_error(gettext.dgettext("gettextExample", 'Hello World!'))
-- Define a local function called _ to make the code more readable and have it call dgettext
-- with the proper domain.
local function _(msgid)
return gettext.dgettext("gettextExample", msgid)
end
dt.print_error(_('Hello World!'))

View File

@@ -27,7 +27,7 @@ USAGE
]]
local dt = require "darktable"
dt.configuration.check_version(...,{2,0,0})
dt.configuration.check_version(...,{2,0,0},{3,0,0})
dt.print("hello, world")

102
examples/moduleExample.lua Normal file
View File

@@ -0,0 +1,102 @@
--[[
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 "moduleExample"
* it creates a new example lighttable module
More informations about building user interface elements:
https://www.darktable.org/usermanual/ch09.html.php#lua_gui_example
And about new_widget here:
https://www.darktable.org/lua-api/index.html.php#darktable_new_widget
]]
local dt = require "darktable"
dt.configuration.check_version(...,{3,0,0})
-- add a new lib
local check_button = dt.new_widget("check_button"){label = "MyCheck_button", value = true}
local combobox = dt.new_widget("combobox"){label = "MyCombobox", value = 2, "8", "16", "32"}
--https://www.darktable.org/lua-api/ar01s02s54.html.php
local entry = dt.new_widget("entry")
{
text = "test",
placeholder = "placeholder",
is_password = false,
editable = true,
tooltip = "Tooltip Text",
reset_callback = function(self) self.text = "text" end
}
local file_chooser_button = dt.new_widget("file_chooser_button")
{
title = "MyFile_chooser_button", -- The title of the window when choosing a file
value = "", -- The currently selected file
is_directory = false -- True if the file chooser button only allows directories to be selecte
}
local label = dt.new_widget("label")
label.label = "MyLabel" -- This is an alternative way to the "{}" syntax to set a property
local separator = dt.new_widget("separator"){}
local slider = dt.new_widget("slider")
{
label = "MySlider",
soft_min = 10, -- 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 = 0, -- The hard minimum value for the slider, the user can't manually enter a value beyond this point
hard_max = 1000, -- The hard maximum value for the slider, the user can't manually enter a value beyond this point
value = 52 -- The current value of the slider
}
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
},
nil,-- view_enter
nil -- view_leave
)
-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua
-- kate: hl Lua;

View File

@@ -16,13 +16,13 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
]]
--[[
darktable script to show the different prefference types that are possible with the Lua
darktable script to show the different preference types that are possible with Lua
USAGE
* require this script from your main lua file
]]
local dt = require "darktable"
dt.configuration.check_version(...,{2,0,1})
dt.configuration.check_version(...,{2,0,1},{3,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

View File

@@ -33,7 +33,7 @@ Note that you need to restart DT for your changes to enabled scripts to take eff
]]
local dt = require "darktable"
local io = require "io"
dt.configuration.check_version(...,{2,0,0})
dt.configuration.check_version(...,{3,0,0})
local output = io.popen("cd "..dt.configuration.config_dir.."/lua ;find . -name \\*.lua -print")
local my_name={...}

218
lib/dtutils.lua Normal file
View File

@@ -0,0 +1,218 @@
local dtutils = {}
dtutils.libdoc = {
Name = [[dtutils]],
Synopsis = [[A Darktable lua utilities library]],
Usage = [[local du = require "lib/dtutils"]],
Description = [[dtutils provides a common library of functions used to build
lua scripts. There are also sublibraries that provide more functions.]],
Return_Value = [[du - library - the library of functions]],
Limitations = [[]],
Example = [[]],
See_Also = [[dtutils.debug(3), dtutils.file(3), dtutils.log(3), dtutils.string(3)]],
Reference = [[]],
License = [[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/>.]],
Copyright = [[Copyright (C) 2016 Bill Ferguson <wpferguson@gmail.com>.
Copyright (C) 2016 Tobias Jakobs]],
functions = {}
}
local dt = require "darktable"
local log = require "lib/dtutils.log"
dt.configuration.check_version(...,{3,0,0})
dtutils.libdoc.functions["split"] = {
Name = [[split]],
Synopsis = [[split a string on a specified separator]],
Usage = [[local du = require "lib/dtutils"
local result = du.split(str, pat)
str - string - the string to split
pat - string - the pattern to split on]],
Description = [[split separates a string into a table of strings. The strings are separated at each
occurrence of the supplied pattern. The pattern may be any pattern as described in the lua docs.
Each match of the pattern is consumed and not returned.]],
Return_Value = [[result - a table of strings on success, or an empty table on error]],
Limitations = [[]],
Example = [[split("/a/long/path/name/to/a/file.txt", "/") would return a table like
{a, "long", "path", "name", "to", a, "file.txt"}]],
See_Also = [[]],
Reference = [[http://lua-users.org/wiki/SplitJoin]],
License = [[]],
Copyright = [[]],
}
function dtutils.split(str, pat)
local t = {}
local fpat = "(.-)" .. pat
local last_end = 1
local s, e, cap = str:find(fpat, 1)
while s do
if s ~= 1 or cap ~= "" then
table.insert(t,cap)
end
last_end = e+1
s, e, cap = str:find(fpat, last_end)
end
if last_end <= #str then
cap = str:sub(last_end)
table.insert(t, cap)
end
return t
end
dtutils.libdoc.functions["join"] = {
Name = [[join]],
Synopsis = [[join a table of strings with a specified separator]],
Usage = [[local du = require "lib/dtutils"
local result = du.join(tabl, pat)
tabl - a table of strings
pat - a separator]],
Description = [[join assembles a table of strings into a string with the specified pattern
in between each string]],
Return_Value = [[result - string - the joined string on success, or an empty string on failure]],
Limitations = [[]],
Example = [[join({a, "long", "path", "name", "to", a, "file.txt"}, " ") would return the string
"a long path name to a file.txt"]],
See_Also = [[]],
Reference = [[http://lua-users.org/wiki/SplitJoin]],
License = [[]],
Copyright = [[]],
}
function dtutils.join(tabl, pat)
returnstr = ""
for i,str in pairs(tabl) do
returnstr = returnstr .. str .. pat
end
return string.sub(returnstr, 1, -(pat:len() + 1))
end
--[[
NAME
prequire - a protected lua require
SYNOPSIS
local du = require "lib/dtutils"
local result = du.prequire(req_name)
req_name - the filename of the lua code to load without the ".lua" filetype
DESCRIPTION
prequire is a protected require that can survive an error in the code being loaded without
bringing down the calling routine.
RETURN VALUE
result - the code or true on success, otherwise an error message
EXAMPLE
prequire("lib/dtutils.file") which would load lib/dtutils/file.lua
]]
dtutils.libdoc.functions["prequire"] = {
Name = [[prequire]],
Synopsis = [[a protected lua require]],
Usage = [[local du = require "lib/dtutils"
local status, lib = du.prequire(req_name)
req_name - the filename of the lua code to load without the ".lua" filetype]],
Description = [[prequire is a protected require that can survive an error in the code being loaded without
bringing down the calling routine.]],
Return_Value = [[status - boolean - true on success
lib - if status is true, then the code, otherwise an error message]],
Limitations = [[]],
Example = [[local status, lib = prequire("lib/dtutils.file") which would load lib/dtutils/file.lua which
would return a status of true and the reference to the library in lib.]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils.prequire(req_name)
local status, lib = pcall(require, req_name)
if status then
log.msg(log.info, "Loaded " .. req_name)
else
log.msg(log.info, "Error loading " .. req_name)
end
return status, lib
end
dtutils.libdoc.functions["spairs"] = {
Name = [[spairs]],
Synopsis = [[an iterator that provides sorted pairs from a table]],
Usage = [[local du = require "lib/dtutils"
for key, value in du.spairs(t, order) do
t - table - table of key, value pairs
order - function - an optional function to sort the pairs
if none is supplied, table.sort() is used]],
Description = [[spairs is an iterator that returns key, value pairs from a table in sorted
order. The sorting order is the result of table.sort() if no function is
supplied, otherwise sorting is done as specified in the function.]],
Return_Value = [[]],
Limitations = [[]],
Example = [[HighScore = { Robin = 8, Jon = 10, Max = 11 }
-- basic usage, just sort by the keys
for k,v in spairs(HighScore) do
print(k,v)
end
--> Jon 10
--> Max 11
--> Robin 8
-- this uses an custom sorting function ordering by score descending
for k,v in spairs(HighScore, function(t,a,b) return t[b] < t[a] end) do
print(k,v)
end
--> Max 11
--> Jon 10
--> Robin 8]],
See_Also = [[]],
Reference = [[Code copied from http://stackoverflow.com/questions/15706270/sort-a-table-in-lua]],
License = [[]],
Copyright = [[]],
}
-- Sort a table
function dtutils.spairs(_table, order) -- Code copied from http://stackoverflow.com/questions/15706270/sort-a-table-in-lua
-- collect the keys
local keys = {}
for _key in pairs(_table) do keys[#keys + 1] = _key end
-- if order function given, sort by it by passing the table and keys a, b,
-- otherwise just sort the keys
if order then
table.sort(keys, function(a,b) return order(_table, a, b) end)
else
table.sort(keys)
end
-- return the iterator function
local i = 0
return function()
i = i + 1
if keys[i] then
return keys[i], _table[keys[i]]
end
end
end
return dtutils

161
lib/dtutils/debug.lua Normal file
View File

@@ -0,0 +1,161 @@
--[[
This file is part of darktable,
Copyright (c) 2014 Jérémy Rosen
Copyright (c) 2016 Bill Ferguson
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/>.
]]
--[[
DEBUG HELPERS
A collection of helper functions to help debugging lua scripts.
require it as
dhelpers = require "lib/dtutils.debug"
Each function is documented in its own header
]]
local dt = require "darktable"
local io = require "io"
local table = require "table"
require "darktable.debug"
local log = require "lib/dtutils.log"
local M = {} -- The actual content of the module
M.libdoc = {
Name = [[dtutils.debug]],
Synopsis = [[debugging helpers used in developing darktable lua scripts]],
Usage = [[local dd = require "lib/dtutils.debug"]],
Description = [[dtutils.debug provides an interface to the darktable debugging routines.]],
Return_Value = [[dd - library - the darktable lua debugging helpers]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = log.libdoc.License,
Copyright = [[Copyright (c) 2014 Jérémy Rosen
Copyright (c) 2016 Bill Ferguson
]],
functions = {}
}
M.libdoc.functions["tracepoint"] = {
Name = [[tracepoint]],
Synopsis = [[print out a tracepoint and dump the arguments]],
Usage = [[local dd = require "lib/dtutils.debug"
local result = tracepoint(name, ...)
name - string - the name of the tracepoint to print out
... - arguments - variables to dump the contents of]],
Description = [[tracepoint prints its name and dumps its parameters using
dt.debug]],
Return_Value = [[result - ... - the supplied argument list]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function M.tracepoint(name,...)
log.msg(log.always, 4, "***** "..name.." ****")
params = {...}
log.msg(log.always, 0, dt.debug.dump(params,"parameters"))
return ...;
end
M.libdoc.functions["new_tracepoint"] = {
Name = [[new_tracepoint]],
Synopsis = [[create a function returning a tracepoint]],
Usage = [[local dd = require "lib/dtutils.debug"
local result = new_tracepoint(name, ...)
name - string - the name of the tracepoint to print out
... - arguments - variables to dump the contents of]],
Description = [[A function that returns a tracepoint function with the given name
This is mainly used to debug callbacks.]],
Return_Value = [[result - function - a function that returns the result of a tracepoint]],
Limitations = [[]],
Example = [[register_event(event, dd.new_tracepoint("hit callback"))
will print the following each time the callback is called
**** hit callback ****
<all the callback's parameters dumped>]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function M.new_tracepoint(name)
return function(...) return M.tracepoint(name,...) end
end
M.libdoc.functions["dprint"] = {
Name = [[dprint]],
Synopsis = [[pass a variable to dt.debug.dump and print the results to stdout]],
Usage = [[local dd = require "lib/dtutils.debug"
dd.dprint(var)
var - variable - any variable that you want to see the contents of]],
Description = [[Wrapper around debug.dump, will directly print to stdout,
same calling convention]],
Return_Value = [[]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function M.dprint(...)
log.msg(log.always, 4, dt.debug.dump(...))
end
M.libdoc.functions["terse_dump"] = {
Name = [[terse_dump]],
Synopsis = [[set dt.debug.known to shorten all image dumps to a single line]],
Usage = [[local dd = require "lib/dtutils.debug"
dd.terse_dump()]],
Description = [[terse_dump sets dt.debug.known to shorten all images to a single line.
If you don't need to debug the content of images, this will avoid them flooding your logs]],
Return_Value = [[]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function M.terse_dump()
for _,v in ipairs(dt.database) do
dt.debug.known[v] = tostring(v)
end
end
return M
-- vim: shiftwidth=2 expandtab tabstop=2 cindent
-- kate: tab-indents: off; indent-width 2; replace-tabs on; remove-trailing-space on;

394
lib/dtutils/file.lua Normal file
View File

@@ -0,0 +1,394 @@
local dtutils_file = {}
local dt = require "darktable"
local log = require "lib/dtutils.log"
dtutils_file.libdoc = {
Name = [[dtutils.file]],
Synopsis = [[common darktable lua file functions]],
Usage = [[local df = require "lib/dtutils.file"]],
Description = [[[dtutils.file provides common file manipulation functions used in
constructing Darktable lua scripts]],
Return_Value = [[df - library - the file functions]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = log.libdoc.License,
Copyright = [[Copyright (C) 2016 Bill Ferguson <wpferguson@gmail.com>.]],
Copyright = [[Copyright (C) 2016 Bill Ferguson <wpferguson@gmail.com>.
Copyright (C) 2016 Tobias Jakobs]],
functions = {}
}
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("dtutils.file",dt.configuration.config_dir.."/lua/locale/")
local function _(msgid)
return gettext.dgettext("dtutils.file", msgid)
end
dtutils_file.libdoc.functions["check_if_bin_exists"] = {
Name = [[check_if_bin_exists]],
Synopsis = [[check if an executable is in the path]],
Usage = [[local df = require "lib/dtutils.file"
local result = df.check_if_bin_exists(bin)
bin - string - the binary to check for]],
Description = [[check_if_bin_exists checks to see if the specified binary executable is
in the path.]],
Return_Value = [[result - boolean - true if the executable was found, false if not]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_file.check_if_bin_exists(bin)
local result = os.execute("which " .. bin)
if not result then
result = false
end
return result
end
dtutils_file.libdoc.functions["split_filepath"] = {
Name = [[split_filepath]],
Synopsis = [[split a filepath into parts]],
Usage = [[local df = require "lib/dtutils.file"
local result = df.split_filepath(filepath)
filepath - string - path and filename]],
Description = [[split_filepath splits a filepath into the path, filename, basename and filetype and puts
that in a table]],
Return_Value = [[result - table - a table containing the path, filename, basename, and filetype]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_file.split_filepath(str)
-- strip out single quotes from quoted pathnames
str = string.gsub(str, "'", "")
local result = {}
-- Thank you Tobias Jakobs for the awesome regular expression, which I tweaked a little
result["path"], result["filename"], result["basename"], result["filetype"] = string.match(str, "(.-)(([^\\/]-)%.?([^%.\\/]*))$")
return result
end
dtutils_file.libdoc.functions["get_path"] = {
Name = [[get_path]],
Synopsis = [[get the path from a file path]],
Usage = [[local df = require "lib/dtutils.file"
local result = df.get_path(filepath)
filepath - string - path and filename]],
Description = [[get_path strips the filename and filetype from a path and returns the path]],
Return_Value = [[result - string - the path]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_file.get_path(str)
local parts = dtutils_file.split_filepath(str)
return parts["path"]
end
dtutils_file.libdoc.functions["get_filename"] = {
Name = [[get_filename]],
Synopsis = [[get the filename and extension from a file path]],
Usage = [[local df = require "lib/dtutils.file"
local result = df.get_filename(filepath)
filepath - string - path and filename]],
Description = [[get_filename strips the path from a filepath and returns the filename]],
Return_Value = [[result - string - the file name and type]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_file.get_filename(str)
local parts = dtutils_file.split_filepath(str)
return parts["filename"]
end
dtutils_file.libdoc.functions["get_basename"] = {
Name = [[get_basename]],
Synopsis = [[get the filename without the path or extension]],
Usage = [[local df = require "lib/dtutils.file"
local result = df.get_basename(filepath)
filepath - string - path and filename]],
Description = [[get_basename returns the name of the file without the path or filetype
]],
Return_Value = [[result - string - the basename of the file]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_file.get_basename(str)
local parts = dtutils_file.split_filepath(str)
return parts["basename"]
end
dtutils_file.libdoc.functions["get_filetype"] = {
Name = [[get_filetype]],
Synopsis = [[get the filetype from a filename]],
Usage = [[local df = require "lib/dtutils.file"
local result = df.get_filetype(filepath)
filepath - string - path and filename]],
Description = [[get_filetype returns the filetype from the supplied filepath]],
Return_Value = [[result - string - the filetype]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_file.get_filetype(str)
local parts = dtutils_file.split_filepath(str)
return parts["filetype"]
end
-- Thanks Tobias Jakobs for the idea
dtutils_file.libdoc.functions["check_if_file_exists"] = {
Name = [[check_if_file_exists]],
Synopsis = [[check if a file or path exist]],
Usage = [[local df = require "lib/dtutils.file"
local result = df.check_if_file_exists(filepath)
filepath - string - a file or path to check]],
Description = [[check_if_file_exists checks to see if a file or path exists]],
Return_Value = [[result - boolean - true if the file or path exists, false if it doesn't]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_file.check_if_file_exists(filepath)
local result = os.execute("test -e " .. filepath)
if not result then
result = false
end
return result
end
dtutils_file.libdoc.functions["chop_filetype"] = {
Name = [[chop_filetype]],
Synopsis = [[remove a filetype from a filename]],
Usage = [[local df = require "lib/dtutils.file"
local result = df.chop_filetype(path)
path - string - a filename with or without a path]],
Description = [[chop_filetype removes the filetype from the filename]],
Return_Value = [[result - string - the path and filename without the filetype]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_file.chop_filetype(path)
local length = dtutils_file.get_filetype(path):len() + 2
return string.sub(path, 1, -length)
end
dtutils_file.libdoc.functions["file_copy"] = {
Name = [[file_copy]],
Synopsis = [[copy a file to another name/location]],
Usage = [[local df = require "lib/dtutils.file"
local result = df.file_copy(fromFile, toFile)
fromFile - string - name of file to copy from
toFile - string - name of file to copy to]],
Description = [[copy a file using a succession of methods from operating system
to a pure lua solution]],
Return_Value = [[result - boolean - nil on error, true on success]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_file.file_copy(fromFile, toFile)
local result = nil
-- if cp exists, use it
if dtutils_file.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
if not result then
local fileIn, err = io.open(fromFile, 'rb')
if fileIn then
local fileOut, errr = io.open(toFile, 'w')
if fileOut then
local content = fileIn:read(4096)
while content do
fileOut:write(content)
content = fileIn:read(4096)
end
result = true
fileIn:close()
fileOut:close()
else
log.msg(log.error, errr)
end
else
log.msg(log.error, err)
end
end
return result
end
dtutils_file.libdoc.functions["file_move"] = {
Name = [[file_move]],
Synopsis = [[move a file from one directory to another]],
Usage = [[local df = require "lib/dtutils.file"
local result = df.file_move(fromFile, toFile)
fromFile - string - name of the original file
toFile - string - the new file location and name]],
Description = [[Move a file from one place to another. Try a succession of methods from
builtin to operating system to a pure lua solution.]],
Return_Value = [[result - boolean - nil on error, some value on success]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_file.file_move(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 dtutils_file.check_if_bin_exists("mv") then
success = os.execute("mv '" .. fromFile .. "' '" .. toFile .. "'")
end
-- if the mv didn't exist or succeed, then...
if not success then
-- pure lua solution
success = dtutils_file.file_copy(fromFile, toFile)
if success then
os.remove(fromFile)
else
log.msg(log.error, "Unable to move " .. fromFile .. " to " .. toFile .. ". Leaving " .. fromFile .. " in place.")
end
end
end
return success -- nil on error, some value if success
end
dtutils_file.libdoc.functions["filename_increment"] = {
Name = [[filename_increment]],
Synopsis = [[add a two digit increment to a filename]],
Usage = [[local df = require "lib/dtutils.file"
local result = df.filename_increment(filepath)
filepath - string - filename to increment]],
Description = [[filename_increment solves the problem of filename confllict by adding an
increment to the filename. If the supplied filename has no increment then
"01" is added to the basename. If the filename already has an increment, then
1 is added to it and the filename returned.]],
Return_Value = [[result - string - the incremented filename]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_file.filename_increment(filepath)
-- break up the filepath into parts
local path = dtutils_file.get_path(filepath)
local basename = dtutils_file.get_basename(filepath)
local filetype = dtutils_file.get_filetype(filepath)
-- check to see if we've incremented before
local increment = string.match(basename, "_(%d-)$")
if increment then
-- we do 2 digit increments so make sure we didn't grab part of the filename
if string.len(increment) > 2 then
-- we got the filename so set the increment to 01
increment = "01"
else
increment = string.format("%02d", tonumber(increment) + 1)
basename = string.gsub(basename, "_(%d-)$", "")
end
else
increment = "01"
end
local incremented_filepath = path .. basename .. "_" .. increment .. "." .. filetype
return incremented_filepath
end
dtutils_file.libdoc.functions["create_unique_filename"] = {
Name = [[create_unique_filename]],
Synopsis = [[create a unique filename from the supplied argment]],
Usage = [[local df = require "lib/dtutils.file"
local result = df.create_unique_filename(filepath)
filepath - string - the path and filename requested]],
Description = [[create_unique_filename takes a requested filepath and checks to see if
it exists. If if doesn't then it's returned intact. If it already exists, then a two
digit increment is added to the filename and it is tested again. The increment keeps
increasing until either a unique filename is found or there have been 100 attempts.]],
Return_Value = [[result - string - the incremented filename]],
Limitations = [[create_unique_filename will only attempt 100 increments.]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_file.create_unique_filename(filepath)
while dtutils_file.check_if_file_exists(filepath) do
filepath = dtutils_file.filename_increment(filepath)
-- limit to 99 more exports of the original export
if string.match(dtfileutils.get_basename(filepath), "_(d-)$") == "99" then
break
end
end
return filepath
end
return dtutils_file

291
lib/dtutils/log.lua Normal file
View File

@@ -0,0 +1,291 @@
local dtutils_log = {}
dtutils_log.libdoc = {
Name = [[dtutils.log]],
Synopsis = [[darktable lua logging library]],
Usage = [[local log = require "lib/dtutils.log"]],
Description = [[log provides a multi-level logging solution for use with
the darktable lua scripts. With this library you can leave log messages
scattered through out your code and only turn them on as necessary.]],
Return_Value = [[log - library - the darktable lua logging functions]],
Limitations = [[]],
Example = [[local log = require "lib/dtutils.log"
local cur_level = log.log_level()
log.log_level(log.warn)
print out warning, error and success messages as code is running
log.log_level(debug)
print out debugging messages too because this isnt working
log.log_level(info)
I want to make sure this is working ok
log.log_level(cur_level)
reset the logging level back to normal]],
See_Also = [[]],
Reference = [[]],
License = [[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/>.]],
Copyright = [[Copyright (C) 2016 Bill Ferguson <wpferguson@gmail.com>.]],
functions = {}
}
local dt = require "darktable"
local dt_print_error = dt.print_error
-- work around until dt.print_log()
local dt_print_log = dt.print_error
local dt_print = dt.print
-- set the default log levels
dtutils_log.debug = {
label = "DEBUG:",
enabled = false,
engine = dt_print_log,
level = 1,
}
dtutils_log.info = {
label = "INFO:",
enable = false,
engine = dt_print_log,
level = 2,
}
dtutils_log.warn = {
label = "WARN:",
enabled = false,
engine = dt_print_log,
level = 3,
}
dtutils_log.error = {
label = "ERROR:",
enabled = true,
engine = dt_print_error,
level = 4,
}
dtutils_log.success = {
label = "SUCCESS:",
enabled = true,
engine = dt_print_log,
level = 5,
}
dtutils_log.screen = {
label = "",
enabled = true,
engine = dt_print,
level = 9,
}
dtutils_log.always = {
label = "",
enabled = true,
engine = dt_print_log,
level = 9,
}
dtutils_log.critical = {
label = "CRITICAL:",
enabled = true,
engine = print,
level = 9,
}
dtutils_log.libdoc.functions["caller"] = {
Name = [[caller]],
Synopsis = [[get the name and line number of the calling routine]],
Usage = [[local log = require "lib/dtutils.log"
result = log.caller(level)
level - number - the number of stack levels to go down to retrieve the caller routine information]],
Description = [[caller gets the name and line number of the calling routine and returns it]],
Return_Value = [[result - string - the name and line number of the calling function or 'callback: ' if the attempt to get the
caller returns nil]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_log.caller(level)
local name = debug.getinfo(level).name
local lineno = nil
local source = nil
if name then
lineno = debug.getinfo(level).currentline
-- returns the path to the file prefixed with @
source = debug.getinfo(level).source
-- we just need the filename, so grab it from the string
-- Thanks, Tobias Jakobs :-)
source = string.match(source, "@.-([^\\/]-%.?[^%.\\/]*)$")
return name .. ": " .. source .. ": " .. lineno .. ":"
else
return "callback:"
end
end
dtutils_log.libdoc.functions["msg"] = {
Name = [[msg]],
Synopsis = [[print a log message]],
Usage = [[local log = require "lib/log"
log.msg(level, ...)
level - table - the type of message, one of:
log.debug - debugging messages
log.info - informational messages
log.warn - warning messages
log.error - error messages
log.success - success messages
log.always - an internal message for debugging
log.screen - output 1 line of text to the screen
log.critical - print a critical message to the console
... - string(s) - the message to print, which could be a comma separated set of strings]],
Description = [[msg checks the level to see if it is enabled, then prints the level type and message if it is.
Messages are output using the engine configured in each log level.]],
Return_Value = [[]],
Limitations = [[If you use log.msg in a callback, the name of the calling routine can't be determined. A solution
is to include some means of reference such as the name of the callback as an argument, i.e.
log.msg(log.debug, "libPlugin.format_combobox:", "value is " .. self.value)
which would result in
DEBUG: callback: libPlugin.format_combobox: value is JPEG]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_log.msg(level, ...)
if level.enabled then
local args = {...}
local call_level = 3
if level == dtutils_log.always then
call_level = args[1]
table.remove(args, 1)
end
local log_msg = level.label
if level.engine ~= dt_screen and call_level ~= 0 then
log_msg = log_msg .. dtutils_log.caller(call_level) .. " "
elseif log_msg:len() > 2 then
log_msg = log_msg .. " "
end
for i = 1,#args do
log_msg = log_msg .. tostring(args[i]) .. " "
end
level.engine(log_msg)
end
end
dtutils_log.libdoc.functions["log_level"] = {
Name = [[log_level]],
Synopsis = [[get or set the log level]],
Usage = [[local log = require "lib/log"
local result = log.log_level(...)
... - arguments - if none is supplied, then the current log level is returned as one of:
log.debug, log.info, log.warn, log.error, log.success. If one of log.debug, log.info, log.warn,
log.error, or log.success is supplied as the argument then the log level is set to that value. All
log levels greater than or equal in value will be enabled. Any levels of lesser value will be disabled.]],
Description = [[log_level gets and sets the logging level. When called with no arguments the current log level
is returned as one of log.debug, log.info, log.warn, log.error, or log.success. When called with one of log.debug,
log.info, log.warn, log.error or log.success then the log level is set. When setting the log level all levels
equal or greater are enabled and any of lesser value are disabled. See the example.]],
Return_Value = [[result - the log level, one of log.debug, log.info, log.warn, log.error or log.success]],
Limitations = [[]],
Example = [[Assume that the current log level is log.error. Calling log.log_level() will return log.error.
Calling log.log_level(log.info) will leave log.debug disabled, and enable log.info, log.warn, log.error and
log.success. log.info will be returned as the log_level.]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_log.log_level(...)
local levels = {"debug", "info", "warn", "error", "success"}
local args = {...}
local log_level = nil
if #args > 0 then
log_level = args[1]
if log_level == dtutils_log.critical or
log_level == dtutils_log.screen or
log_level == dtutils_log.always then
-- these aren't valid for setting levels
return nil
else
for _,v in ipairs(levels) do
if dtutils_log[v].level >= log_level.level then
dtutils_log[v].enabled = true
else
dtutils_log[v].enabled = false
end
end
end
else
for _,v in ipairs(levels) do
if dtutils_log[v].enabled == true then
log_level = dtutils_log[v]
end
end
end
return log_level
end
dtutils_log.libdoc.functions["engine"] = {
Name = [[engine]],
Synopsis = [[get and set the output engine]],
Usage = [[local log = require "lib/dtutils.log"
result = log.engine(level, ...)
level - table - the log level to get or set the engine for, one of log.debug, log.info, log.warn, log.error
log.success, log.always, log.screen, log.critical
... - function - the output function, one of dt.print, dt.print_error, dt.print_log, print
if not function is included, the current engine is returned for the specified log level]],
Description = [[engine returns the output engine for the specified log level if a second argument is not
supplied. If a function is supplied as the second argment, then the output engine for the specified log level
is set to that.]],
Return_Value = [[result - function - the current output engine]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[]],
Copyright = [[]],
}
function dtutils_log.print_engine(level, ...)
local engines = {"dt_print", "dt_print_error", "dt_print_log", "print"}
local args = {...}
local cur_engine = ""
if #args == 0 then
cur_engine = level.engine
else
for _,v in ipairs(engines) do
if args[1] == v then
level.engine = args[1]
cur_engine = level.engine
end
end
end
return cur_engine
end
return dtutils_log

173
lib/dtutils/string.lua Normal file
View File

@@ -0,0 +1,173 @@
local dtutils_string = {}
dtutils_string.libdoc = {
Name = [[dtutils.string]],
Synopsis = [[a library of string utilities for use in darktable lua scripts]],
Usage = [[local ds = require "lib/dtutils.string"]],
Description = [[This library contains string manipulation routines to aid in building
darktable lua scripts.]],
Return_Value = [[du - library - the darktable lua string library]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[]],
License = [[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/>.]],
Copyright = [[Copyright (c) 2016 Bill Ferguson <wpferguson@gmail.com>]],
functions = {}
}
dtutils_string.libdoc.functions["strip_accents"] = {
Name = [[strip_accents]],
Synopsis = [[strip accents from characters]],
Usage = [[local ds = require "lib/dtutils.string"
local result = ds.strip_accents(str)
str - string - the string with characters that need accents removed]],
Description = [[strip_accents removes accents from accented characters returning the
unaccented character.]],
Return_Value = [[result - string - the string containing unaccented characters]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[Copied from https://forums.coronalabs.com/topic/43048-remove-special-characters-from-string/]],
License = [[]],
Copyright = [[]],
}
function dtutils_string.strip_accents( str )
local tableAccents = {}
tableAccents["à"] = "a"
tableAccents["á"] = "a"
tableAccents["â"] = "a"
tableAccents["ã"] = "a"
tableAccents["ä"] = "a"
tableAccents["ç"] = "c"
tableAccents["è"] = "e"
tableAccents["é"] = "e"
tableAccents["ê"] = "e"
tableAccents["ë"] = "e"
tableAccents["ì"] = "i"
tableAccents["í"] = "i"
tableAccents["î"] = "i"
tableAccents["ï"] = "i"
tableAccents["ñ"] = "n"
tableAccents["ò"] = "o"
tableAccents["ó"] = "o"
tableAccents["ô"] = "o"
tableAccents["õ"] = "o"
tableAccents["ö"] = "o"
tableAccents["ù"] = "u"
tableAccents["ú"] = "u"
tableAccents["û"] = "u"
tableAccents["ü"] = "u"
tableAccents["ý"] = "y"
tableAccents["ÿ"] = "y"
tableAccents["À"] = "A"
tableAccents["Á"] = "A"
tableAccents["Â"] = "A"
tableAccents["Ã"] = "A"
tableAccents["Ä"] = "A"
tableAccents["Ç"] = "C"
tableAccents["È"] = "E"
tableAccents["É"] = "E"
tableAccents["Ê"] = "E"
tableAccents["Ë"] = "E"
tableAccents["Ì"] = "I"
tableAccents["Í"] = "I"
tableAccents["Î"] = "I"
tableAccents["Ï"] = "I"
tableAccents["Ñ"] = "N"
tableAccents["Ò"] = "O"
tableAccents["Ó"] = "O"
tableAccents["Ô"] = "O"
tableAccents["Õ"] = "O"
tableAccents["Ö"] = "O"
tableAccents["Ù"] = "U"
tableAccents["Ú"] = "U"
tableAccents["Û"] = "U"
tableAccents["Ü"] = "U"
tableAccents["Ý"] = "Y"
local normalizedString = ""
for strChar in string.gmatch(str, "([%z\1-\127\194-\244][\128-\191]*)") do
if tableAccents[strChar] ~= nil then
normalizedString = normalizedString..tableAccents[strChar]
else
normalizedString = normalizedString..strChar
end
end
return normalizedString
end
dtutils_string.libdoc.functions["escape_xml_characters"] = {
Name = [[escape_xml_characters]],
Synopsis = [[escape characters for xml documents]],
Usage = [[local ds = require "lib/dtutils.string"
local result = ds.escape_xml_characters(str)
str - string - the string that needs escaped]],
Description = [[escape_xml_characters provides the escape sequences for
"&", '"', "'", "<", and ">" with the corresponding "&amp;",
"&quot;", "&apos;", "&lt;", and "&gt;".]],
Return_Value = [[result - string - the string containing escapes for the xml characters]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[https://stackoverflow.com/questions/1091945/what-characters-do-i-need-to-escape-in-xml-documents]],
License = [[]],
Copyright = [[]],
}
-- Keep &amp; first, otherwise it will double escape other characters
function dtutils_string.escape_xml_characters( str )
str = string.gsub(str,"&", "&amp;")
str = string.gsub(str,"\"", "&quot;")
str = string.gsub(str,"'", "&apos;")
str = string.gsub(str,"<", "&lt;")
str = string.gsub(str,">", "&gt;")
return str
end
dtutils_string.libdoc.functions["urlencode"] = {
Name = [[urlencode]],
Synopsis = [[encode a string in a websage manner]],
Usage = [[local ds = require "lib/dtutils.string"
local result = ds.urlencode(str)
str - string - the string that needs to be made websafe]],
Description = [[urlencode converts a string into a websafe version suitable for
use in a web browser.]],
Return_Value = [[result - string - a websafe string]],
Limitations = [[]],
Example = [[]],
See_Also = [[]],
Reference = [[https://forums.coronalabs.com/topic/43048-remove-special-characters-from-string/]],
License = [[]],
Copyright = [[]],
}
function dtutils_string.urlencode(str)
if (str) then
str = string.gsub (str, "\n", "\r\n")
str = string.gsub (str, "([^%w ])", function () return string.format ("%%%02X", string.byte()) end)
str = string.gsub (str, " ", "+")
end
return str
end
return dtutils_string

View File

@@ -31,7 +31,7 @@ local dt = require "darktable"
local https = require "ssl.https"
local cjson = require "cjson"
dt.configuration.check_version(...,{2,0,0})
dt.configuration.check_version(...,{2,0,0},{3,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,

View File

@@ -0,0 +1,128 @@
--[[
This file is part of darktable,
copyright (c) 2016 Tobias Ellinghaus
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/>.
]]
--[[
ADD SUPPORT FOR COPYING METADATA+RATING+COLOR LABELS+TAGS BETWEEN IMAGES
This script adds keyboard shortcuts and buttons to copy/paste metadata between images.
USAGE
* require this script from your main lua file
* it adds buttons to the selected images module
* it adds two keyboard shortcuts
]]
local dt = require "darktable"
dt.configuration.check_version(...,{3,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
local overwrite = true
local have_data = false
local rating = 1
local red = false
local green = false
local yellow = false
local blue = false
local purple = false
local title = ""
local description = ""
local creator = ""
local publisher = ""
local rights = ""
local tags = {}
local function copy(image)
if not image then
have_data = false
else
have_data = true
rating = image.rating
red = image.red
green = image.green
yellow = image.yellow
blue = image.blue
purple = image.purple
title = image.title
description = image.description
creator = image.creator
publisher = image.publisher
rights = image.rights
tags = {}
for _, tag in ipairs(image:get_tags()) do
if not (string.sub(tag.name, 1, string.len("darktable|")) == "darktable|") then
table.insert(tags, tag)
end
end
end
end
local function paste(images)
if have_data then
for _, image in ipairs(images) do
image.rating = rating
image.red = red
image.green = green
image.yellow = yellow
image.blue = blue
image.purple = purple
if image.title == "" or overwrite then
image.title = title
end
if image.description == "" or overwrite then
image.description = description
end
if image.creator == "" or overwrite then
image.creator = creator
end
if image.publisher == "" or overwrite then
image.publisher = publisher
end
if image.rights == "" or overwrite then
image.rights = rights
end
for _, tag in ipairs(tags) do
image:attach_tag(tag)
end
end
end
end
dt.gui.libs.image.register_action(
"copy metadata",
function(event, images) copy(images[1]) end,
"copy metadata of the first selected image"
)
dt.gui.libs.image.register_action(
"paste metadata",
function(event, images) paste(images) end,
"paste metadata to the selected images"
)
dt.register_event(
"shortcut",
function(event, shortcut) copy(dt.gui.action_images[1]) end,
"copy metadata"
)
dt.register_event(
"shortcut",
function(event, shortcut) paste(dt.gui.action_images) end,
"paste metadata"
)

View File

@@ -1,93 +0,0 @@
--[[
This file is part of darktable,
copyright (c) 2014 Jérémy Rosen
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/>.
]]
--[[
DEBUG HELPERS
A collection of helper functions to help debugging lua scripts.
require it as
dhelpers = require "official/debug-helpers"
Each function is documented in its own header
]]
local dt = require "darktable"
local io = require "io"
local table = require "table"
require "darktable.debug"
local M = {} -- The actual content of the module
--[[
A function which prints its name and its parameters
* name : the name of the tracepoint
* ... : anything, will be dumped using dt.debug
]]
function M.tracepoint(name,...)
print("***** "..name.." ****")
params = {...}
print(dt.debug.dump(params,"parameters"))
return ...;
end
--[[
A function that returns a tracepoint function with the given name
This is mainly used to debug callbacks,
register_event(event, dhelpers.new_tracepoint("hit callback"))
will will print the following each time the callback is called
**** hit callback ****
<all the callback's parameters dumped>
]]
function M.new_tracepoint(name)
return function(...) return M.tracepoint(name,...) end
end
--[[
Wrapper around debug.dump, will directly print to stdout,
same calling covention
]]
function M.dprint(...)
print(dt.debug.dump(...))
end
--[[
sets dt.debug.known to shorten all images to a single line
if you don't need to debug the content of images, this will avoid them flooding your logs
]]
function M.terse_dump()
for _,v in ipairs(dt.database) do
dt.debug.known[v] = tostring(v)
end
end
return M
-- vim: shiftwidth=2 expandtab tabstop=2 cindent
-- kate: tab-indents: off; indent-width 2; replace-tabs on; remove-trailing-space on;

View File

@@ -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})
dt.configuration.check_version(...,{2,0,0},{3,0,0})
dt.preferences.register("delete_long_tags", "length", "integer",
"maximum length of tags to keep",

176
official/enfuse.lua Normal file
View File

@@ -0,0 +1,176 @@
--[[
This file is part of darktable,
copyright (c) 2016 Tobias Ellinghaus
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/>.
]]
--[[
RUN ENFUSE ON THE SELECTED IMAGES
This script uses enfuse to merge the selected images into one HDR and imports the result.
It only works on ldr images (like, JPEG).
USAGE
* require this script from your main lua file
* it creates a new lighttable module
TODO
* remember the exposure_mu value in config when the slider is moved
* make the output filename unique so you can use it more than once per filmroll
* find a less stupid way to make sure the float value of exposure_mu gets turned into a string
with a decimal point instead of a comma in some languages
* export images that are not ldr and remove them afterwards
]]
local dt = require "darktable"
require "official/yield"
dt.configuration.check_version(...,{3,0,0})
-- 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
end
-- add a new lib
-- is enfuse installed?
local enfuse_installed = checkIfBinExists("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
dt.preferences.write("enfuse", "depth", "integer", 2)
dt.preferences.write("enfuse", "exposure_mu", "float", 0.5)
end
-- set up some widgets, initialized from config
local exposure_mu = dt.new_widget("slider")
{
label = "exposure mu",
tooltip = "center also known as MEAN of Gaussian weighting function (0 <= MEAN <= 1); default: 0.5",
hard_min = 0,
hard_max = 1,
value = dt.preferences.read("enfuse", "exposure_mu", "float")
}
local depth = dt.new_widget("combobox")
{
label = "depth",
tooltip = "the number of bits per channel of the output image",
value = dt.preferences.read("enfuse", "depth", "integer"),
changed_callback = function(w) dt.preferences.write("enfuse", "depth", "integer", w.selected) end,
"8", "16", "32"
}
-- ... and tell dt about it all
dt.register_lib(
"enfuse", -- plugin name
"enfuse", -- name
true, -- expandable
false, -- resetable
{[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 100}}, -- containers
dt.new_widget("box") -- widget
{
orientation = "vertical",
sensitive = enfuse_installed,
exposure_mu,
depth,
dt.new_widget("button")
{
label = enfuse_installed and "run enfuse" or "enfuse not installed",
clicked_callback = function (_)
-- remember exposure_mu
-- TODO: find a way to save it whenever the value changes
local mu = exposure_mu.value
dt.preferences.write("enfuse", "exposure_mu", "float", mu)
-- create a temp response file
local response_file = os.tmpname()
local f = io.open(response_file, "w")
if not f then
dt.print("error writing to `"..response_file.."'")
os.remove(response_file)
return
end
-- add all filenames to the response file
local cnt = 0
local n_skipped = 0
local target_dir
for _, i in ipairs(dt.gui.action_images) do
-- only use ldr files as enfuse can't open raws. alternatively we could export raws that we encounter
if i.is_ldr then
cnt = cnt + 1
f:write(i.path.."/"..i.filename.."\n")
target_dir = i.path
else
dt.print("skipping "..i.filename)
n_skipped = n_skipped + 1
end
end
f:close()
-- bail out if there is nothing to do
if cnt == 0 then
dt.print("no suitable images selected, nothing to do for enfuse")
os.remove(response_file)
return
end
if n_skipped == 1 then
dt.print(n_skipped.." image skipped")
elseif n_skipped > 1 then
dt.print(n_skipped.." images skipped")
end
-- call enfuse on the response file
-- TODO: find something nicer
local ugly_decimal_point_hack = string.gsub(string.format("%.04f", mu), ",", ".")
-- TODO: make filename unique
local output_image = target_dir.."/enfuse.tiff"
local command = "enfuse --depth "..depth.value.." --exposure-mu "..ugly_decimal_point_hack
.." -o \""..output_image.."\" \"@"..response_file.."\""
if dt.control.execute( command) > 0 then
dt.print("enfuse failed, see terminal output for details")
os.remove(response_file)
return
end
-- remove the response file
os.remove(response_file)
-- import resulting tiff
local image = dt.database.import(output_image)
-- tell the user that everything worked
dt.print("enfuse was successful, resulting image was imported")
-- normally printing to stdout is bad, but we allow enfuse to show its output, so adding one extra line is ok
print("enfuse: done, resulting image '"..output_image.."' was imported with id "..image.id)
end
}
},
nil,-- view_enter
nil -- view_leave
)
-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua
-- kate: hl Lua;

View File

@@ -31,12 +31,14 @@ USAGE
-- TODO:
-- * enable showing of the txt file (plugins/lighttable/draw_custom_metadata) if this script is enabled
-- * maybe allow a lua command returning text instead of a command line call ? both ?
-- * maybe allow a lua command returning text instead of a command line call? both?
-- * make filenames with double quotes (") work
local dt = require "darktable"
require "darktable.debug"
dt.configuration.check_version(...,{2,1,0})
require "official/yield"
dt.configuration.check_version(...,{2,1,0},{3,0,0})
dt.preferences.register("generate_image_txt",
"enabled",
@@ -97,7 +99,7 @@ dt.register_event("mouse-over-image-changed", function(event, img)
local command = command_setting:gsub("%$%(FILE_NAME%)", '"'..img_filename..'"')..' > "'..txt_filename..'"'
-- finally, run it
coroutine.yield("RUN_COMMAND", command)
dt.control.execute( command)
end
)

View File

@@ -28,9 +28,8 @@ 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})
dt.configuration.check_version(...,{2,0,0},{3,0,0})
local main_label = dt.new_widget("label"){selectable = true, ellipsize = "middle", halign = "start"}
@@ -59,6 +58,6 @@ dt.register_lib("image_path_no_ui","Selected Images path",true,false,{
);
dt.register_event("mouse-over-image-changed",reset_widget);
]]
--
-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua

View File

@@ -1,6 +1,6 @@
--[[
This file is part of darktable,
copyright (c) 2015 Tobias Ellinghaus
copyright (c) 2015-2016 Tobias Ellinghaus & Christian Mandel
darktable is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -50,6 +50,11 @@ dt.register_import_filter("prefer raw over jpeg", function(event, images)
local current_base = ""
local jpg_indices = {}
local other_format_found = false
-- add dummy image to force processing for the last image
local last_index
table.insert(images, "")
for i, img in ipairs(images) do
local extension = img:match("[^.]*$"):upper()
local base = img:match("^.*[.]")
@@ -73,7 +78,14 @@ dt.register_import_filter("prefer raw over jpeg", function(event, images)
other_format_found = true
end
last_index = i
end
-- remove dummy image from list (just to make sure, it works even with keeping
-- the dummy but that may break in the future), table.remove(images) does not
-- work reliable because it can fail for sparse tables
images[last_index] = nil
end)
-- vim: shiftwidth=2 expandtab tabstop=2 cindent

View File

@@ -34,7 +34,7 @@ increase it if you need more temporary selection buffers
]]
local dt = require "darktable"
dt.configuration.check_version(...,{2,0,0})
dt.configuration.check_version(...,{2,0,0},{3,0,0})
local buffer_count = 5
@@ -45,7 +45,7 @@ for i=1,buffer_count do
end,"save to buffer "..i)
dt.register_event("shortcut",function()
dt.gui.selection(saved_selection)
end,"restor from buffer "..i)
end,"restore from buffer "..i)
end
local bounce_buffer = {}

View File

@@ -1,6 +1,7 @@
--[[
This file is part of darktable,
copyright (c) 2015 Jérémy Rosen & Pascal Obry
edited 2016 Tejovanth N
darktable is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -28,10 +29,14 @@ USAGE
This plugin will add a new exporter that will allow you to generate the pdf file
Plugin allows you to choose how many thumbnails you need per row
]]
local dt = require "darktable"
dt.configuration.check_version(...,{2,0,0})
require "official/yield"
dt.configuration.check_version(...,{2,0,0},{3,0,0})
dt.preferences.register
("selection_to_pdf","Open with","string",
@@ -40,20 +45,29 @@ dt.preferences.register
"xdg-open")
local title_widget = dt.new_widget("entry") {
placeholder="Title"
placeholder="Title"
}
local no_of_thumbs_widget = dt.new_widget("slider")
{
label = "Thumbs per Line",
soft_min = 1, -- The soft minimum value for the slider, the slider can't go beyond this point
soft_max = 10, -- 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 = 10, -- The hard maximum value for the slider, the user can't manually enter a value beyond this point
value = 4 -- The current value of the slider
}
local widget = dt.new_widget("box") {
orientation=horizontal,
dt.new_widget("label"){label = "Title:"},
title_widget
orientation=horizontal,
dt.new_widget("label"){label = "Title:"},
title_widget,
dt.new_widget("label"){label = "Thumbnails per row:"},
no_of_thumbs_widget
}
local ending = [[
\end{document}
]]
local thumbs_per_line=4;
local width = 1/thumbs_per_line-0.01
local filename =dt.configuration.tmp_dir.."/pdfout.tex"
@@ -93,23 +107,27 @@ dt.register_storage("export_pdf","Export thumbnails to pdf",
local my_title = title_widget.text
if my_title == "" then
my_title = "Title"
end
local preamble = [[
\documentclass[a4paper,10pt]{article}
\usepackage{graphicx}
\pagestyle{empty}
\parindent0pt
\usepackage{geometry}
\geometry{a4paper,left=5mm,right=5mm, top=5mm, bottom=5mm}
\begin{document}
{\Large\bfseries ]]..my_title..[[} \\
\bigskip\bigskip
]]
end
local thumbs_per_line = no_of_thumbs_widget.value
thumbs_per_line = tonumber(thumbs_per_line)
width = (1/thumbs_per_line) - 0.01
local errmsg
local latexfile
latexfile,errmsg=io.open(filename,"w")
if not latexfile then
local preamble = [[
\documentclass[a4paper,10pt]{article}
\usepackage{graphicx}
\pagestyle{empty}
\parindent0pt
\usepackage{geometry}
\geometry{a4paper,left=5mm,right=5mm, top=5mm, bottom=5mm}
\begin{document}
{\Large\bfseries ]]..my_title..[[} \\
\bigskip\bigskip
]]
local errmsg
local latexfile
latexfile,errmsg=io.open(filename,"w")
if not latexfile then
error(errmsg)
end
my_write(latexfile,preamble)
@@ -128,7 +146,7 @@ dt.register_storage("export_pdf","Export thumbnails 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 = coroutine.yield("RUN_COMMAND",command)
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)
@@ -138,7 +156,7 @@ dt.register_storage("export_pdf","Export thumbnails to pdf",
local pdffile=string.gsub(filename, ".tex", ".pdf")
command = dt.preferences.read("selection_to_pdf","Open with","string")
command = command.." "..pdffile
local result = coroutine.yield("RUN_COMMAND",command)
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)

57
official/yield.lua Normal file
View File

@@ -0,0 +1,57 @@
--[[
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 yield compatibility script
USAGE
* require this script from your main Lua file in the first line
]]
local dt = require "darktable"
local yield_orig = coroutine.yield
-- 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)
yield_orig("RUN_COMMAND", command)
end
dt.control.read = function(command)
yield_orig("FILE_READABLE", command)
end
dt.control.sleep = function(command)
yield_orig("WAIT_MS", command)
end
end
-- vim: shiftwidth=2 expandtab tabstop=2 cindent syntax=lua
-- kate: hl Lua;

View File

@@ -0,0 +1,76 @@
--[[
get_lib_manpages.lua - retrieve the included library documentation and output it as man pages
Copyright (c) 2016, Bill Ferguson
]]
local dt = require "darktable"
local du = require "lib/dtutils"
local df = require "lib/dtutils.file"
local log = require "lib/dtutils.log"
local libname = nil
dt.configuration.check_version(...,{3,0,0})
local keys = {"Name", "Synopsis", "Usage", "Description", "Return_Value", "Limitations",
"Example", "See_Also", "Reference", "License", "Copyright"}
local function output_man(d)
local name = d["Name"]
if not libname then
libname = name
end
local fname = "/tmp/" .. name .. ".3"
local mf = io.open(fname, "w")
if mf then
mf:write(".TH " .. string.upper(name) .. " 3 \"\" \"\" \"Darktable " .. libname .. " functions\"\n")
for _,section in ipairs(keys) do
if d[section]:len() > 0 then
mf:write(".SH " .. string.upper(string.gsub(section, "_", " ")) .. "\n")
mf:write(d[section] .. "\n")
end
end
mf:close()
if df.check_if_bin_exists("groff") then
if df.check_if_bin_exists("ps2pdf") then
os.execute("groff -man " .. fname .. " | ps2pdf - " .. fname .. ".pdf")
else
log.msg(log.error, "Missing ps2pdf. Can't generate pdf man pages.")
end
else
log.msg(log.error, "Missing groff. Can't generate pdf man pages.")
end
else
log.msg(log.error, "Can't open file " .. fname .. "for writing")
end
end
-- find the libraries
local output = io.popen("cd "..dt.configuration.config_dir.."/lua/lib ;find . -name \\*.lua -print | sort")
-- loop through the libraries
for line in output:lines() do
line = string.gsub(line, "/", ".")
local lib_name = line:sub(3,-5)
if lib_name:len() > 2 then
lib_name = "lib/" .. lib_name
local lib = require(lib_name)
-- print the documentation for the library
if lib.libdoc then
local doc = lib.libdoc
if doc then
output_man(doc)
for _,fdoc in pairs(doc.functions) do
-- print the documentation for each of the functions
output_man(fdoc)
end
end
end
end
libname = nil
end

49
tools/get_libdoc.lua Normal file
View File

@@ -0,0 +1,49 @@
--[[
get_libdoc.lua - retrieve the included library documentation and output it
Copyright (c) 2016, Bill Ferguson
]]
local dt = require "darktable"
dt.configuration.check_version(...,{3,0,0})
local keys = {"Name", "Synopsis", "Usage", "Description", "Return_Value", "Limitations",
"Example", "See_Also", "Reference", "License", "Copyright"}
local function output_doc(d)
for _,section in ipairs(keys) do
if d[section]:len() > 0 then
print(string.upper(string.gsub(section, "_", " ")))
print("\t" .. d[section] .. "\n")
end
end
print("\f")
end
-- find the libraries
local output = io.popen("cd "..dt.configuration.config_dir.."/lua/lib ;find . -name \\*.lua -print | sort")
-- loop through the libraries
for line in output:lines() do
line = string.gsub(line, "/", ".")
local lib_name = line:sub(3,-5)
if lib_name:len() > 2 then
lib_name = "lib/" .. lib_name
local lib = require(lib_name)
-- print the documentation for the library
if lib.libdoc then
local doc = lib.libdoc
output_doc(doc)
for _,fdoc in pairs(doc.functions) do
-- print the documentation for each of the functions
output_doc(fdoc)
end
end
end
end