diff --git a/ChangeLog.md b/ChangeLog.md index 34d4d96..c84cc31 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,4 +1,5 @@ ## Changes from most recent to oldest +**31 Aug 2021 - wpferguson - remove styles hiding from AutoGrouper.lua** **02 Jul 2021 - wpferguson - merged API-7.0.0-dev branch to master** * API-7.0.0 is darktable 3.6 * breaking changes diff --git a/contrib/AutoGrouper.lua b/contrib/AutoGrouper.lua index a1d449d..58a8c1b 100644 --- a/contrib/AutoGrouper.lua +++ b/contrib/AutoGrouper.lua @@ -41,9 +41,6 @@ local du = require "lib/dtutils" du.check_min_api_version("7.0.0", "AutoGrouper") -dt.print_log("hiding styles") -dt.gui.libs["styles"].visible = false - local MOD = 'autogrouper' -- return data structure for script_manager @@ -218,4 +215,4 @@ script_data.destroy_method = "hide" script_data.restart = restart script_data.show = restart -return script_data \ No newline at end of file +return script_data diff --git a/contrib/color_profile_manager.lua b/contrib/color_profile_manager.lua new file mode 100644 index 0000000..bd09755 --- /dev/null +++ b/contrib/color_profile_manager.lua @@ -0,0 +1,372 @@ +--[[ + + color_profile_manager.lua - manage external darktable color profiles + + Copyright (C) 2021 Bill Ferguson . + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +]] +--[[ + color_profile_manager - manage external darktable color profiles + + This script provides a tool to manage input and output external color + profiles used by darktable. Color profiles can be added or removed + to/from the correct directories so that darktable can find and use + them. + + ADDITIONAL SOFTWARE NEEDED FOR THIS SCRIPT + * None + + USAGE + * require this script from your main lua file + * select the input or output set of color profiles + * a list of profiles is displayed. Click the check box beside the + profile name to select it for removal. Click the "remove profile" + button to remove the profile. + * use the file selector to select a color profile to add to the currently + selected set (input or output) + * click the "add profile" button to add the profile to the selected set + + BUGS, COMMENTS, SUGGESTIONS + * Send to Bill Ferguson, wpferguson@gmail.com or raise an issue on + https://github.com/dakrtable-org/lua-scripts +]] +local dt = require "darktable" +local du = require "lib/dtutils" +local df = require "lib/dtutils.file" + +du.check_min_api_version("7.0.0", "color_profile_manager") + +-- - - - - - - - - - - - - - - - - - - - - - - - +-- L O C A L I Z A T I O N +-- - - - - - - - - - - - - - - - - - - - - - - - + +local gettext = dt.gettext + +-- Tell gettext where to find the .mo file translating messages for a particular domain +gettext.bindtextdomain("color_profile_manager", dt.configuration.config_dir .. "/lua/locale/") + +local function _(msgid) + return gettext.dgettext("color_profile_manager", msgid) +end + +-- - - - - - - - - - - - - - - - - - - - - - - - +-- C O N S T A N T S +-- - - - - - - - - - - - - - - - - - - - - - - - + +local MODULE_NAME = "color_profile_manager" +local PS = dt.configuration.running_os == "windows" and "\\" or "/" +local CS = dt.configuration.running_os == "windows" and "&" or ";" +local DIR_CMD = dt.configuration.running_os == "windows" and "dir /b" or "ls" +local COLOR_IN_DIR = dt.configuration.config_dir .. PS .. "color" .. PS .. "in" +local COLOR_OUT_DIR = dt.configuration.config_dir .. PS .. "color" .. PS .. "out" + +-- - - - - - - - - - - - - - - - - - - - - - - - +-- N A M E S P A C E +-- - - - - - - - - - - - - - - - - - - - - - - - + +local cpm = {} +cpm.widgets = {} +cpm.widgets.profile_box = dt.new_widget("box"){ + orientation = "vertical", +} +cpm.module_installed = false +cpm.event_registered = false +-- - - - - - - - - - - - - - - - - - - - - - - - +-- F U N C T I O N S +-- - - - - - - - - - - - - - - - - - - - - - - - + +local function check_for_directories() + if not df.test_file(COLOR_IN_DIR, "d") then + dt.print_log("didn't find " .. COLOR_IN_DIR) + return false + elseif not df.test_file(COLOR_OUT_DIR, "d") then + dt.print_log("didn't find " .. COLOR_OUT_DIR) + return false + else + dt.print_log("both directories exist") + return true + end +end + +local function add_directories() + df.mkdir(COLOR_IN_DIR) + df.mkdir(COLOR_OUT_DIR) +end + +local function list_profiles(dir) + local files = {} + local p = io.popen(DIR_CMD .. " " .. dir) + if p then + for line in p:lines() do + table.insert(files, line) + end + end + p:close() + return files +end + +local function add_profile(file, dir) + df.file_copy(file, dir) + dt.print(_("added color profile " .. file .. " to " .. dir)) + dt.print_log("color profile " .. file .. " added to " .. dir) +end + +local function remove_profile(file, dir) + os.remove(dir .. PS .. file) + dt.print(_("removed color profile " .. file .. " from " .. dir)) + dt.print_log("color profile " .. file .. " removed from " .. dir) +end + +local function clear_profile_box() + for i = #cpm.widgets.profile_box, 1, -1 do + cpm.widgets.profile_box[i] = nil + end +end + +local function add_profile_callback() + local profile_dir = COLOR_IN_DIR + if cpm.widgets.profile_set.selected == 2 then + profile_dir = COLOR_OUT_DIR + end + + local new_profile = cpm.widgets.profile_selector.value + if string.lower(df.get_filetype(new_profile)) ~= "icm" and string.lower(df.get_filetype(new_profile)) ~= "icc" then + dt.print(_("ERROR: color profile must be an icc or icm file")) + dt.print_error(new_profile .. " selected and isn't an icc or icm file") + return + end + + -- set selector value to directory that new profile came from + -- in case there are more + cpm.widgets.profile_selector.value = df.get_path(cpm.widgets.profile_selector.value) + add_profile(new_profile, profile_dir) + local files = list_profiles(profile_dir) + local widgets = {} + + local profile_ptr = 1 + for i, file in ipairs(files) do + if #cpm.widgets.profile_box == 0 or cpm.widgets.profile_box[profile_ptr].label ~= file then + table.insert(widgets, dt.new_widget("check_button"){value = false, label = file}) + else + table.insert(widgets, cpm.widgets.profile_box[profile_ptr]) + profile_ptr = profile_ptr + 1 + if profile_ptr > #cpm.widgets.profile_box then + profile_ptr = #cpm.widgets.profile_box + end + end + end + clear_profile_box() + for _, widget in ipairs(widgets) do + table.insert(cpm.widgets.profile_box, widget) + end + if not cpm.widgets.remove_box.visible then + cpm.widgets.remove_box.visible = true + end +end + +local function remove_profile_callback() + local widgets_to_keep = {} + local profile_dir = COLOR_IN_DIR + if cpm.widgets.profile_set.selected == 2 then + profile_dir = COLOR_OUT_DIR + end + + for _, widget in ipairs(cpm.widgets.profile_box) do + if widget.value == true then + remove_profile(widget.label, profile_dir) + else + table.insert(widgets_to_keep, widget) + end + end + clear_profile_box() + for _, widget in ipairs(widgets_to_keep) do + table.insert(cpm.widgets.profile_box, widget) + end + if #cpm.widgets.profile_box == 0 then + cpm.widgets.remove_box.visible = false + else + cpm.widgets.remove_box.visible = true + end +end + +local function list_profile_callback(choice) + local list_dir = COLOR_IN_DIR + if choice == 2 then + list_dir = COLOR_OUT_DIR + end + + local files = list_profiles(list_dir) + + if #files == 0 then + cpm.widgets.remove_box.visible = false + else + cpm.widgets.remove_box.visible = true + end + + clear_profile_box() + + for i, file in ipairs(files) do + cpm.widgets.profile_box[i] = dt.new_widget("check_button"){value = false, label = file} + end +end + +local function install_module() + if not cpm.module_installed then + dt.register_lib( + MODULE_NAME, -- Module name + _("color profile manager"), -- Visible name + true, -- expandable + false, -- resetable + {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_LEFT_CENTER", 0}}, -- containers + cpm.widgets.main_widget, + nil,-- view_enter + nil -- view_leave + ) + cpm.module_installed = true + dt.control.sleep(500) + if not cpm.initialized then + cpm.widgets.profile_set.visible = false + cpm.widgets.add_box.visible = false + cpm.widgets.remove_box.visible = false + else + cpm.widgets.profile_set.selected = 1 + end + end +end + +local function destroy() + dt.gui.libs[MODULE_NAME].visible = false + return +end + +local function restart() + dt.gui.libs[MODULE_NAME].visible = true + return +end +-- - - - - - - - - - - - - - - - - - - - - - - - +-- W I D G E T S +-- - - - - - - - - - - - - - - - - - - - - - - - + +cpm.initialized = check_for_directories() +dt.print_log("cpm.initialized is " .. tostring(cpm.initialized)) + +if not cpm.initialized then + dt.print_log("creating init_box") + cpm.widgets.init_box = dt.new_widget("box"){ + orientation = "vertical", + dt.new_widget("button"){ + label = _("initialize color profiles"), + tooltip = _("create the directory structure to contain the color profiles"), + clicked_callback = function(this) + add_directories() + cpm.initialized = true + cpm.widgets.profile_set.visible = true + cpm.widgets.add_box.visible = true + cpm.widgets.remove_box.visible = false + cpm.widgets.init_box.visible = false + cpm.widgets.profile_set.selected = 1 + end + } + } +end + +cpm.widgets.profile_set = dt.new_widget("combobox"){ + label = _("select profile set"), + tooltip = _("select input or output profiles"), + visible = cpm.initialized and false or true, + changed_callback = function(this) + if cpm.initialized then + list_profile_callback(this.selected) + end + end, + _("input"), _("output"), +} + +cpm.widgets.profile_selector = dt.new_widget("file_chooser_button"){ + title = _("select color profile to add"), + tooltip = _("select the .icc or .icm file to add"), + is_directory = false +} + +cpm.widgets.add_box = dt.new_widget("box"){ + orientation = "vertical", + visible = cpm.initialized and true or false, + dt.new_widget("section_label"){label = _("add profile")}, + cpm.widgets.profile_selector, + dt.new_widget("button"){ + label = _("add selected color profile"), + tooltip = _("add selected file to profiles"), + clicked_callback = function(this) + add_profile_callback() + end + } +} + +cpm.widgets.remove_box = dt.new_widget("box"){ + orientation = "vertical", + visible = cpm.initialized and true or false, + dt.new_widget("section_label"){label = _("remove profile")}, + cpm.widgets.profile_box, + dt.new_widget("button"){ + label = _("remove selected profile(s)"), + tooltip = _("remove the checked profile(s)"), + clicked_callback = function(this) + remove_profile_callback() + end + } +} + +local main_widgets = {} + +if not cpm.initialized then + table.insert(main_widgets, cpm.widgets.init_box) +end +table.insert(main_widgets, cpm.widgets.profile_set) +table.insert(main_widgets, cpm.widgets.remove_box) +table.insert(main_widgets, cpm.widgets.add_box) + +cpm.widgets.main_widget = dt.new_widget("box"){ + orientation = "vertical", + table.unpack(main_widgets) +} + +-- - - - - - - - - - - - - - - - - - - - - - - - +-- M A I N +-- - - - - - - - - - - - - - - - - - - - - - - - + +if dt.gui.current_view().id == "lighttable" then + install_module() +else + if not cpm.event_registered then + dt.register_event( + MODULE_NAME, "view-changed", + function(event, old_view, new_view) + if new_view.name == "lighttable" and old_view.name == "darkroom" then + install_module() + end + end + ) + cpm.event_registered = true + end +end + +local script_data = {} + +script_data.destroy = destroy +script_data.restart = restart +script_data.destroy_method = "hide" +script_data.show = restart + +return script_data \ No newline at end of file diff --git a/contrib/harmonic_armature_guide.lua b/contrib/harmonic_armature_guide.lua new file mode 100644 index 0000000..e5c23f2 --- /dev/null +++ b/contrib/harmonic_armature_guide.lua @@ -0,0 +1,78 @@ +--[[ + harmonic artmature guide for darktable + + copyright (c) 2021 Hubert Kowalski + + 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 . +]] + +--[[ +HARMONIC ARMATURE GUIDE +Harmonic Armature (also known as 14 line armature) + +INSTALLATION +* copy this file in $CONFIGDIR/lua/contrib where CONFIGDIR is your darktable configuration directory +* add the following line in the file $CONFIGDIR/luarc + require "contrib/harmonic_armature_guide" + +USAGE +* when using guides, select "harmonic armature" as guide +]] + +local dt = require "darktable" +local du = require "lib/dtutils" +local gettext = dt.gettext + +du.check_min_api_version("2.0.0", "harmonic_armature_guide") + +-- Tell gettext where to find the .mo file translating messages for a particular domain +gettext.bindtextdomain("harmonic_armature_guide",dt.configuration.config_dir.."/lua/locale/") + +local function _(msgid) + return gettext.dgettext("harmonic_armature_guide", msgid) +end + +dt.guides.register_guide("harmonic armature", +-- draw +function(cairo, x, y, width, height, zoom_scale) + cairo:save() + + cairo:translate(x, y) + cairo:scale(width, height) + + cairo:move_to(0,0) + cairo:line_to(1, 0.5) + cairo:line_to(0.5, 1) + cairo:line_to(0,0) + cairo:line_to(1, 1) + cairo:line_to(0.5, 0) + cairo:line_to(0, 0.5) + cairo:line_to(1, 1) + + cairo:move_to(1, 0) + cairo:line_to(0, 0.5) + cairo:line_to(0.5, 1) + cairo:line_to(1, 0) + cairo:line_to(0, 1) + cairo:line_to(0.5, 0) + cairo:line_to(1, 0.5) + cairo:line_to(0, 1) + + cairo:restore() +end, +-- gui +function() + return dt.new_widget("label"){label = _("harmonic armature"), halign = "start"} +end +) \ No newline at end of file diff --git a/contrib/rename_images.lua b/contrib/rename_images.lua new file mode 100644 index 0000000..4ddf78f --- /dev/null +++ b/contrib/rename_images.lua @@ -0,0 +1,315 @@ +--[[ + + rename.lua - rename image file(s) + + Copyright (C) 2020, 2021 Bill Ferguson . + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +]] +--[[ + rename - rename an image file or files + + This shortcut resets the GPS information to that contained within + the image file. If no GPS info is in the image file, the GPS data + is cleared. + + USAGE + * require this script from your luarc file or start it from script_manager + * select an image or images + * enter a renaming pattern + * click the button to rename the files + + BUGS, COMMENTS, SUGGESTIONS + * Send to Bill Ferguson, wpferguson@gmail.com + + CHANGES + + TODO + * Add pattern builder + * Add new name preview +]] + +local dt = require "darktable" +local du = require "lib/dtutils" +local df = require "lib/dtutils.file" + +du.check_min_api_version("7.0.0", "rename_images") + +local gettext = dt.gettext + +-- Tell gettext where to find the .mo file translating messages for a particular domain +gettext.bindtextdomain("rename_images",dt.configuration.config_dir.."/lua/locale/") + +local function _(msgid) + return gettext.dgettext("rename_images", msgid) +end + +-- namespace variable +local rename = { + presets = {}, + substitutes = {}, + placeholders = {"ROLL_NAME","FILE_FOLDER","FILE_NAME","FILE_EXTENSION","ID","VERSION","SEQUENCE","YEAR","MONTH","DAY", + "HOUR","MINUTE","SECOND","EXIF_YEAR","EXIF_MONTH","EXIF_DAY","EXIF_HOUR","EXIF_MINUTE","EXIF_SECOND", + "STARS","LABELS","MAKER","MODEL","TITLE","CREATOR","PUBLISHER","RIGHTS","USERNAME","PICTURES_FOLDER", + "HOME","DESKTOP","EXIF_ISO","EXIF_EXPOSURE","EXIF_EXPOSURE_BIAS","EXIF_APERTURE","EXIF_FOCUS_DISTANCE", + "EXIF_FOCAL_LENGTH","LONGITUDE","LATITUDE","ELEVATION","LENS","DESCRIPTION","EXIF_CROP"}, + widgets = {}, +} +rename.module_installed = false +rename.event_registered = false + +-- script_manager integration +local script_data = {} + +script_data.destroy = nil -- function to destory the script +script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil +script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again + + +-- - - - - - - - - - - - - - - - - - - - - - - - +-- C O N S T A N T S +-- - - - - - - - - - - - - - - - - - - - - - - - + +local MODULE_NAME = "rename_images" +local PS = dt.configuration.running_os == "windows" and "\\" or "/" +local USER = os.getenv("USERNAME") +local HOME = os.getenv(dt.configuration.running_os == "windows" and "HOMEPATH" or "HOME") +local PICTURES = HOME .. PS .. dt.configuration.running_os == "windows" and "My Pictures" or "Pictures" +local DESKTOP = HOME .. PS .. "Desktop" + +-- - - - - - - - - - - - - - - - - - - - - - - - +-- F U N C T I O N S +-- - - - - - - - - - - - - - - - - - - - - - - - + +local function build_substitution_list(image, sequence, datetime, username, pic_folder, home, desktop) + -- build the argument substitution list from each image + -- local datetime = os.date("*t") + local colorlabels = {} + if image.red then table.insert(colorlabels, "red") end + if image.yellow then table.insert(colorlabels, "yellow") end + if image.green then table.insert(colorlabels, "green") end + if image.blue then table.insert(colorlabels, "blue") end + if image.purple then table.insert(colorlabels, "purple") end + local labels = #colorlabels == 1 and colorlabels[1] or du.join(colorlabels, ",") + local eyear,emon,eday,ehour,emin,esec = string.match(image.exif_datetime_taken, "(%d-):(%d-):(%d-) (%d-):(%d-):(%d-)$") + local replacements = {image.film,image.path,df.get_filename(image.filename),string.upper(df.get_filetype(image.filename)),image.id,image.duplicate_index, + sequence,datetime.year,string.format("%02d", datetime.month),string.format("%02d", datetime.day),string.format("%02d", datetime.hour), + string.format("%02d", datetime.min),string.format("%02d", datetime.sec),eyear,emon,eday,ehour,emin,esec,image.rating,labels, + image.exif_maker,image.exif_model,image.title,image.creator,image.publisher,image.rights,username,pic_folder,home,desktop, + image.exif_iso,image.exif_exposure,image.exif_exposure_bias,image.exif_aperture,image.exif_focus_distance,image.exif_focal_length, + image.longitude,image.latitude,image.elevation,image.exif_lens,image.description,image.exif_crop} + + for i=1,#rename.placeholders,1 do rename.substitutes[rename.placeholders[i]] = replacements[i] end +end + +local function substitute_list(str) + -- replace the substitution variables in a string + for match in string.gmatch(str, "%$%(.-%)") do + local var = string.match(match, "%$%((.-)%)") + if rename.substitutes[var] then + str = string.gsub(str, "%$%("..var.."%)", rename.substitutes[var]) + else + dt.print_error(_("unrecognized variable " .. var)) + dt.print(_("unknown variable " .. var .. ", aborting...")) + return -1 + end + end + return str +end + +local function clear_substitute_list() + for i=1,#rename.placeholders,1 do rename.substitutes[rename.placeholders[i]] = nil end +end + +local function stop_job(job) + job.valid = false +end + +local function install_module() + if not rename.module_installed then + dt.register_lib( + MODULE_NAME, + _("rename images"), + true, + true, + {[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER",700}}, + dt.new_widget("box"){ + orientation = "vertical", + rename.widgets.pattern, + rename.widgets.button, + }, + nil, + nil + ) + rename.module_installed = true + end +end + +local function destroy() + dt.gui.libs[MODULE_NAME].visible = false +end + +local function restart() + dt.gui.libs[MODULE_NAME].visible = true +end + +-- - - - - - - - - - - - - - - - - - - - - - - - +-- M A I N +-- - - - - - - - - - - - - - - - - - - - - - - - + +local function do_rename(images) + if #images > 0 then + local pattern = rename.widgets.pattern.text + dt.preferences.write(MODULE_NAME, "pattern", "string", pattern) + dt.print_log(_("pattern is " .. pattern)) + if string.len(pattern) > 0 then + local datetime = os.date("*t") + + local job = dt.gui.create_job(_("renaming images"), true, stop_job) + for i, image in ipairs(images) do + if job.valid then + job.percent = i / #images + build_substitution_list(image, i, datetime, USER, PICTURES, HOME, DESKTOP) + local new_name = substitute_list(pattern) + if new_name == -1 then + dt.print(_("unable to do variable substitution, exiting...")) + stop_job(job) + return + end + clear_substitute_list() + local args = {} + local path = string.sub(df.get_path(new_name), 1, -2) + if string.len(path) == 0 then + path = image.path + end + local filename = df.get_filename(new_name) + local filmname = image.path + if path ~= image.path then + if not df.check_if_file_exists(df.sanitize_filename(path)) then + df.mkdir(df.sanitize_filename(path)) + end + filmname = path + end + args[1] = dt.films.new(filmname) + args[2] = image + if filename ~= image.filename then + args[3] = filename + end + dt.database.move_image(table.unpack(args)) + end + end + stop_job(job) + local collect_rules = dt.gui.libs.collect.filter() + dt.gui.libs.collect.filter(collect_rules) + dt.print(_("renamed " .. #images .. " images")) + else -- pattern length + dt.print_error("no pattern supplied, returning...") + dt.print(_("please enter the new name or pattern")) + end + else -- image count + dt.print_error("no images selected, returning...") + dt.print(_("please select some images and try again")) + end +end + +local function reset_callback() + rename.widgets.pattern.text = "" +end + +-- - - - - - - - - - - - - - - - - - - - - - - - +-- W I D G E T S +-- - - - - - - - - - - - - - - - - - - - - - - - + +rename.widgets.pattern = dt.new_widget("entry"){ + tooltip = _("$(ROLL_NAME) - film roll name\n") .. + _("$(FILE_FOLDER) - image file folder\n") .. + _("$(FILE_NAME) - image file name\n") .. + _("$(FILE_EXTENSION) - image file extension\n") .. + _("$(ID) - image id\n") .. + _("$(VERSION) - version number\n") .. + _("$(SEQUENCE) - sequence number of selection\n") .. + _("$(YEAR) - current year\n") .. + _("$(MONTH) - current month\n") .. + _("$(DAY) - current day\n") .. + _("$(HOUR) - current hour\n") .. + _("$(MINUTE) - current minute\n") .. + _("$(SECOND) - current second\n") .. + _("$(EXIF_YEAR) - EXIF year\n") .. + _("$(EXIF_MONTH) - EXIF month\n") .. + _("$(EXIF_DAY) - EXIF day\n") .. + _("$(EXIF_HOUR) - EXIF hour\n") .. + _("$(EXIF_MINUTE) - EXIF minute\n") .. + _("$(EXIF_SECOND) - EXIF seconds\n") .. + _("$(EXIF_ISO) - EXIF ISO\n") .. + _("$(EXIF_EXPOSURE) - EXIF exposure\n") .. + _("$(EXIF_EXPOSURE_BIAS) - EXIF exposure bias\n") .. + _("$(EXIF_APERTURE) - EXIF aperture\n") .. + _("$(EXIF_FOCAL_LENGTH) - EXIF focal length\n") .. + _("$(EXIF_FOCUS_DISTANCE) - EXIF focus distance\n") .. + _("$(EXIF_CROP) - EXIF crop\n") .. + _("$(LONGITUDE) - longitude\n") .. + _("$(LATITUDE) - latitude\n") .. + _("$(ELEVATION) - elevation\n") .. + _("$(STARS) - star rating\n") .. + _("$(LABELS) - color labels\n") .. + _("$(MAKER) - camera maker\n") .. + _("$(MODEL) - camera model\n") .. + _("$(LENS) - lens\n") .. + _("$(TITLE) - title from metadata\n") .. + _("$(DESCRIPTION) - description from metadata\n") .. + _("$(CREATOR) - creator from metadata\n") .. + _("$(PUBLISHER) - publisher from metadata\n") .. + _("$(RIGHTS) - rights from metadata\n") .. + _("$(USERNAME) - username\n") .. + _("$(PICTURES_FOLDER) - pictures folder\n") .. + _("$(HOME) - user's home directory\n") .. + _("$(DESKTOP) - desktop directory"), + placeholder = _("enter pattern $(FILE_FOLDER)/$(FILE_NAME)"), + text = "" +} + +local pattern_pref = dt.preferences.read(MODULE_NAME, "pattern", "string") +if pattern_pref then + rename.widgets.pattern.text = pattern_pref +end + +rename.widgets.button = dt.new_widget("button"){ + label = _("rename"), + clicked_callback = function(this) + do_rename(dt.gui.action_images) + end +} + +if dt.gui.current_view().id == "lighttable" then + install_module() +else + if not rename.event_registered then + dt.register_event( + "rename_images", "view-changed", + function(event, old_view, new_view) + if new_view.name == "lighttable" and old_view.name == "darkroom" then + install_module() + end + end + ) + rename.event_registered = true + end +end + +script_data.destroy = destroy +script_data.restart = restart +script_data.destroy_method = "hide" +script_data.show = restart + +return script_data