Skip to content

Commit b254577

Browse files
committed
Merge branch 'master' of github.com:chrisaga/lua-scripts
2 parents 63763be + 3d50d0f commit b254577

File tree

5 files changed

+767
-4
lines changed

5 files changed

+767
-4
lines changed

ChangeLog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
## Changes from most recent to oldest
2+
**31 Aug 2021 - wpferguson - remove styles hiding from AutoGrouper.lua**
23
**02 Jul 2021 - wpferguson - merged API-7.0.0-dev branch to master**
34
* API-7.0.0 is darktable 3.6
45
* breaking changes

contrib/AutoGrouper.lua

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,6 @@ local du = require "lib/dtutils"
4141

4242
du.check_min_api_version("7.0.0", "AutoGrouper")
4343

44-
dt.print_log("hiding styles")
45-
dt.gui.libs["styles"].visible = false
46-
4744
local MOD = 'autogrouper'
4845

4946
-- return data structure for script_manager
@@ -218,4 +215,4 @@ script_data.destroy_method = "hide"
218215
script_data.restart = restart
219216
script_data.show = restart
220217

221-
return script_data
218+
return script_data

contrib/color_profile_manager.lua

Lines changed: 372 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,372 @@
1+
--[[
2+
3+
color_profile_manager.lua - manage external darktable color profiles
4+
5+
Copyright (C) 2021 Bill Ferguson <[email protected]>.
6+
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.
11+
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.
16+
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+
]]
20+
--[[
21+
color_profile_manager - manage external darktable color profiles
22+
23+
This script provides a tool to manage input and output external color
24+
profiles used by darktable. Color profiles can be added or removed
25+
to/from the correct directories so that darktable can find and use
26+
them.
27+
28+
ADDITIONAL SOFTWARE NEEDED FOR THIS SCRIPT
29+
* None
30+
31+
USAGE
32+
* require this script from your main lua file
33+
* select the input or output set of color profiles
34+
* a list of profiles is displayed. Click the check box beside the
35+
profile name to select it for removal. Click the "remove profile"
36+
button to remove the profile.
37+
* use the file selector to select a color profile to add to the currently
38+
selected set (input or output)
39+
* click the "add profile" button to add the profile to the selected set
40+
41+
BUGS, COMMENTS, SUGGESTIONS
42+
* Send to Bill Ferguson, [email protected] or raise an issue on
43+
https://github.com/dakrtable-org/lua-scripts
44+
]]
45+
local dt = require "darktable"
46+
local du = require "lib/dtutils"
47+
local df = require "lib/dtutils.file"
48+
49+
du.check_min_api_version("7.0.0", "color_profile_manager")
50+
51+
-- - - - - - - - - - - - - - - - - - - - - - - -
52+
-- L O C A L I Z A T I O N
53+
-- - - - - - - - - - - - - - - - - - - - - - - -
54+
55+
local gettext = dt.gettext
56+
57+
-- Tell gettext where to find the .mo file translating messages for a particular domain
58+
gettext.bindtextdomain("color_profile_manager", dt.configuration.config_dir .. "/lua/locale/")
59+
60+
local function _(msgid)
61+
return gettext.dgettext("color_profile_manager", msgid)
62+
end
63+
64+
-- - - - - - - - - - - - - - - - - - - - - - - -
65+
-- C O N S T A N T S
66+
-- - - - - - - - - - - - - - - - - - - - - - - -
67+
68+
local MODULE_NAME = "color_profile_manager"
69+
local PS = dt.configuration.running_os == "windows" and "\\" or "/"
70+
local CS = dt.configuration.running_os == "windows" and "&" or ";"
71+
local DIR_CMD = dt.configuration.running_os == "windows" and "dir /b" or "ls"
72+
local COLOR_IN_DIR = dt.configuration.config_dir .. PS .. "color" .. PS .. "in"
73+
local COLOR_OUT_DIR = dt.configuration.config_dir .. PS .. "color" .. PS .. "out"
74+
75+
-- - - - - - - - - - - - - - - - - - - - - - - -
76+
-- N A M E S P A C E
77+
-- - - - - - - - - - - - - - - - - - - - - - - -
78+
79+
local cpm = {}
80+
cpm.widgets = {}
81+
cpm.widgets.profile_box = dt.new_widget("box"){
82+
orientation = "vertical",
83+
}
84+
cpm.module_installed = false
85+
cpm.event_registered = false
86+
-- - - - - - - - - - - - - - - - - - - - - - - -
87+
-- F U N C T I O N S
88+
-- - - - - - - - - - - - - - - - - - - - - - - -
89+
90+
local function check_for_directories()
91+
if not df.test_file(COLOR_IN_DIR, "d") then
92+
dt.print_log("didn't find " .. COLOR_IN_DIR)
93+
return false
94+
elseif not df.test_file(COLOR_OUT_DIR, "d") then
95+
dt.print_log("didn't find " .. COLOR_OUT_DIR)
96+
return false
97+
else
98+
dt.print_log("both directories exist")
99+
return true
100+
end
101+
end
102+
103+
local function add_directories()
104+
df.mkdir(COLOR_IN_DIR)
105+
df.mkdir(COLOR_OUT_DIR)
106+
end
107+
108+
local function list_profiles(dir)
109+
local files = {}
110+
local p = io.popen(DIR_CMD .. " " .. dir)
111+
if p then
112+
for line in p:lines() do
113+
table.insert(files, line)
114+
end
115+
end
116+
p:close()
117+
return files
118+
end
119+
120+
local function add_profile(file, dir)
121+
df.file_copy(file, dir)
122+
dt.print(_("added color profile " .. file .. " to " .. dir))
123+
dt.print_log("color profile " .. file .. " added to " .. dir)
124+
end
125+
126+
local function remove_profile(file, dir)
127+
os.remove(dir .. PS .. file)
128+
dt.print(_("removed color profile " .. file .. " from " .. dir))
129+
dt.print_log("color profile " .. file .. " removed from " .. dir)
130+
end
131+
132+
local function clear_profile_box()
133+
for i = #cpm.widgets.profile_box, 1, -1 do
134+
cpm.widgets.profile_box[i] = nil
135+
end
136+
end
137+
138+
local function add_profile_callback()
139+
local profile_dir = COLOR_IN_DIR
140+
if cpm.widgets.profile_set.selected == 2 then
141+
profile_dir = COLOR_OUT_DIR
142+
end
143+
144+
local new_profile = cpm.widgets.profile_selector.value
145+
if string.lower(df.get_filetype(new_profile)) ~= "icm" and string.lower(df.get_filetype(new_profile)) ~= "icc" then
146+
dt.print(_("ERROR: color profile must be an icc or icm file"))
147+
dt.print_error(new_profile .. " selected and isn't an icc or icm file")
148+
return
149+
end
150+
151+
-- set selector value to directory that new profile came from
152+
-- in case there are more
153+
cpm.widgets.profile_selector.value = df.get_path(cpm.widgets.profile_selector.value)
154+
add_profile(new_profile, profile_dir)
155+
local files = list_profiles(profile_dir)
156+
local widgets = {}
157+
158+
local profile_ptr = 1
159+
for i, file in ipairs(files) do
160+
if #cpm.widgets.profile_box == 0 or cpm.widgets.profile_box[profile_ptr].label ~= file then
161+
table.insert(widgets, dt.new_widget("check_button"){value = false, label = file})
162+
else
163+
table.insert(widgets, cpm.widgets.profile_box[profile_ptr])
164+
profile_ptr = profile_ptr + 1
165+
if profile_ptr > #cpm.widgets.profile_box then
166+
profile_ptr = #cpm.widgets.profile_box
167+
end
168+
end
169+
end
170+
clear_profile_box()
171+
for _, widget in ipairs(widgets) do
172+
table.insert(cpm.widgets.profile_box, widget)
173+
end
174+
if not cpm.widgets.remove_box.visible then
175+
cpm.widgets.remove_box.visible = true
176+
end
177+
end
178+
179+
local function remove_profile_callback()
180+
local widgets_to_keep = {}
181+
local profile_dir = COLOR_IN_DIR
182+
if cpm.widgets.profile_set.selected == 2 then
183+
profile_dir = COLOR_OUT_DIR
184+
end
185+
186+
for _, widget in ipairs(cpm.widgets.profile_box) do
187+
if widget.value == true then
188+
remove_profile(widget.label, profile_dir)
189+
else
190+
table.insert(widgets_to_keep, widget)
191+
end
192+
end
193+
clear_profile_box()
194+
for _, widget in ipairs(widgets_to_keep) do
195+
table.insert(cpm.widgets.profile_box, widget)
196+
end
197+
if #cpm.widgets.profile_box == 0 then
198+
cpm.widgets.remove_box.visible = false
199+
else
200+
cpm.widgets.remove_box.visible = true
201+
end
202+
end
203+
204+
local function list_profile_callback(choice)
205+
local list_dir = COLOR_IN_DIR
206+
if choice == 2 then
207+
list_dir = COLOR_OUT_DIR
208+
end
209+
210+
local files = list_profiles(list_dir)
211+
212+
if #files == 0 then
213+
cpm.widgets.remove_box.visible = false
214+
else
215+
cpm.widgets.remove_box.visible = true
216+
end
217+
218+
clear_profile_box()
219+
220+
for i, file in ipairs(files) do
221+
cpm.widgets.profile_box[i] = dt.new_widget("check_button"){value = false, label = file}
222+
end
223+
end
224+
225+
local function install_module()
226+
if not cpm.module_installed then
227+
dt.register_lib(
228+
MODULE_NAME, -- Module name
229+
_("color profile manager"), -- Visible name
230+
true, -- expandable
231+
false, -- resetable
232+
{[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_LEFT_CENTER", 0}}, -- containers
233+
cpm.widgets.main_widget,
234+
nil,-- view_enter
235+
nil -- view_leave
236+
)
237+
cpm.module_installed = true
238+
dt.control.sleep(500)
239+
if not cpm.initialized then
240+
cpm.widgets.profile_set.visible = false
241+
cpm.widgets.add_box.visible = false
242+
cpm.widgets.remove_box.visible = false
243+
else
244+
cpm.widgets.profile_set.selected = 1
245+
end
246+
end
247+
end
248+
249+
local function destroy()
250+
dt.gui.libs[MODULE_NAME].visible = false
251+
return
252+
end
253+
254+
local function restart()
255+
dt.gui.libs[MODULE_NAME].visible = true
256+
return
257+
end
258+
-- - - - - - - - - - - - - - - - - - - - - - - -
259+
-- W I D G E T S
260+
-- - - - - - - - - - - - - - - - - - - - - - - -
261+
262+
cpm.initialized = check_for_directories()
263+
dt.print_log("cpm.initialized is " .. tostring(cpm.initialized))
264+
265+
if not cpm.initialized then
266+
dt.print_log("creating init_box")
267+
cpm.widgets.init_box = dt.new_widget("box"){
268+
orientation = "vertical",
269+
dt.new_widget("button"){
270+
label = _("initialize color profiles"),
271+
tooltip = _("create the directory structure to contain the color profiles"),
272+
clicked_callback = function(this)
273+
add_directories()
274+
cpm.initialized = true
275+
cpm.widgets.profile_set.visible = true
276+
cpm.widgets.add_box.visible = true
277+
cpm.widgets.remove_box.visible = false
278+
cpm.widgets.init_box.visible = false
279+
cpm.widgets.profile_set.selected = 1
280+
end
281+
}
282+
}
283+
end
284+
285+
cpm.widgets.profile_set = dt.new_widget("combobox"){
286+
label = _("select profile set"),
287+
tooltip = _("select input or output profiles"),
288+
visible = cpm.initialized and false or true,
289+
changed_callback = function(this)
290+
if cpm.initialized then
291+
list_profile_callback(this.selected)
292+
end
293+
end,
294+
_("input"), _("output"),
295+
}
296+
297+
cpm.widgets.profile_selector = dt.new_widget("file_chooser_button"){
298+
title = _("select color profile to add"),
299+
tooltip = _("select the .icc or .icm file to add"),
300+
is_directory = false
301+
}
302+
303+
cpm.widgets.add_box = dt.new_widget("box"){
304+
orientation = "vertical",
305+
visible = cpm.initialized and true or false,
306+
dt.new_widget("section_label"){label = _("add profile")},
307+
cpm.widgets.profile_selector,
308+
dt.new_widget("button"){
309+
label = _("add selected color profile"),
310+
tooltip = _("add selected file to profiles"),
311+
clicked_callback = function(this)
312+
add_profile_callback()
313+
end
314+
}
315+
}
316+
317+
cpm.widgets.remove_box = dt.new_widget("box"){
318+
orientation = "vertical",
319+
visible = cpm.initialized and true or false,
320+
dt.new_widget("section_label"){label = _("remove profile")},
321+
cpm.widgets.profile_box,
322+
dt.new_widget("button"){
323+
label = _("remove selected profile(s)"),
324+
tooltip = _("remove the checked profile(s)"),
325+
clicked_callback = function(this)
326+
remove_profile_callback()
327+
end
328+
}
329+
}
330+
331+
local main_widgets = {}
332+
333+
if not cpm.initialized then
334+
table.insert(main_widgets, cpm.widgets.init_box)
335+
end
336+
table.insert(main_widgets, cpm.widgets.profile_set)
337+
table.insert(main_widgets, cpm.widgets.remove_box)
338+
table.insert(main_widgets, cpm.widgets.add_box)
339+
340+
cpm.widgets.main_widget = dt.new_widget("box"){
341+
orientation = "vertical",
342+
table.unpack(main_widgets)
343+
}
344+
345+
-- - - - - - - - - - - - - - - - - - - - - - - -
346+
-- M A I N
347+
-- - - - - - - - - - - - - - - - - - - - - - - -
348+
349+
if dt.gui.current_view().id == "lighttable" then
350+
install_module()
351+
else
352+
if not cpm.event_registered then
353+
dt.register_event(
354+
MODULE_NAME, "view-changed",
355+
function(event, old_view, new_view)
356+
if new_view.name == "lighttable" and old_view.name == "darkroom" then
357+
install_module()
358+
end
359+
end
360+
)
361+
cpm.event_registered = true
362+
end
363+
end
364+
365+
local script_data = {}
366+
367+
script_data.destroy = destroy
368+
script_data.restart = restart
369+
script_data.destroy_method = "hide"
370+
script_data.show = restart
371+
372+
return script_data

0 commit comments

Comments
 (0)