Files
lua-scripts-w-api/tools/script_manager.lua
wpferguson 37b523f989 [script_manager] rewrite of script_manager for a better fit with
darktable 3.4 and the new scripts_installer. Changed
                 interface to paged instead of scrolled so that less
                 screen space is required.  Added capability to
                 install/update external repositories and seamlessly
                 integrate with script_manager.
2020-12-23 19:54:16 -05:00

895 lines
28 KiB
Lua

--[[
This file is part of darktable,
copyright (c) 2018, 2020 Bill Ferguson <wpferguson@gmail.com>
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/>.
]]
--[[
script_manager.lua - a tool for managing the darktable lua scripts
script_manager is designed to be called from the users luarc file and used to
manage the lua scripts.
On startup script_manager scans the lua scripts directory to see what scripts are present.
Scripts are sorted by 'category' based on what sub-directory they are in. With no
additional script repositories iinstalled, the categories are contrib, examples, official
and tools. When a category is selected the buttons show the script name and whether the
script is started or stopped. The button is a toggle, so if the script is stopped click
the button to start it and vice versa.
Features
* the number of script buttons shown can be changed to any number between 5 and 20. The
default is 10 buttons. This can be changed in the configuration action.
* additional repositories of scripts may be installed using from the install/update action.
* installed scripts can be updated from the install/update action. This includes extra
repositories that have been installed.
* the scripts can be disabled if desired from the install/update action. This can only
be reversed manually. To enable the "Disable Scripts" button, check the checkbox to
endable it. This is to prevent accidentally disabling the scripts. Click the
"Disable Scripts" button and the luarc file is renamed to luarc.disable. If at
a later time you want to enable the scripts again, simply rename the luarc.disabled
file to luarc and the scripts will run.
]]
local dt = require "darktable"
local du = require "lib/dtutils"
local df = require "lib/dtutils.file"
local ds = require "lib/dtutils.string"
local dtsys = require "lib/dtutils.system"
local log = require "lib/dtutils.log"
local gettext = dt.gettext
-- Tell gettext where to find the .mo file translating messages for a particular domain
gettext.bindtextdomain("script_manager",dt.configuration.config_dir.."/lua/locale/")
local function _(msgid)
return gettext.dgettext("script_manager", msgid)
end
-- api check
du.check_min_api_version("5.0.0", "script_manager")
-- - - - - - - - - - - - - - - - - - - - - - - -
-- C O N S T A N T S
-- - - - - - - - - - - - - - - - - - - - - - - -
-- path separator
local PS = dt.configuration.running_os == "windows" and "\\" or "/"
-- command separator
local CS = dt.configuration.running_os == "windows" and "&" or ";"
local MODULE = "script_manager"
local MIN_BUTTONS_PER_PAGE = 5
local MAX_BUTTONS_PER_PAGE = 20
local DEFAULT_BUTTONS_PER_PAGE = 10
local DEFAULT_LOG_LEVEL = log.error
local LUA_DIR = dt.configuration.config_dir .. PS .. "lua"
local LUA_SCRIPT_REPO = "https://github.com/darktable-org/lua-scripts.git"
local CURR_API_STRING = dt.configuration.api_version_string
-- - - - - - - - - - - - - - - - - - - - - - - -
-- L O G L E V E L
-- - - - - - - - - - - - - - - - - - - - - - - -
local old_log_level = log.log_level()
log.log_level(DEFAULT_LOG_LEVEL)
-- - - - - - - - - - - - - - - - - - - - - - - -
-- N A M E S P A C E
-- - - - - - - - - - - - - - - - - - - - - - - -
local script_manager = {}
local sm = script_manager
sm.executables = {}
sm.executables.git = df.check_if_bin_exists("git")
sm.module_installed = false
sm.event_registered = false
-- set up tables to contain all the widgets and choices
sm.widgets = {}
sm.categories = {}
sm.scripts = {}
sm.page_status = {}
sm.page_status.num_buttons = DEFAULT_BUTTONS_PER_PAGE
sm.page_status.buttons_created = 0
sm.page_status.current_page = 0
sm.page_status.category = ""
-- installed script repositories
sm.installed_repositories = {
{name = "lua-scripts", directory = LUA_DIR},
}
-- don't let it run until everything is in place
sm.run = false
-- - - - - - - - - - - - - - - - - - - - - - - -
-- F U N C T I O N S
-- - - - - - - - - - - - - - - - - - - - - - - -
local function pref_read(name, pref_type)
log.msg(log.debug, "name is " .. name .. " and type is " .. pref_type)
local val = dt.preferences.read(MODULE, name, pref_type)
if not string.match(pref_type, "bool") then
log.msg(log.debug, "read value " .. tostring(val))
end
return val
end
local function pref_write(name, pref_type, value)
dt.preferences.write(MODULE, name, pref_type, value)
end
local function update_combobox_choices(combobox, choice_table, selected)
local items = #combobox
local choices = #choice_table
for i, name in ipairs(choice_table) do
combobox[i] = name
end
if choices < items then
for j = items, choices + 1, -1 do
combobox[j] = nil
end
end
if not selected then
selected = 1
end
combobox.value = selected
end
local function add_script_category(category)
if #sm.categories == 0 or not string.match(du.join(sm.categories, " "), ds.sanitize_lua(category)) then
table.insert(sm.categories, category)
sm.scripts[category] = {}
log.msg(log.debug, "created category " .. category)
end
end
local function get_script_doc(script)
local description = nil
f = io.open(LUA_DIR .. PS .. script .. ".lua")
if f then
-- slurp the file
local content = f:read("*all")
f:close()
-- assume that the second block comment is the documentation
description = string.match(content, "%-%-%[%[.-%]%].-%-%-%[%[(.-)%]%]")
else
log.msg(log.error, _("Cant read from " .. script))
end
if description then
return description
else
return "No documentation available"
end
end
local function activate(script)
log.msg(log.info, "activating " .. script.name)
local status, err = du.prequire(script.path)
if status then
pref_write(script.script_name, "bool", true)
log.msg(log.screen, _("Loaded ") .. script.script_name)
script.running = true
else
log.msg(log.screen, script.script_name .. _(" failed to load"))
log.msg(log.error, "Error loading " .. script.script_name)
log.msg(log.error, "Error message: " .. err)
end
return status
end
local function deactivate(script)
-- presently the lua api doesn't support unloading gui elements therefore
-- we just mark then inactive for the next time darktable starts
-- deactivate it....
pref_write(script.script_name, "bool", false)
script.running = false
log.msg(log.info, "setting " .. script.script_name .. " to not start")
log.msg(log.screen, script.name .. _(" will not start when darktable is restarted"))
end
local function add_script_name(name, path, category)
log.msg(log.debug, "category is " .. category)
log.msg(log.debug, "name is " .. name)
local script = {
name = name,
path = category .. "/" .. path .. name,
running = false,
doc = get_script_doc(category .. "/" .. path .. name),
script_name = category .. "/" .. name
}
table.insert(sm.scripts[category], script)
if pref_read(script.script_name, "bool") then
activate(script)
end
end
local function process_script_data(script_file)
-- the script file supplied is category/filename.filetype
-- the following pattern splits the string into category, path, name, fileename, and filetype
-- for example contrib/gimp.lua becomes
-- category - contrib
-- path -
-- name - gimp.lua
-- filename - gimp
-- filetype - lua
-- Thanks Tobias Jakobs for the awesome regulary expression
local pattern = "(.-)/(.-)(([^\\/]-)%.?([^%.\\/]*))$"
if dt.configuration.running_os == "windows" then
-- change the path separator from / to \ for windows
pattern = "(.-)\\(.-)(([^\\]-)%.?([^%.\\]*))$"
end
log.msg(log.info, "processing " .. script_file)
-- add the script data
local category,path,name,filename,filetype = string.match(script_file, pattern)
log.msg(log.debug, "category is " .. category)
log.msg(log.debug, "name is " .. name)
add_script_category(category)
if name then
add_script_name(name, path, category)
end
end
local function scan_scripts(script_dir)
local script_count = 0
local find_cmd = "find -L " .. script_dir .. " -name \\*.lua -print | sort"
if dt.configuration.running_os == "windows" then
find_cmd = "dir /b/s " .. script_dir .. "\\*.lua | sort"
end
log.msg(log.debug, _("find command is ") .. find_cmd)
-- scan the scripts
local output = io.popen(find_cmd)
for line in output:lines() do
local l = string.gsub(line, ds.sanitize_lua(LUA_DIR) .. PS, "") -- strip the lua dir off
local script_file = l:sub(1,-5) -- strip off .lua\n
if not string.match(script_file, "script_manager") then -- let's not include ourself
if not string.match(script_file, "plugins") then -- skip plugins
if not string.match(script_file, "lib" .. PS) then -- let's not try and run libraries
if not string.match(script_file, "%.git") then -- don't match files in the .git directory
process_script_data(script_file)
script_count = script_count + 1
end
end
end
end
end
return script_count
end
local function update_scripts()
local result = false
local git = sm.executables.git
if not git then
dt.print("ERROR: git not found. Install or specify the location of the git executable.")
return
end
local git_command = "cd " .. LUA_DIR .. " " .. CS .. " " .. git .. " pull"
log.msg(log.debug, "update git command is " .. git_command)
if dt.configuration.running_os == "windows" then
result = dtsys.windows_command(git_command)
else
result = os.execute(git_command)
end
if result == 0 then
dt.print(_("lua scripts successfully updated"))
end
return result
end
local function update_script_update_choices()
local installs = {}
local pref_string = ""
for i, repo in ipairs(sm.installed_repositories) do
table.insert(installs, repo.name)
pref_string = pref_string .. i .. "," .. repo.name .. "," .. repo.directory .. ","
end
update_combobox_choices(sm.widgets.update_script_choices, installs, 1)
log.msg(log.debug, "repo pref string is " .. pref_string)
pref_write("installed_repos", "string", pref_string)
end
local function scan_repositories()
local script_count = 0
local find_cmd = "find -L " .. LUA_DIR .. " -name \\*.git -print | sort"
if dt.configuration.running_os == "windows" then
find_cmd = "dir /b/s /a:d " .. LUA_DIR .. PS .. "*.git | sort"
end
log.msg(log.debug, _("find command is ") .. find_cmd)
local output = io.popen(find_cmd)
for line in output:lines() do
local l = string.gsub(line, ds.sanitize_lua(LUA_DIR) .. PS, "") -- strip the lua dir off
local category = string.match(l, "(.-)" .. PS) -- get everything to teh first /
if category then -- if we have a category (.git doesn't)
log.msg(log.debug, "found category " .. category)
if not string.match(category, "plugins") and not string.match(category, "%.git") then -- skip plugins
if #sm.installed_repositories == 1 then
log.msg(log.debug, "only 1 repo, adding " .. category)
table.insert(sm.installed_repositories, {name = category, directory = LUA_DIR .. PS .. category})
else
log.msg(log.debug, "more than 1 repo, we have to search the repos to make sure it's not there")
local found = nil
for _, repo in ipairs(sm.installed_repositories) do
if string.match(repo.name, ds.sanitize_lua(category)) then
log.msg(log.debug, "matched " .. repo.name)
found = true
break
end
end
if not found then
table.insert(sm.installed_repositories, {name = category, directory = LUA_DIR .. PS .. category})
end
end
end
end
end
update_script_update_choices()
end
local function install_scripts()
local url = sm.widgets.script_url.text
local category = sm.widgets.new_category.text
if string.match(du.join(sm.categories, " "), ds.sanitize_lua(category)) then
log.msg(log.screen, _("category ") .. category .. _(" is already in use. Please specify a different category name."))
log.msg(log.error, "category " .. category .. " already exists, returning...")
return
end
local result = false
local git = sm.executables.git
if not git then
dt.print("ERROR: git not found. Install or specify the location of the git executable.")
return
end
local git_command = "cd " .. LUA_DIR .. " " .. CS .. " " .. git .. " clone " .. url .. " " .. category
log.msg(log.debug, "update git command is " .. git_command)
if dt.configuration.running_os == "windows" then
result = dtsys.windows_command(git_command)
else
result = dtsys.external_command(git_command)
end
log.msg(log.info, "result from import is " .. result)
if result == 0 then
local count = scan_scripts(LUA_DIR .. PS .. category)
if count > 0 then
update_combobox_choices(sm.widgets.category_selector, sm.categories, sm.widgets.category_selector.selected)
dt.print(_("scripts successfully installed into category ") .. category)
table.insert(sm.installed_repositories, {name = category, directory = LUA_DIR .. PS .. category})
update_script_update_choices()
for i = 1, #sm.widgets.category_selector do
if string.match(sm.widgets.category_selector[i], ds.sanitize_lua(category)) then
log.msg(log.debug, "setting category selector to " .. i)
sm.widgets.category_selector.selected = i
break
end
i = i + 1
end
log.msg(log.debug, "clearing text fields")
sm.widgets.script_url.text = ""
sm.widgets.new_category.text = ""
sm.widgets.main_menu.selected = 3
else
dt.print(_("No scripts found to install"))
log.msg(log.error, "scan_scripts returned " .. count .. " scripts found. Not adding to category_selector")
end
else
dt.print(_("failed to download scripts"))
end
return result
end
local function clear_button(number)
local button = sm.widgets.buttons[number]
button.label = ""
button.sensitive = false
end
local function find_script(category, name)
for _, script in ipairs(sm.scripts[category]) do
if string.match(script.name, "^" .. ds.sanitize_lua(name) .. "$") then
return script
end
end
return nil
end
local function populate_buttons(category, first, last)
log.msg(log.debug, "category is " .. category .. " and first is " .. first .. " and last is " .. last)
local button_num = 1
for i = first, last do
script = sm.scripts[category][i]
button = sm.widgets.buttons[button_num]
if script.running then
button.label = script.name .. " started"
else
button.label = script.name .. " stopped"
end
if CURR_API_STRING >= "6.0.1" then
button.ellipsize = "middle"
end
button.sensitive = true
button.tooltip = script.doc
button.clicked_callback = function (this)
local script_name, state = string.match(this.label, "(.-) (.+)")
local script = find_script(sm.widgets.category_selector.value, script_name)
if script then
log.msg(log.debug, "found script " .. script.name .. " with path " .. script.path)
if string.match(state, "started") then
log.msg(log.debug, "deactivating " .. script.name .. " on " .. script.path .. " for button " .. this.label)
deactivate(script)
this.label = script.name .. " stopped"
else
log.msg(log.debug, "activating " .. script.name .. " on " .. script.path .. " for button " .. this.label)
local result = activate(script)
if result then
this.label = script.name .. " started"
end
end
else
log.msg(log.error, "script " .. script_name .. " not found")
end
end
button_num = button_num + 1
end
if button_num <= sm.page_status.num_buttons then
for i = button_num, sm.page_status.num_buttons do
clear_button(i)
end
end
end
local function paginate(direction)
local category = sm.page_status.category
log.msg(log.debug, "category is " .. category)
local num_scripts = #sm.scripts[category]
log.msg(log.debug, "num_scripts is " .. num_scripts)
local max_pages = math.ceil(num_scripts / sm.page_status.num_buttons)
local cur_page = sm.page_status.current_page
log.msg(log.debug, "max pages is " .. max_pages)
local buttons_needed = nil
local first = nil
local last = nil
if direction == 0 then
cur_page = cur_page - 1
if cur_page < 1 then
cur_page = 1
end
elseif direction == 1 then
cur_page = cur_page + 1
if cur_page > max_pages then
cur_page = max_pages
end
else
log.msg(log.debug, "took path 2")
cur_page = 1
end
log.msg(log.debug, "cur_page is " .. cur_page .. " and max_pages is " .. max_pages)
if cur_page == max_pages and cur_page == 1 then
sm.widgets.page_forward.sensitive = false
sm.widgets.page_back.sensitive = false
elseif cur_page == max_pages then
sm.widgets.page_forward.sensitive = false
sm.widgets.page_back.sensitive = true
elseif cur_page == 1 then
sm.widgets.page_forward.sensitive = true
sm.widgets.page_back.sensitive = false
else
sm.widgets.page_forward.sensitive = true
sm.widgets.page_back.sensitive = true
end
sm.page_status.current_page = cur_page
first = (cur_page * sm.page_status.num_buttons) - (sm.page_status.num_buttons - 1)
if first + sm.page_status.num_buttons > num_scripts then
last = num_scripts
else
last = first + sm.page_status.num_buttons - 1
end
sm.widgets.page_status.label = _("Page ") .. cur_page .. _(" of ") .. max_pages
populate_buttons(category, first, last)
end
local function change_category(category)
if not category then
log.msg(log.debug "setting category to selector value " .. sm.widgets.category_selector.value)
sm.page_status.category = sm.widgets.category_selector.value
else
log.msg(log.debug, "setting catgory to argument " .. category)
sm.page_status.category = category
end
paginate(2)
end
local function change_num_buttons()
cur_buttons = sm.page_status.num_buttons
new_buttons = sm.widgets.num_buttons.value
pref_write("num_buttons", "integer", new_buttons)
if new_buttons < cur_buttons then
for i = 1, cur_buttons - new_buttons do
table.remove(sm.widgets.scripts)
end
log.msg(log.debug, "finished removing widgets, now there are " .. #sm.widgets.buttons)
elseif new_buttons > cur_buttons then
if new_buttons > sm.page_status.buttons_created then
for i = sm.page_status.buttons_created + 1, new_buttons do
table.insert(sm.widgets.buttons, dt.new_widget("button"){})
sm.page_status.buttons_created = sm.page_status.buttons_created + 1
end
end
log.msg(log.debug, "cur_buttons is " .. cur_buttons .. " and new_buttons is " .. new_buttons)
log.msg(log.debug, #sm.widgets.buttons .. " buttons are available")
for i = cur_buttons + 1, new_buttons do
log.msg(log.debug, "inserting button " .. i .. " into scripts widget")
table.insert(sm.widgets.scripts, sm.widgets.buttons[i])
end
log.msg(log.debug, "finished adding widgets, now there are " .. #sm.widgets.buttons)
else -- no change
log.msg(log.debug, "no change, just returning")
return
end
sm.page_status.num_buttons = new_buttons
log.msg(log.debug, "num_buttons set to " .. sm.page_status.num_buttons)
paginate(2) -- force the buttons to repopulate
sm.widgets.main_menu.selected = 3 -- jump back to start/stop scripts
end
local function load_preferences()
-- load the prefs and update settings
-- update_script_choices
local pref_string = pref_read("installed_repos", "string")
local entries = du.split(pref_string, ",")
while #entries > 2 do
local num = table.remove(entries, 1)
local name = table.remove(entries, 1)
local directory = table.remove(entries, 1)
if not string.match(sm.installed_repositories[1].name, "^" .. ds.sanitize_lua(name) .. "$") then
table.insert(sm.installed_repositories, {name = name, directory = directory})
end
end
update_script_update_choices()
log.msg(log.debug, "updated installed scripts")
-- category selector
local val = pref_read("category_selector", "integer")
if val == 0 then
val = 1
end
sm.widgets.category_selector.selected = val
sm.page_status.category = sm.widgets.category_selector.value
log.msg(log.debug, "updated category selector and set it to " .. sm.widgets.category_selector.value)
-- num_buttons
local val = pref_read("num_buttons", "integer")
if val == 0 then
val = DEFAULT_BUTTONS_PER_PAGE
end
sm.widgets.num_buttons.value = val
log.msg(log.debug, "set page buttons to " .. val)
change_num_buttons()
log.msg(log.debug, "paginated")
-- main menu
local val = pref_read("main_menu_action", "integer")
log.msg(log.debug, "read " .. val .. " for main menu")
if val == 0 then
val = 3
end
sm.widgets.main_menu.selected = val
log.msg(log.debug, "set main menu to val " .. val .. " which is " .. sm.widgets.main_menu.value)
log.msg(log.debug, "set main menu to " .. sm.widgets.main_menu.value)
end
local function install_module()
if not sm.module_installed then
dt.register_lib(
"script_manager", -- Module name
"script manager", -- Visible name
true, -- expandable
false, -- resetable
{[dt.gui.views.lighttable] = {"DT_UI_CONTAINER_PANEL_LEFT_BOTTOM", 600}}, -- containers
sm.widgets.main_box,
nil,-- view_enter
nil -- view_leave
)
sm.module_installed = true
end
sm.run = true
log.msg(log.debug, "set run to true, loading preferences")
load_preferences()
scan_repositories()
end
-- - - - - - - - - - - - - - - - - - - - - - - -
-- M A I N P R O G R A M
-- - - - - - - - - - - - - - - - - - - - - - - -
scan_scripts(LUA_DIR)
log.msg(log.debug, "finished processing scripts")
-- - - - - - - - - - - - - - - - - - - - - - - -
-- U S E R I N T E R F A C E
-- - - - - - - - - - - - - - - - - - - - - - - -
sm.widgets = {}
-- update the scripts
sm.widgets.update_script_choices = dt.new_widget("combobox"){
label = _("scripts to update"),
tooltip = _("select the scripts installation to update"),
selected = 1,
changed_callback = function(this)
pref_write("update_script_choices", "integer", this.selected)
end,
"placeholder",
}
sm.widgets.update = dt.new_widget("button"){
label = _("update scripts"),
tooltip = _("update the lua scripts from the repository"),
clicked_callback = function(this)
update_scripts()
end
}
-- add additional scripts
sm.widgets.script_url = dt.new_widget("entry"){
text = "",
placeholder = "https://<repository url>",
tooltip = _("enter the URL of the git repository containing the scripts you wish to add")
}
sm.widgets.new_category = dt.new_widget("entry"){
text = "",
placeholder = _("name of new category"),
tooltip = _("enter a category name for the additional scripts")
}
sm.widgets.add_scripts = dt.new_widget("box"){
orientation = vertical,
dt.new_widget("label"){label = _("URL to download additional scripts from")},
sm.widgets.script_url,
dt.new_widget("label"){label = _("new category to place scripts in")},
sm.widgets.new_category,
dt.new_widget("button"){
label = _("install additional scripts"),
clicked_callback = function(this)
install_scripts()
end
}
}
sm.widgets.allow_disable = dt.new_widget("check_button"){
label = _('Enable "Dsiable Scripts" button'),
value = false,
clicked_callback = function(this)
if this.value == true then
sm.widgets.disable_scripts.sensitive = true
end
end,
}
sm.widgets.disable_scripts = dt.new_widget("button"){
label = _("Disable Scripts"),
sensitive = false,
clicked_callback = function(this)
local LUARC = dt.configuration.config_dir .. PS .. "luarc"
df.file_move(LUARC, LUARC .. ".disabled")
log.msg(log.info, "lua scripts disabled")
dt.print(_("lua scripts will not run the next time darktable is started"))
end
}
sm.widgets.install_update = dt.new_widget("box"){
orientation = "vertical",
dt.new_widget("section_label"){label = _("update scripts")},
sm.widgets.update_script_choices,
sm.widgets.update,
dt.new_widget("section_label"){label = _("add more scripts")},
sm.widgets.add_scripts,
dt.new_widget("section_label"){label = _("disable scripts")},
sm.widgets.allow_disable,
sm.widgets.disable_scripts
}
-- manage the scripts
sm.widgets.category_selector = dt.new_widget("combobox"){
label = _("category"),
tooltip = _( "select the script category"),
selected = 1,
changed_callback = function(self)
if sm.run then
pref_write("category_selector", "integer", self.selected)
change_category(self.value)
end
end,
table.unpack(sm.categories),
}
sm.widgets.buttons ={}
for i =1, DEFAULT_BUTTONS_PER_PAGE do
table.insert(sm.widgets.buttons, dt.new_widget("button"){})
sm.page_status.buttons_create = sm.page_status.buttons_created + 1
end
local page_back = "<"
local page_forward = ">"
if CURR_API_STRING < "6.1.0" then
page_back = " < "
page_forward = " > "
end
sm.widgets.page_status = dt.new_widget("label"){label = _("Page:")}
sm.widgets.page_back = dt.new_widget("button"){
label = page_back,
clicked_callback = function(this)
if sm.run then
paginate(0)
end
end
}
sm.widgets.page_forward = dt.new_widget("button"){
label = page_forward,
clicked_callback = function(this)
if sm.run then
paginate(1)
end
end
}
sm.widgets.page_control = dt.new_widget("box"){
orientation = "horizontal",
sm.widgets.page_back,
sm.widgets.page_status,
sm.widgets.page_forward,
}
sm.widgets.scripts = dt.new_widget("box"){
orientation = vertical,
dt.new_widget("label"){label = _("Scripts")},
sm.widgets.category_selector,
sm.widgets.page_control,
table.unpack(sm.widgets.buttons)
}
-- configure options
sm.widgets.num_buttons = dt.new_widget("slider"){
label = _("scripts per page"),
tooltip = _("select number of start/stop buttons to display"),
soft_min = MIN_BUTTONS_PER_PAGE,
hard_min = MIN_BUTTONS_PER_PAGE,
soft_max = MAX_BUTTONS_PER_PAGE,
hard_max = MAX_BUTTONS_PER_PAGE,
step = 1,
digits = 0,
value = 10
}
sm.widgets.change_buttons = dt.new_widget("button"){
label = _("change number of buttons"),
clicked_callback = function(this)
change_num_buttons()
end
}
sm.widgets.configure = dt.new_widget("box"){
orientation = "vertical",
dt.new_widget("label"){label = _("Configuration")},
sm.widgets.num_buttons,
sm.widgets.change_buttons,
}
-- stack for the options
sm.widgets.main_stack = dt.new_widget("stack"){
sm.widgets.install_update,
sm.widgets.configure,
sm.widgets.scripts,
}
if CURR_API_STRING >= "6.0.1" then
sm.widgets.main_stack.h_size_fixed = false
sm.widgets.main_stack.v_size_fixed = false
end
-- main menu
sm.widgets.main_menu = dt.new_widget("combobox"){
label = _("action"),
changed_callback = function(self)
sm.widgets.main_stack.active = self.selected
pref_write("main_menu_action", "integer", self.selected)
log.msg(log.debug, "saved " .. self.selected .. " for main menu")
end,
_("install/update scripts"), _("configure"), _("start/stop scripts")
}
-- widget for module
sm.widgets.main_box = dt.new_widget("box"){
sm.widgets.main_menu,
sm.widgets.main_stack
}
-- - - - - - - - - - - - - - - - - - - - - - - -
-- D A R K T A B L E I N T E G R A T I O N
-- - - - - - - - - - - - - - - - - - - - - - - -
if dt.gui.current_view().id == "lighttable" then
install_module()
else
if not sm.event_registered then
dt.register_event(
"view-changed",
function(event, old_view, new_view)
if new_view.name == "lighttable" and old_view.name == "darkroom" then
install_module()
end
end
)
sm.event_registered = true
end
end