diff --git a/frontend/dispatcher.lua b/frontend/dispatcher.lua index 31f39e2f0..035da23d6 100644 --- a/frontend/dispatcher.lua +++ b/frontend/dispatcher.lua @@ -205,6 +205,8 @@ local settingsList = { kopt_auto_straighten = {category="absolutenumber", paging=true}, kopt_detect_indent = {category="configurable", paging=true, condition=false}, kopt_max_columns = {category="configurable", paging=true}, + + settings = nil, -- reserved for per instance dispatcher settings } -- array for item order in menu @@ -478,14 +480,22 @@ function Dispatcher:removeAction(name) return true end +local function iter_func(settings) + if settings and settings.settings and settings.settings.order then + return ipairs(settings.settings.order) + else + return pairs(settings) + end +end + -- Returns a display name for the item. -function Dispatcher:getNameFromItem(item, location, settings) +function Dispatcher:getNameFromItem(item, settings) if settingsList[item] == nil then return _("Unknown item") end local amount - if location[settings] ~= nil and location[settings][item] ~= nil then - amount = location[settings][item] + if settings ~= nil and settings[item] ~= nil then + amount = settings[item] end if amount == nil or (amount == 0 and settingsList[item].category == "incrementalnumber") @@ -495,7 +505,105 @@ function Dispatcher:getNameFromItem(item, location, settings) return T(settingsList[item].title, amount) end -function Dispatcher:addItem(caller, menu, location, settings, section) +-- Add the item to the end of the execution order. +-- If item or the order is nil all items will be added. +function Dispatcher:_addToOrder(location, settings, item) + if location[settings] then + if not location[settings].settings then location[settings].settings = {} end + if not location[settings].settings.order or item == nil then + location[settings].settings.order = {} + for k in pairs(location[settings]) do + if settingsList[k] ~= nil then + table.insert(location[settings].settings.order, k) + end + end + else + table.insert(location[settings].settings.order, item) + end + end +end + +-- Remove the item from the execution order. +-- If item is nil all items will be removed. +-- If the resulting order is empty it will be nilled +function Dispatcher:_removeFromOrder(location, settings, item) + if location[settings] and location[settings].settings then + if location[settings].settings.order then + if item then + local k = util.arrayContains(location[settings].settings.order, item) + if k then table.remove(location[settings].settings.order, k) end + else + location[settings].settings.order = {} + end + if next(location[settings].settings.order) == nil then + location[settings].settings.order = nil + if next(location[settings].settings) == nil then + location[settings].settings = nil + end + end + end + end +end + +-- Get a textual representation of the enabled actions to display in a menu item. +function Dispatcher:menuTextFunc(settings) + local action_name = _("Pass through") + if settings then + local count = util.tableSize(settings) + if count == 0 then return _("Nothing") end + if count > 1 and settings.settings ~= nil then + count = count - 1 + end + if count == 1 then + local item = next(settings) + if item == "settings" then item = next(settings, item) end + action_name = Dispatcher:getNameFromItem(item, settings) + else + action_name = _("Many") + end + end + return action_name +end + +-- Get a list of all enabled actions to display in a menu. +function Dispatcher:getDisplayList(settings) + local item_table = {} + if not settings then return item_table end + for item, v in iter_func(settings) do + if type(item) == "number" then item = v end + if settingsList[item] ~= nil and (settingsList[item].condition == nil or settingsList[item].condition == true) then + table.insert(item_table, {text = Dispatcher:getNameFromItem(item, settings), key = item}) + end + end + return item_table +end + +-- Display a SortWidget to sort the enable actions execution order. +function Dispatcher:_sortActions(caller, location, settings, touchmenu_instance) + local display_list = Dispatcher:getDisplayList(location[settings]) + local SortWidget = require("ui/widget/sortwidget") + local sort_widget + sort_widget = SortWidget:new{ + title = _("Sort"), + item_table = display_list, + callback = function() + if location[settings] and next(location[settings]) ~= nil then + if not location[settings].settings then + location[settings].settings = {} + end + location[settings].settings.order = {} + for i, v in ipairs(sort_widget.item_table) do + location[settings].settings.order[i] = v.key + end + end + if touchmenu_instance then touchmenu_instance:updateItems() end + caller.updated = true + end + } + UIManager:show(sort_widget) +end + +function Dispatcher:_addItem(caller, menu, location, settings, section) for _, k in ipairs(dispatcher_menu_order) do if settingsList[k][section] == true and (settingsList[k].condition == nil or settingsList[k].condition) @@ -512,8 +620,10 @@ function Dispatcher:addItem(caller, menu, location, settings, section) end if location[settings][k] then location[settings][k] = nil + Dispatcher:_removeFromOrder(location, settings, k) else location[settings][k] = true + Dispatcher:_addToOrder(location, settings, k) end caller.updated = true if touchmenu_instance then touchmenu_instance:updateItems() end @@ -523,7 +633,7 @@ function Dispatcher:addItem(caller, menu, location, settings, section) elseif settingsList[k].category == "absolutenumber" then table.insert(menu, { text_func = function() - return Dispatcher:getNameFromItem(k, location, settings) + return Dispatcher:getNameFromItem(k, location[settings]) end, checked_func = function() return location[settings] ~= nil and location[settings][k] ~= nil @@ -542,13 +652,14 @@ function Dispatcher:addItem(caller, menu, location, settings, section) value_hold_step = 5, value_max = settingsList[k].max, default_value = settingsList[k].default, - title_text = Dispatcher:getNameFromItem(k, location, settings), + title_text = Dispatcher:getNameFromItem(k, location[settings]), ok_always_enabled = true, callback = function(spin) if location[settings] == nil then location[settings] = {} end location[settings][k] = spin.value + Dispatcher:_addToOrder(location, settings, k) caller.updated = true if touchmenu_instance then touchmenu_instance:updateItems() @@ -560,6 +671,7 @@ function Dispatcher:addItem(caller, menu, location, settings, section) hold_callback = function(touchmenu_instance) if location[settings] ~= nil and location[settings][k] ~= nil then location[settings][k] = nil + Dispatcher:_removeFromOrder(location, settings, k) caller.updated = true end if touchmenu_instance then touchmenu_instance:updateItems() end @@ -569,7 +681,7 @@ function Dispatcher:addItem(caller, menu, location, settings, section) elseif settingsList[k].category == "incrementalnumber" then table.insert(menu, { text_func = function() - return Dispatcher:getNameFromItem(k, location, settings) + return Dispatcher:getNameFromItem(k, location[settings]) end, checked_func = function() return location[settings] ~= nil and location[settings][k] ~= nil @@ -589,7 +701,7 @@ function Dispatcher:addItem(caller, menu, location, settings, section) value_hold_step = 5, value_max = settingsList[k].max, default_value = 0, - title_text = Dispatcher:getNameFromItem(k, location, settings), + title_text = Dispatcher:getNameFromItem(k, location[settings]), info_text = _([[If called by a gesture the amount of the gesture will be used]]), ok_always_enabled = true, callback = function(spin) @@ -597,6 +709,7 @@ function Dispatcher:addItem(caller, menu, location, settings, section) location[settings] = {} end location[settings][k] = spin.value + Dispatcher:_addToOrder(location, settings, k) caller.updated = true if touchmenu_instance then touchmenu_instance:updateItems() @@ -608,6 +721,7 @@ function Dispatcher:addItem(caller, menu, location, settings, section) hold_callback = function(touchmenu_instance) if location[settings] ~= nil and location[settings][k] ~= nil then location[settings][k] = nil + Dispatcher:_removeFromOrder(location, settings, k) caller.updated = true end if touchmenu_instance then @@ -634,13 +748,14 @@ function Dispatcher:addItem(caller, menu, location, settings, section) location[settings] = {} end location[settings][k] = settingsList[k].args[i] + Dispatcher:_addToOrder(location, settings, k) caller.updated = true end, }) end table.insert(menu, { text_func = function() - return Dispatcher:getNameFromItem(k, location, settings) + return Dispatcher:getNameFromItem(k, location[settings]) end, checked_func = function() return location[settings] ~= nil and location[settings][k] ~= nil @@ -650,6 +765,7 @@ function Dispatcher:addItem(caller, menu, location, settings, section) hold_callback = function(touchmenu_instance) if location[settings] ~= nil and location[settings][k] ~= nil then location[settings][k] = nil + Dispatcher:_removeFromOrder(location, settings, k) caller.updated = true end if touchmenu_instance then @@ -699,7 +815,7 @@ function Dispatcher:addSubMenu(caller, menu, location, settings) } for _, section in ipairs(section_list) do local submenu = {} - Dispatcher:addItem(caller, submenu, location, settings, section[1]) + Dispatcher:_addItem(caller, submenu, location, settings, section[1]) table.insert(menu, { text = section[2], checked_func = function() @@ -716,6 +832,7 @@ function Dispatcher:addSubMenu(caller, menu, location, settings) for k, _ in pairs(location[settings]) do if settingsList[k] ~= nil and settingsList[k][section[1]] == true then location[settings][k] = nil + Dispatcher:_removeFromOrder(location, settings, k) caller.updated = true end end @@ -725,6 +842,78 @@ function Dispatcher:addSubMenu(caller, menu, location, settings) sub_item_table = submenu, }) end + menu[#menu].separator = true + table.insert(menu, { + text = _("Show as QuickMenu"), + checked_func = function() + return location[settings] ~= nil + and location[settings].settings ~= nil + and location[settings].settings.show_as_quickmenu + end, + callback = function() + if location[settings] and location[settings].settings then + if location[settings].settings.show_as_quickmenu then + location[settings].settings.show_as_quickmenu = nil + if next(location[settings].settings) == nil then + location[settings].settings = nil + end + else + location[settings].settings.show_as_quickmenu = true + end + else + location[settings].settings = {["show_as_quickmenu"] = true} + end + caller.updated = true + end, + }) + table.insert(menu, { + text = _("Sort"), + checked_func = function() + return location[settings] ~= nil + and location[settings].settings ~= nil + and location[settings].settings.order ~= nil + end, + callback = function(touchmenu_instance) + Dispatcher:_sortActions(caller, location, settings, touchmenu_instance) + end, + hold_callback = function(touchmenu_instance) + if location[settings] + and location[settings].settings + and location[settings].settings.order then + Dispatcher:_removeFromOrder(location, settings) + caller.updated = true + if touchmenu_instance then touchmenu_instance:updateItems() end + end + end, + }) +end + +function Dispatcher:_showAsMenu(settings) + local display_list = Dispatcher:getDisplayList(settings) + local quickmenu + local buttons = {} + for _, v in ipairs(display_list) do + table.insert(buttons, {{ + text = v.text, + align = "left", + font_face = "smallinfofont", + font_size = 22, + font_bold = false, + callback = function() + UIManager:close(quickmenu) + Dispatcher:execute({[v.key] = settings[v.key]}) + end, + }}) + end + local ButtonDialogTitle = require("ui/widget/buttondialogtitle") + quickmenu = ButtonDialogTitle:new{ + title = settings.settings.name or "Quick Menu", + title_align = "center", + width_factor = 0.8, + use_info_style = false, + buttons = buttons, + } + UIManager:show(quickmenu) end --[[-- @@ -735,8 +924,15 @@ arguments are: 3) optionally a `gestures`object --]]-- function Dispatcher:execute(settings, gesture) - for k, v in pairs(settings) do - if settingsList[k] ~= nil and (settingsList[k].conditions == nil or settingsList[k].conditions == true) then + if settings.settings ~= nil and settings.settings.show_as_quickmenu == true then + return Dispatcher:_showAsMenu(settings) + end + for k, v in iter_func(settings) do + if type(k) == "number" then + k = v + v = settings[k] + end + if settingsList[k] ~= nil and (settingsList[k].condition == nil or settingsList[k].condition == true) then Notification:setNotifySource(Notification.SOURCE_DISPATCHER) if settingsList[k].configurable then local value = v diff --git a/plugins/gestures.koplugin/main.lua b/plugins/gestures.koplugin/main.lua index d2ef7a49c..8ac06d7cf 100644 --- a/plugins/gestures.koplugin/main.lua +++ b/plugins/gestures.koplugin/main.lua @@ -186,30 +186,16 @@ function Gestures:init() self:initGesture() end -local gestureTextFunc = function(location, ges) - local item = location[ges] - local action_name = _("Pass through") - if item then - local sub_item = next(item) - if sub_item == nil then return _("Nothing") end - action_name = Dispatcher:getNameFromItem(sub_item, location, ges) - if next(item, sub_item) ~= nil then - action_name = _("Many") - end - end - return action_name -end - function Gestures:gestureTitleFunc(ges) local title = gestures_list[ges] or self:friendlyMultiswipeName(ges) - return T(_("%1 (%2)"), title, gestureTextFunc(self.gestures, ges)) + return T(_("%1 (%2)"), title, Dispatcher:menuTextFunc(self.gestures[ges])) end function Gestures:genMenu(ges) local sub_items = {} if gestures_list[ges] ~= nil then table.insert(sub_items, { - text = T(_("%1 (default)"), gestureTextFunc(self.defaults, ges)), + text = T(_("%1 (default)"), Dispatcher:menuTextFunc(self.defaults[ges])), keep_menu_open = true, separator = true, checked_func = function() @@ -224,7 +210,6 @@ function Gestures:genMenu(ges) table.insert(sub_items, { text = _("Pass through"), keep_menu_open = true, - separator = true, checked_func = function() return self.gestures[ges] == nil end, diff --git a/plugins/profiles.koplugin/main.lua b/plugins/profiles.koplugin/main.lua index 8fc25f020..3ce5b44bb 100644 --- a/plugins/profiles.koplugin/main.lua +++ b/plugins/profiles.koplugin/main.lua @@ -45,14 +45,11 @@ end local function dispatcherRegisterProfile(name) Dispatcher:registerAction("profile_exec_"..name, - {category="none", event="ProfileExecute", arg=name, title=T(_("Profile \u{F144} %1"), name), general=true}) - Dispatcher:registerAction("profile_menu_"..name, - {category="none", event="ProfileShowMenu", arg=name, title=T(_("Profile \u{F0CA} %1"), name), general=true}) + {category="none", event="ProfileExecute", arg=name, title=T(_("Profile %1"), name), general=true}) end local function dispatcherRemoveProfile(name) Dispatcher:removeAction("profile_exec_"..name) - Dispatcher:removeAction("profile_menu_"..name) end function Profiles:onDispatcherRegisterActions() @@ -80,6 +77,8 @@ function Profiles:getSubMenuItems() callback = function(touchmenu_instance) local function editCallback(new_name) self.data[new_name] = {} + self.data[new_name].settings = {} + self.data[new_name].settings.name = new_name self.updated = true dispatcherRegisterProfile(new_name) touchmenu_instance.item_table = self:getSubMenuItems() @@ -102,35 +101,6 @@ function Profiles:getSubMenuItems() self:onProfileExecute(k) end, }, - { - text = _("Show as QuickMenu"), - callback = function() - self:onProfileShowMenu(k) - end, - }, - { - text = _("Show as QuickMenu on long-press"), - checked_func = function() - local settings = self.data[k].settings - return settings and settings.long_press_show_menu - end, - callback = function() - local settings = self.data[k].settings - if settings then - if settings.long_press_show_menu then - settings.long_press_show_menu = nil - if #settings == 0 then - self.data[k].settings = nil - end - else - settings.long_press_show_menu = true - end - else - self.data[k].settings = {["long_press_show_menu"] = true} - end - self.updated = true - end, - }, { text = _("Autostart"), help_text = _("Execute this profile when KOReader is started with 'file browser' or 'last file'."), @@ -144,36 +114,16 @@ function Profiles:getSubMenuItems() separator = true, }, { - text = _("Edit actions"), + text_func = function() return T(_("Edit actions: (%1)"), Dispatcher:menuTextFunc(v)) end, sub_item_table = edit_actions_sub_items, }, - { - text = _("Sort actions"), - checked_func = function() - local settings = self.data[k].settings - return settings and settings.actions_order - end, - callback = function(touchmenu_instance) - self:sortActions(k, touchmenu_instance) - end, - hold_callback = function(touchmenu_instance) - if self.data[k].settings and self.data[k].settings.actions_order then - self.data[k].settings.actions_order = nil - if #self.data[k].settings == 0 then - self.data[k].settings = nil - end - self.updated = true - touchmenu_instance:updateItems() - end - end, - separator = true, - }, { text = T(_("Rename: %1"), k), keep_menu_open = true, callback = function(touchmenu_instance) local function editCallback(new_name) self.data[new_name] = util.tableDeepCopy(v) + self.data[new_name].settings.name = new_name self.data[k] = nil self.updated = true self:renameAutostart(k, new_name) @@ -186,11 +136,15 @@ function Profiles:getSubMenuItems() end, }, { - text = _("Copy"), + text = _("Duplicate"), keep_menu_open = true, callback = function(touchmenu_instance) local function editCallback(new_name) self.data[new_name] = util.tableDeepCopy(v) + if not self.data[new_name].settings then + self.data[new_name].settings = {} + end + self.data[new_name].settings.name = new_name self.updated = true dispatcherRegisterProfile(new_name) touchmenu_instance.item_table = self:getSubMenuItems() @@ -224,12 +178,7 @@ function Profiles:getSubMenuItems() hold_keep_menu_open = false, sub_item_table = sub_items, hold_callback = function() - local settings = self.data[k].settings - if settings and settings.long_press_show_menu then - self:onProfileShowMenu(k) - else - self:onProfileExecute(k) - end + self:onProfileExecute(k) end, }) end @@ -237,71 +186,7 @@ function Profiles:getSubMenuItems() end function Profiles:onProfileExecute(name) - local profile = self.data[name] - if profile and profile.settings and profile.settings.actions_order then - self:syncOrder(name) - for _, action in ipairs(profile.settings.actions_order) do - Dispatcher:execute({[action] = profile[action]}) - end - else - Dispatcher:execute(profile) - end -end - -function Profiles:onProfileShowMenu(name) - if UIManager:getTopWidget() == name then return end - local profile = self.data[name] - local actions_list = self:getActionsList(name) - local quickmenu - local buttons = {} - for _, v in ipairs(actions_list) do - table.insert(buttons, {{ - text = v.text, - align = "left", - font_face = "smallinfofont", - font_size = 22, - font_bold = false, - callback = function() - UIManager:close(quickmenu) - local action = v.label - Dispatcher:execute({[action] = profile[action]}) - end, - }}) - end - local ButtonDialogTitle = require("ui/widget/buttondialogtitle") - quickmenu = ButtonDialogTitle:new{ - name = name, - title = name, - title_align = "center", - width_factor = 0.8, - use_info_style = false, - buttons = buttons, - } - UIManager:show(quickmenu) -end - -function Profiles:sortActions(name, touchmenu_instance) - local profile = self.data[name] - local actions_list = self:getActionsList(name) - local SortWidget = require("ui/widget/sortwidget") - local sort_widget - sort_widget = SortWidget:new{ - title = _("Sort actions"), - item_table = actions_list, - callback = function() - if profile.settings then - self.data[name].settings.actions_order = {} - else - self.data[name].settings = {["actions_order"] = {}} - end - for i, v in ipairs(sort_widget.item_table) do - self.data[name].settings.actions_order[i] = v.label - end - touchmenu_instance:updateItems() - self.updated = true - end - } - UIManager:show(sort_widget) + Dispatcher:execute(self.data[name]) end function Profiles:editProfileName(editCallback, old_name) @@ -337,51 +222,6 @@ function Profiles:editProfileName(editCallback, old_name) name_input:onShowKeyboard() end -function Profiles:getActionsList(name) - local profile = self.data[name] - local function getActionFullName (profile_name, action_name) - local location = {} -- make this as expected by Dispatcher:getNameFromItem() - if type(profile_name[action_name]) ~= "boolean" then - location[action_name] = {[action_name] = profile_name[action_name]} - end - return Dispatcher:getNameFromItem(action_name, location, action_name) - end - local actions_list = {} - if profile and profile.settings and profile.settings.actions_order then - self:syncOrder(name) - for _, action in ipairs(profile.settings.actions_order) do - table.insert(actions_list, {text = getActionFullName(profile, action), label = action}) - end - else - for action in pairs(profile) do - if action ~= "settings" then - table.insert(actions_list, {text = getActionFullName(profile, action), label = action}) - end - end - end - return actions_list -end - -function Profiles:syncOrder(name) - local profile = self.data[name] - for i = #profile.settings.actions_order, 1, -1 do - if not profile[profile.settings.actions_order[i]] then - table.remove(self.data[name].settings.actions_order, i) - if not self.updated then - self.updated = true - end - end - end - for action in pairs(profile) do - if action ~= "settings" and not util.arrayContains(profile.settings.actions_order, action) then - table.insert(self.data[name].settings.actions_order, action) - if not self.updated then - self.updated = true - end - end - end -end - function Profiles:renameAutostart(old_name, new_name) if G_reader_settings:getSettingForExt("autostart_profiles", old_name) then G_reader_settings:saveSettingForExt("autostart_profiles", nil, old_name)