Skip to content

Commit a5961eb

Browse files
committed
contrib/change_group_leader.lua - adds a shortcut to cycle through
the images in a group making the next on the new group leader. When the end of the group is reached the first image in the group is selected.
1 parent 025f429 commit a5961eb

File tree

1 file changed

+109
-152
lines changed

1 file changed

+109
-152
lines changed

contrib/change_group_leader.lua

Lines changed: 109 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -1,201 +1,158 @@
11
--[[
2-
change group leader
32
4-
copyright (c) 2020, 2022 Bill Ferguson <[email protected]>
5-
copyright (c) 2021 Angel Angelov
3+
change_group_leader.lua - change image grouip leader
64
7-
darktable is free software: you can redistribute it and/or modify
8-
it under the terms of the GNU General Public License as published by
9-
the Free Software Foundation, either version 3 of the License, or
10-
(at your option) any later version.
5+
Copyright (C) 2024 Bill Ferguson <[email protected]>
116
12-
darktable is distributed in the hope that it will be useful,
13-
but WITHOUT ANY WARRANTY; without even the implied warranty of
14-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15-
GNU General Public License for more details.
7+
This program is free software: you can redistribute it and/or modify
8+
it under the terms of the GNU General Public License as published by
9+
the Free Software Foundation; either version 3 of the License, or
10+
(at your option) any later version.
1611
17-
You should have received a copy of the GNU General Public License
18-
along with darktable. If not, see <http://www.gnu.org/licenses/>.
19-
]]
12+
This program is distributed in the hope that it will be useful,
13+
but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
GNU General Public License for more details.
2016
17+
You should have received a copy of the GNU General Public License
18+
along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
]]
2120
--[[
22-
CHANGE GROUP LEADER
23-
automatically change the leader of raw+jpg paired image groups
24-
25-
INSTALLATION
26-
* copy this file in $CONFIGDIR/lua/ where CONFIGDIR is your darktable configuration directory
27-
* add the following line in the file $CONFIGDIR/luarc
28-
require "change_group_leader"
29-
30-
USAGE
31-
* in lighttable mode, select the image groups you wish to process,
32-
select whether you want to set the leader to "jpg" or "raw",
33-
and click "Execute"
21+
change_group_leader - change image grouip leader
22+
23+
change_group_leader changes the group leader to the next
24+
image in the group. If the end of the group is reached
25+
then the next image is wrapped around to the first image.
26+
27+
ADDITIONAL SOFTWARE NEEDED FOR THIS SCRIPT
28+
None
29+
30+
USAGE
31+
* enable with script_manager
32+
* assign a key to the shortcut
33+
34+
BUGS, COMMENTS, SUGGESTIONS
35+
Bill Ferguson <[email protected]>
36+
37+
CHANGES
3438
]]
3539

3640
local dt = require "darktable"
3741
local du = require "lib/dtutils"
42+
local df = require "lib/dtutils.file"
3843

39-
local gettext = dt.gettext
44+
-- - - - - - - - - - - - - - - - - - - - - - - -
45+
-- C O N S T A N T S
46+
-- - - - - - - - - - - - - - - - - - - - - - - -
4047

4148
local MODULE = "change_group_leader"
4249

43-
du.check_min_api_version("3.0.0", MODULE)
50+
-- - - - - - - - - - - - - - - - - - - - - - - -
51+
-- A P I C H E C K
52+
-- - - - - - - - - - - - - - - - - - - - - - - -
53+
54+
du.check_min_api_version("7.0.0", MODULE)
4455

45-
-- return data structure for script_manager
56+
57+
-- - - - - - - - - - - - - - - - - - - - - - - - - -
58+
-- S C R I P T M A N A G E R I N T E G R A T I O N
59+
-- - - - - - - - - - - - - - - - - - - - - - - - - -
4660

4761
local script_data = {}
4862

4963
script_data.destroy = nil -- function to destory the script
50-
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet, otherwise leave as nil
64+
script_data.destroy_method = nil -- set to hide for libs since we can't destroy them commpletely yet
5165
script_data.restart = nil -- how to restart the (lib) script after it's been hidden - i.e. make it visible again
5266
script_data.show = nil -- only required for libs since the destroy_method only hides them
5367

68+
-- - - - - - - - - - - - - - - - - - - - - - - - - -
69+
-- I 1 8 N
70+
-- - - - - - - - - - - - - - - - - - - - - - - - - -
71+
72+
local gettext = dt.gettext
73+
5474
-- Tell gettext where to find the .mo file translating messages for a particular domain
55-
gettext.bindtextdomain(MODULE, dt.configuration.config_dir.."/lua/locale/")
75+
gettext.bindtextdomain(MODULE, dt.configuration.config_dir .. "/lua/locale/")
5676

5777
local function _(msgid)
5878
return gettext.dgettext(MODULE, msgid)
5979
end
6080

61-
-- create a namespace to contain persistent data and widgets
62-
chg_grp_ldr = {}
63-
64-
local cgl = chg_grp_ldr
65-
66-
cgl.widgets = {}
81+
-- - - - - - - - - - - - - - - - - - - - - - - -
82+
-- F U N C T I O N S
83+
-- - - - - - - - - - - - - - - - - - - - - - - -
6784

68-
cgl.event_registered = false
69-
cgl.module_installed = false
85+
local function toggle_global_toolbox_grouping()
86+
dt.gui.libs.global_toolbox.grouping = false
87+
dt.gui.libs.global_toolbox.grouping = true
88+
end
7089

71-
-- - - - - - - - - - - - - - - - - - - - - - - -
72-
-- F U N C T I O N S
73-
-- - - - - - - - - - - - - - - - - - - - - - - -
74-
75-
local function install_module()
76-
if not cgl.module_installed then
77-
dt.register_lib(
78-
MODULE, -- Module name
79-
_("change_group_leader"), -- Visible name
80-
true, -- expandable
81-
false, -- resetable
82-
{[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_RIGHT_CENTER", 700}}, -- containers
83-
cgl.widgets.box,
84-
nil,-- view_enter
85-
nil -- view_leave
86-
)
87-
cgl.module_installed = true
88-
end
90+
local function hinter_msg(msg)
91+
dt.print_hinter(msg)
92+
dt.control.sleep(1500)
93+
dt.print_hinter(" ")
8994
end
9095

91-
local function find_group_leader(images, mode)
92-
for _, img in ipairs(images) do
93-
dt.print_log("checking image " .. img.id .. " named " .. img.filename)
94-
local found = false
95-
if mode == "jpg" then
96-
if string.match(string.lower(img.filename), "jpg$") then
97-
dt.print_log("jpg matched image " .. img.filename)
98-
found = true
99-
end
100-
elseif mode == "raw" then
101-
if img.is_raw and img.duplicate_index == 0 then
102-
dt.print_log("found raw " .. img.filename)
103-
found = true
104-
end
105-
elseif mode == "non-raw" then
106-
if img.is_ldr then
107-
dt.print_log("found ldr " .. img.filename)
108-
found = true
96+
-- - - - - - - - - - - - - - - - - - - - - - - -
97+
-- M A I N P R O G R A M
98+
-- - - - - - - - - - - - - - - - - - - - - - - -
99+
100+
local function change_group_leader(image)
101+
local group_images = image:get_group_members()
102+
if #group_images < 2 then
103+
hinter_msg(_("No images to change to in group"))
104+
return
105+
else
106+
local position = nil
107+
for i, img in ipairs(group_images) do
108+
if image == img then
109+
position = i
109110
end
110-
else
111-
dt.print_error(MODULE .. ": unrecognized mode " .. mode)
112-
return
113111
end
114-
if found then
115-
dt.print_log("making " .. img.filename .. " group leader")
116-
img:make_group_leader()
117-
return
112+
113+
if position == #group_images then
114+
position = 1
115+
else
116+
position = position + 1
118117
end
119-
end
120-
end
121118

122-
local function process_image_groups(images)
123-
if #images < 1 then
124-
dt.print(_("No images selected."))
125-
dt.print_log(MODULE .. "no images seletected, returning...")
126-
else
127-
local mode = cgl.widgets.mode.value
128-
for _,img in ipairs(images) do
129-
dt.print_log("checking image " .. img.id)
130-
local group_images = img:get_group_members()
131-
if group_images == 1 then
132-
dt.print_log("only one image in group for image " .. image.id)
133-
else
134-
find_group_leader(group_images, mode)
135-
end
119+
new_leader = group_images[position]
120+
new_leader:make_group_leader()
121+
dt.gui.selection({new_leader})
122+
123+
if dt.gui.libs.global_toolbox.grouping then
124+
-- toggle the grouping to make the new leader show
125+
toggle_global_toolbox_grouping()
136126
end
137127
end
138128
end
139129

140-
-- - - - - - - - - - - - - - - - - - - - - - - -
141-
-- S C R I P T M A N A G E R I N T E G R A T I O N
142-
-- - - - - - - - - - - - - - - - - - - - - - - -
130+
-- - - - - - - - - - - - - - - - - - - - - - - -
131+
-- D A R K T A B L E I N T E G R A T I O N
132+
-- - - - - - - - - - - - - - - - - - - - - - - -
143133

144134
local function destroy()
145-
dt.gui.libs[MODULE].visible = false
135+
-- put things to destroy (events, storages, etc) here
136+
dt.destroy_event(MODULE, "shortcut")
146137
end
147138

148-
local function restart()
149-
dt.gui.libs[MODULE].visible = true
150-
end
139+
script_data.destroy = destroy
151140

152-
-- - - - - - - - - - - - - - - - - - - - - - - -
153-
-- W I D G E T S
154-
-- - - - - - - - - - - - - - - - - - - - - - - -
155-
156-
cgl.widgets.mode = dt.new_widget("combobox"){
157-
label = _("select new group leader"),
158-
tooltip = _("select type of image to be group leader"),
159-
selected = 1,
160-
"jpg", "raw", "non-raw",
161-
}
162-
163-
cgl.widgets.execute = dt.new_widget("button"){
164-
label = _("Execute"),
165-
clicked_callback = function()
166-
process_image_groups(dt.gui.action_images)
167-
end
168-
}
169-
170-
cgl.widgets.box = dt.new_widget("box"){
171-
orientation = "vertical",
172-
cgl.widgets.mode,
173-
cgl.widgets.execute,
174-
}
175-
176-
-- - - - - - - - - - - - - - - - - - - - - - - -
177-
-- D A R K T A B L E I N T E G R A T I O N
178-
-- - - - - - - - - - - - - - - - - - - - - - - -
179-
180-
if dt.gui.current_view().id == "lighttable" then
181-
install_module()
182-
else
183-
if not cgl.event_registered then
184-
dt.register_event(
185-
"view-changed",
186-
function(event, old_view, new_view)
187-
if new_view.name == "lighttable" and old_view.name == "darkroom" then
188-
install_module()
189-
end
190-
end
191-
)
192-
cgl.event_registered = true
193-
end
194-
end
141+
-- - - - - - - - - - - - - - - - - - - - - - - -
142+
-- E V E N T S
143+
-- - - - - - - - - - - - - - - - - - - - - - - -
195144

196-
script_data.destroy = destroy
197-
script_data.restart = restart
198-
script_data.destroy_method = "hide"
199-
script_data.show = restart
145+
dt.register_event(MODULE, "shortcut",
146+
function(event, shortcut)
147+
-- ignore the film roll, it contains all the images, not just the imported
148+
local images = dt.gui.selection()
149+
if #images < 1 then
150+
dt.print(_("No image selected. Please select an image and try again"))
151+
else
152+
change_group_leader(images[1])
153+
end
154+
end,
155+
_("Change group leader")
156+
)
200157

201158
return script_data

0 commit comments

Comments
 (0)