diff --git a/tools/script_manager.lua b/tools/script_manager.lua index 3907205..435768c 100644 --- a/tools/script_manager.lua +++ b/tools/script_manager.lua @@ -216,17 +216,24 @@ end local function pref_read(name, pref_type) local old_log_level = set_log_level(sm.log_level) + log.msg(log.debug, "name is " .. name .. " and type is " .. pref_type) + local val = dt.preferences.read(MODULE, name, pref_type) + log.msg(log.debug, "read value " .. tostring(val)) + restore_log_level(old_log_level) return val end local function pref_write(name, pref_type, value) local old_log_level = set_log_level(sm.log_level) + log.msg(log.debug, "writing value " .. tostring(value) .. " for name " .. name) + dt.preferences.write(MODULE, name, pref_type, value) + restore_log_level(old_log_level) end @@ -236,12 +243,15 @@ end local function get_repo_status(repo) local old_log_level = set_log_level(sm.log_level) + local p = io.popen("cd " .. repo .. CS .. "git status") + if p then local data = p:read("*a") p:close() return data end + log.msg(log.error, "unable to get status of " .. repo) restore_log_level(old_log_level) return nil @@ -249,8 +259,11 @@ end local function get_current_repo_branch(repo) local old_log_level = set_log_level(sm.log_level) + local branch = nil + local p = io.popen("cd " .. repo .. CS .. "git branch --all") + if p then local data = p:read("*a") p:close() @@ -258,23 +271,29 @@ local function get_current_repo_branch(repo) for _, b in ipairs(branches) do log.msg(log.debug, "branch for testing is " .. b) branch = string.match(b, "^%* (.-)$") + if branch then log.msg(log.info, "current repo branch is " .. branch) return branch end + end end + if not branch then log.msg(log.error, "no current branch detected in repo_data") end + restore_log_level(old_log_level) return nil end local function get_repo_branches(repo) local old_log_level = set_log_level(sm.log_level) + local branches = {} local p = io.popen("cd " .. repo .. CS .. "git pull --all" .. CS .. "git branch --all") + if p then local data = p:read("*a") p:close() @@ -289,12 +308,14 @@ local function get_repo_branches(repo) end end end + restore_log_level(old_log_level) return branches end local function is_repo_clean(repo_data) local old_log_level = set_log_level(sm.log_level) + if string.match(repo_data, "\n%s-%a.-%a:%s-%a%g-\n") then log.msg(log.info, "repo is dirty") return false @@ -302,13 +323,17 @@ local function is_repo_clean(repo_data) log.msg(log.info, "repo is clean") return true end + restore_log_level(old_log_level) end local function checkout_repo_branch(repo, branch) local old_log_level = set_log_level(sm.log_level) + log.msg(log.info, "checkout out branch " .. branch .. " from repository " .. repo) + os.execute("cd " .. repo .. CS .. "git checkout " .. branch) + restore_log_level(old_log_level) end @@ -318,16 +343,20 @@ end local function update_combobox_choices(combobox, choice_table, selected) local old_log_level = set_log_level(sm.log_level) + 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 @@ -338,8 +367,10 @@ end local function string_trim(str) local old_log_level = set_log_level(sm.log_level) + local result = string.gsub(str, "^%s+", "") result = string.gsub(result, "%s+$", "") + restore_log_level(old_log_level) return result end @@ -358,11 +389,13 @@ end local function add_script_folder(folder) local old_log_level = set_log_level(sm.log_level) + if #sm.folders == 0 or not string.match(du.join(sm.folders, " "), ds.sanitize_lua(folder)) then table.insert(sm.folders, folder) sm.scripts[folder] = {} log.msg(log.debug, "created folder " .. folder) end + restore_log_level(old_log_level) end @@ -435,18 +468,26 @@ end local function activate(script) local old_log_level = set_log_level(sm.log_level) + local status = nil -- status of start function local err = nil -- error message returned if module doesn't start + log.msg(log.info, "activating " .. script.name) + if script.running == false then + script_manager_running_script = script.name + status, err = du.prequire(script.path) log.msg(log.debug, "prequire returned " .. tostring(status) .. " and for err " .. tostring(err)) + script_manager_running_script = nil + if status then pref_write(script.script_name, "bool", true) log.msg(log.screen, _("Loaded ") .. script.script_name) script.running = true + if err ~= true then log.msg(log.debug, "got lib data") script.data = err @@ -456,17 +497,20 @@ local function activate(script) else script.data = nil end + 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 + else -- script is a lib and loaded but hidden and the user wants to reload script.data.restart() script.running = true status = true pref_write(script.script_name, "bool", true) end + restore_log_level(old_log_level) return status end @@ -481,9 +525,13 @@ local function deactivate(script) -- deactivate it.... local old_log_level = set_log_level(sm.log_level) + pref_write(script.script_name, "bool", false) + if script.data then + script.data.destroy() + if script.data.destroy_method then if string.match(script.data.destroy_method, "hide") then script.running = "hidden" @@ -495,20 +543,26 @@ local function deactivate(script) package.loaded[script.script_name] = nil script.running = false end + log.msg(log.info, "turned off " .. script.script_name) log.msg(log.screen, script.name .. _(" stopped")) + else 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 + restore_log_level(old_log_level) end local function add_script_name(name, path, folder) local old_log_level = set_log_level(sm.log_level) + log.msg(log.debug, "folder is " .. folder) log.msg(log.debug, "name is " .. name) + local script = { name = name, path = folder .. "/" .. path .. name, @@ -518,12 +572,15 @@ local function add_script_name(name, path, folder) script_name = folder .. "/" .. name, data = nil } + table.insert(sm.scripts[folder], script) + if pref_read(script.script_name, "bool") then activate(script) else pref_write(script.script_name, "bool", false) end + restore_log_level(old_log_level) end @@ -565,31 +622,43 @@ end local function ensure_lib_in_search_path(line) local old_log_level = set_log_level(sm.log_level) - -- set_log_level(log.debug) + log.msg(log.debug, "line is " .. line) + if string.match(line, ds.sanitize_lua(dt.configuration.config_dir .. PS .. "lua/lib")) then log.msg(log.debug, line .. " is already in search path, returning...") return end + local path = string.match(line, "(.+)/lib/.+lua") + log.msg(log.debug, "extracted path is " .. path) log.msg(log.debug, "package.path is " .. package.path) + if not string.match(package.path, ds.sanitize_lua(path)) then + log.msg(log.debug, "path isn't in package.path, adding...") + package.path = package.path .. ";" .. path .. "/?.lua" + log.msg(log.debug, "new package.path is " .. package.path) end + restore_log_level(old_log_level) end local function scan_scripts(script_dir) local old_log_level = set_log_level(sm.log_level) + 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 @@ -608,6 +677,7 @@ local function scan_scripts(script_dir) end end end + restore_log_level(old_log_level) return script_count end @@ -646,39 +716,54 @@ end local function update_script_update_choices() local old_log_level = set_log_level(sm.log_level) + 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) + restore_log_level(old_log_level) end local function scan_repositories() local old_log_level = set_log_level(sm.log_level) + 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 folder = string.match(l, "(.-)" .. PS) -- get everything to teh first / + local folder = string.match(l, "(.-)" .. PS) -- get everything to the first / + if folder then -- if we have a folder (.git doesn't) + log.msg(log.debug, "found folder " .. folder) + if not string.match(folder, "plugins") and not string.match(folder, "%.git") then -- skip plugins + if #sm.installed_repositories == 1 then log.msg(log.debug, "only 1 repo, adding " .. folder) table.insert(sm.installed_repositories, {name = folder, directory = LUA_DIR .. PS .. folder}) 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(folder)) then log.msg(log.debug, "matched " .. repo.name) @@ -686,19 +771,24 @@ local function scan_repositories() break end end + if not found then table.insert(sm.installed_repositories, {name = folder, directory = LUA_DIR .. PS .. folder}) end + end end end end + update_script_update_choices() + restore_log_level(old_log_level) end local function install_scripts() local old_log_level = set_log_level(sm.log_level) + local url = sm.widgets.script_url.text local folder = sm.widgets.new_folder.text @@ -732,11 +822,13 @@ local function install_scripts() if result == 0 then local count = scan_scripts(LUA_DIR .. PS .. folder) + if count > 0 then update_combobox_choices(sm.widgets.folder_selector, sm.folders, sm.widgets.folder_selector.selected) dt.print(_("scripts successfully installed into folder ") .. folder) table.insert(sm.installed_repositories, {name = folder, directory = LUA_DIR .. PS .. folder}) update_script_update_choices() + for i = 1, #sm.widgets.folder_selector do if string.match(sm.widgets.folder_selector[i], ds.sanitize_lua(folder)) then log.msg(log.debug, "setting folder selector to " .. i) @@ -745,6 +837,7 @@ local function install_scripts() end i = i + 1 end + log.msg(log.debug, "clearing text fields") sm.widgets.script_url.text = "" sm.widgets.new_folder.text = "" @@ -753,6 +846,7 @@ local function install_scripts() dt.print(_("No scripts found to install")) log.msg(log.error, "scan_scripts returned " .. count .. " scripts found. Not adding to folder_selector") end + else dt.print(_("failed to download scripts")) end @@ -763,47 +857,59 @@ end local function clear_button(number) local old_log_level = set_log_level(sm.log_level) + local button = sm.widgets.buttons[number] local label = sm.widgets.labels[number] + button.image = BLANK_ICON button.tooltip = "" button.sensitive = false label.label = "" button.name = "" + restore_log_level(old_log_level) end local function find_script(folder, name) local old_log_level = set_log_level(sm.log_level) + log.msg(log.debug, "looking for script " .. name .. " in folder " .. folder) + for _, script in ipairs(sm.scripts[folder]) do if string.match(script.name, "^" .. ds.sanitize_lua(name) .. "$") then return script end end + restore_log_level(old_log_level) return nil end local function populate_buttons(folder, first, last) local old_log_level = set_log_level(sm.log_level) + log.msg(log.debug, "folder is " .. folder .. " and first is " .. first .. " and last is " .. last) + local button_num = 1 + for i = first, last do local script = sm.scripts[folder][i] local button = sm.widgets.buttons[button_num] local label = sm.widgets.labels[button_num] + if script.running == true then button.name = "pb_on" else button.name = "pb_off" end + button.image = POWER_ICON label.label = script.name label.name = "pb_label" button.ellipsize = "end" button.sensitive = true label.tooltip = script.metadata and script.metadata or script.doc + button.clicked_callback = function (this) local cb_script = script local state = nil @@ -822,23 +928,30 @@ local function populate_buttons(folder, first, last) end 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 + restore_log_level(old_log_level) end local function paginate(direction) local old_log_level = set_log_level(sm.log_level) + local folder = sm.page_status.folder log.msg(log.debug, "folder is " .. folder) + local num_scripts = #sm.scripts[folder] 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) @@ -860,7 +973,9 @@ local function paginate(direction) 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 @@ -876,20 +991,25 @@ local function paginate(direction) 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(folder, first, last) + restore_log_level(old_log_level) end local function change_folder(folder) local old_log_level = set_log_level(sm.log_level) + if not folder then log.msg(log.debug "setting folder to selector value " .. sm.widgets.folder_selector.value) sm.page_status.folder = sm.widgets.folder_selector.value @@ -899,20 +1019,25 @@ local function change_folder(folder) end paginate(2) + restore_log_level(old_log_level) end local function change_num_buttons() local old_log_level = set_log_level(sm.log_level) - -- set_log_level(log.debug) + 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 log.msg(log.debug, "took new is less than current branch") + 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 log.msg(log.debug, "took new is greater than current branch") @@ -920,7 +1045,9 @@ local function change_num_buttons() log.msg(log.debug, "number of buttons is " .. #sm.widgets.buttons) log.msg(log.debug, "number of labels is " .. #sm.widgets.labels) log.msg(log.debug, "number of boxes is " .. #sm.widgets.boxes) + if new_buttons > sm.page_status.buttons_created then + for i = sm.page_status.buttons_created + 1, new_buttons do log.msg(log.debug, "i is " .. i) table.insert(sm.widgets.buttons, dt.new_widget("button"){}) @@ -934,73 +1061,97 @@ local function change_num_buttons() log.msg(log.debug, "inserted new box") 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.boxes[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 + restore_log_level(old_log_level) end local function load_preferences() local old_log_level = set_log_level(sm.log_level) + -- 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") + -- folder selector local val = pref_read("folder_selector", "integer") + if val == 0 then val = 1 end + sm.widgets.folder_selector.selected = val sm.page_status.folder = sm.widgets.folder_selector.value log.msg(log.debug, "updated folder selector and set it to " .. sm.widgets.folder_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) + restore_log_level(old_log_level) end local function install_module() local old_log_level = set_log_level(sm.log_level) + if not sm.module_installed then dt.register_lib( "script_manager", -- Module name @@ -1014,6 +1165,7 @@ local function install_module() ) sm.module_installed = true end + sm.run = true sm.use_color = pref_read("use_color", "bool") log.msg(log.debug, "set run to true, loading preferences") @@ -1030,6 +1182,7 @@ local function install_module() dt.control.sleep(5000) dt.print_log("setting sm expanded true") dt.gui.libs["script_manager"].expanded = true]] + restore_log_level(old_log_level) end @@ -1048,22 +1201,28 @@ if check_for_updates then local repo = LUA_DIR if current_branch then + if sm.executables.git and clean and + (current_branch == "master" or string.match(current_branch, "^API%-")) then -- only make changes to clean branches local branches = get_repo_branches(LUA_DIR) + if current_branch ~= LUA_API_VER and current_branch ~= "master" then -- probably upgraded from an earlier api version so get back to master -- to use the latest version of script_manager to get the proper API checkout_repo_branch(repo, "master") log.msg(log.screen, "lua API version reset, please restart darktable") + elseif LUA_API_VER == current_branch then -- do nothing, we are fine log.msg(log.debug, "took equal branch, doing nothing") + elseif string.match(LUA_API_VER, "dev") then -- we are on a dev API version, so checkout the dev -- api version or checkout/stay on master log.msg(log.debug, "took the dev branch") local match = false + for _, branch in ipairs(branches) do log.msg(log.debug, "checking branch " .. branch .. " against API " .. LUA_API_VER) if LUA_API_VER == branch then @@ -1072,6 +1231,7 @@ if check_for_updates then checkout_repo_branch(repo, branch) end end + if not match then if current_branch == "master" then log.msg(log.info, "staying on master, no dev branch yet") @@ -1080,25 +1240,33 @@ if check_for_updates then checkout_repo_branch(repo, "master") end end + elseif #branches > 0 and LUA_API_VER > branches[#branches] then log.msg(log.info, "no newer branches, staying on master") -- stay on master + else -- checkout the appropriate branch for API version if it exists log.msg(log.info, "checking out the appropriate API branch") + local match = false + for _, branch in ipairs(branches) do log.msg(log.debug, "checking branch " .. branch .. " against API " .. LUA_API_VER) + if LUA_API_VER == branch then match = true log.msg(log.info, "checking out repo branch " .. branch) checkout_repo_branch(repo, branch) log.msg(log.screen, "you must restart darktable to use the correct version of the lua") end + end + if not match then log.msg(log.warn, "no matching branch found for " .. LUA_API_VER) end + end end end @@ -1216,6 +1384,7 @@ sm.widgets.folder_selector = dt.new_widget("combobox"){ sm.widgets.buttons ={} sm.widgets.labels = {} sm.widgets.boxes = {} + for i =1, DEFAULT_BUTTONS_PER_PAGE do table.insert(sm.widgets.buttons, dt.new_widget("button"){}) table.insert(sm.widgets.labels, dt.new_widget("label"){}) @@ -1228,6 +1397,7 @@ local page_back = "<" local page_forward = ">" 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) @@ -1297,6 +1467,7 @@ sm.widgets.color = dt.new_widget("check_button"){ sm.use_color = this.value end } + table.insert(sm.widgets.configure, sm.widgets.color) -- stack for the options