You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

174 lines
5.5 KiB
Lua

-- Fork of the autogroup plugin but only comparing pictures with the same timestamp
local dt = require "darktable"
local du = require "lib/dtutils"
local df = require "lib/dtutils.file"
du.check_min_api_version("7.0.0", "AutoGroupInstant")
local MOD = 'autogroupinstant'
-- return data structure for script_manager
local script_data = {}
script_data.destroy = nil -- function to destory the script
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
script_data.show = nil -- only required for libs since the destroy_method only hides them
local gettext = dt.gettext
-- Tell gettext where to find the .mo file translating messages for a particular domain
gettext.bindtextdomain("AutoGroupInstant",dt.configuration.config_dir.."/lua/locale/")
local function _(msgid)
return gettext.dgettext("AutoGroupInstant", msgid)
end
local Ag = {}
Ag.module_installed = false
Ag.event_registered = false
local GUI = {
gap = {},
selected = {},
collection = {}
}
local function InRange(test, low, high) --tests if test value is within range of low and high (inclusive)
if test >= low and test <= high then
return true
else
return false
end
end
local function CompTime(first, second) --compares the timestamps and returns true if first was taken before second
first_time = first.exif_datetime_taken
if string.match(first_time, '[0-9]') == nil then first_time = '9999:99:99 99:99:99' end
first_time = tonumber(string.gsub(first_time, '[^0-9]*',''))
second_time = second.exif_datetime_taken
if string.match(second_time, '[0-9]') == nil then second_time = '9999:99:99 99:99:99' end
second_time = tonumber(string.gsub(second_time, '[^0-9]*',''))
return first_time < second_time
end
local function SeperateTime(str) --seperates the timestamp into individual components for used with OS.time operations
local cleaned = string.gsub(str, '[^%d]',':')
cleaned = string.gsub(cleaned, '::*',':') --YYYY:MM:DD:hh:mm:ss
local year = string.sub(cleaned,1,4)
local month = string.sub(cleaned,6,7)
local day = string.sub(cleaned,9,10)
local hour = string.sub(cleaned,12,13)
local min = string.sub(cleaned,15,16)
local sec = string.sub(cleaned,18,19)
return {year = year, month = month, day = day, hour = hour, min = min, sec = sec}
end
local function GetTimeDiff(curr_image, prev_image) --returns the time difference (in sec.) from current image and the previous image
local curr_time = SeperateTime(curr_image.exif_datetime_taken)
local prev_time = SeperateTime(prev_image.exif_datetime_taken)
return os.time(curr_time)-os.time(prev_time)
end
local function main(on_collection)
local images = {}
if on_collection then
local col_images = dt.collection
for i,image in ipairs(col_images) do --copy images to a standard table, table.sort barfs on type dt_lua_singleton_image_collection
table.insert(images,i,image)
end
else
images = dt.gui.selection()
end
if #images < 2 then
dt.print('please select at least 2 images')
return
end
table.sort(images, function(first, second) return CompTime(first,second) end) --sort images by timestamp
for i, image in ipairs(images) do
if i == 1 then
prev_image = image
elseif string.match(image.exif_datetime_taken, '[%d]') ~= nil then --make sure current image has a timestamp
local curr_image = image
if GetTimeDiff(curr_image, prev_image) == 0 then
images[i]:group_with(images[i-1])
for _, member in ipairs(images[i]:get_group_members()) do
local ext = string.lower(df.get_filetype(member.filename))
if ext == "rw2" or ext == "arw" then
member:make_group_leader()
end
end
end
prev_image = curr_image
end
end
end
local function install_module()
if not Ag.module_installed then
dt.print_log("installing module")
dt.register_lib(
MOD, -- Module name
_('Group identical Timestamps'), -- name
true, -- expandable
true, -- resetable
{[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 99}}, -- containers
dt.new_widget("box"){
orientation = "vertical",
GUI.selected,
GUI.collection
}
)
Ag.module_installed = true
dt.print_log("module installed")
dt.print_log("styles module visibility is " .. tostring(dt.gui.libs["styles"].visible))
end
end
local function destroy()
dt.gui.libs[MOD].visible = false
end
local function restart()
dt.gui.libs[MOD].visible = true
end
-- GUI --
GUI.selected = dt.new_widget("button"){
label = _('auto group: selected'),
tooltip =_('auto group selected images'),
clicked_callback = function() main(false) end
}
GUI.collection = dt.new_widget("button"){
label = _('auto group: collection'),
tooltip =_('auto group the entire collection'),
clicked_callback = function() main(true) end
}
if dt.gui.current_view().id == "lighttable" then
install_module()
else
if not Ag.event_registered then
dt.register_event(
"AutoGroupInstant", "view-changed",
function(event, old_view, new_view)
if new_view.name == "lighttable" and old_view.name == "darkroom" then
install_module()
end
end
)
Ag.event_registered = true
end
end
script_data.destroy = destroy
script_data.destroy_method = "hide"
script_data.restart = restart
script_data.show = restart
return script_data