Add new presets.lua module and dictionary presets (#13774)
Some checks failed
macos / macOS 13 x86-64 🔨15.2 🎯10.15 (push) Has been cancelled
macos / macOS 14 ARM64 🔨15.4 🎯11.0 (push) Has been cancelled

This commit is contained in:
David
2025-06-20 22:33:45 +01:00
committed by GitHub
parent 0594f619c3
commit 30499e33b0
6 changed files with 633 additions and 219 deletions

View File

@@ -14,6 +14,7 @@ local KeyValuePage = require("ui/widget/keyvaluepage")
local LuaData = require("luadata")
local MultiConfirmBox = require("ui/widget/multiconfirmbox")
local NetworkMgr = require("ui/network/manager")
local Presets = require("ui/presets")
local SortWidget = require("ui/widget/sortwidget")
local Trapper = require("ui/trapper")
local UIManager = require("ui/uimanager")
@@ -165,6 +166,17 @@ function ReaderDictionary:init()
if not lookup_history then
lookup_history = LuaData:open(DataStorage:getSettingsDir() .. "/lookup_history.lua", "LookupHistory")
end
self.preset_obj = {
presets = G_reader_settings:readSetting("dict_presets", {}),
cycle_index = G_reader_settings:readSetting("dict_presets_cycle_index"),
dispatcher_name = "load_dictionary_preset",
saveCycleIndex = function(this)
G_reader_settings:saveSetting("dict_presets_cycle_index", this.cycle_index)
end,
buildPreset = function() return self:buildPreset() end,
loadPreset = function(preset) self:loadPreset(preset) end,
}
end
function ReaderDictionary:registerKeyEvents()
@@ -281,9 +293,18 @@ function ReaderDictionary:addToMainMenu(menu_items)
end)
end,
},
{
text = _("Dictionary presets"),
help_text = _("This feature allows you to organize dictionaries into presets (for example, by language). You can quickly switch between these presets to change which dictionaries are used for lookups.\n\nNote: presets only store dictionaries, no other settings."),
sub_item_table_func = function()
return Presets.genPresetMenuItemTable(self.preset_obj, _("Create new preset from enabled dictionaries"),
function() return self.enabled_dict_names and #self.enabled_dict_names > 0 end)
end,
},
{
text = _("Download dictionaries"),
sub_item_table_func = function() return self:_genDownloadDictionariesMenu() end,
separator = true,
},
{
text_func = function()
@@ -313,32 +334,40 @@ function ReaderDictionary:addToMainMenu(menu_items)
separator = true,
},
{
text = _("Enable dictionary lookup history"),
text = _("Dictionary lookup history"),
checked_func = function()
return not self.disable_lookup_history
end,
callback = function()
self.disable_lookup_history = not self.disable_lookup_history
G_reader_settings:saveSetting("disable_lookup_history", self.disable_lookup_history)
end,
},
{
text = _("Clean dictionary lookup history"),
enabled_func = function()
return lookup_history:has("lookup_history")
end,
keep_menu_open = true,
callback = function(touchmenu_instance)
UIManager:show(ConfirmBox:new{
text = _("Clean dictionary lookup history?"),
ok_text = _("Clean"),
ok_callback = function()
-- empty data table to replace current one
lookup_history:reset{}
touchmenu_instance:updateItems()
sub_item_table = {
{
text = _("Enable dictionary lookup history"),
checked_func = function()
return not self.disable_lookup_history
end,
})
end,
callback = function()
self.disable_lookup_history = not self.disable_lookup_history
G_reader_settings:saveSetting("disable_lookup_history", self.disable_lookup_history)
end,
},
{
text = _("Clean dictionary lookup history"),
enabled_func = function()
return lookup_history:has("lookup_history")
end,
keep_menu_open = true,
callback = function(touchmenu_instance)
UIManager:show(ConfirmBox:new{
text = _("Clean dictionary lookup history?"),
ok_text = _("Clean"),
ok_callback = function()
-- empty data table to replace current one
lookup_history:reset{}
touchmenu_instance:updateItems()
end,
})
end,
},
},
separator = true,
},
{ -- setting used by dictquicklookup
@@ -385,7 +414,7 @@ function ReaderDictionary:addToMainMenu(menu_items)
}
}
if not is_docless then
table.insert(menu_items.dictionary_settings.sub_item_table, 3, {
table.insert(menu_items.dictionary_settings.sub_item_table, 2, {
keep_menu_open = true,
text = _("Set dictionary priority for this book"),
help_text = _("This feature enables you to specify dictionary priorities on a per-book basis. Results from higher-priority dictionaries will be displayed first when looking up words. Only dictionaries that are currently active can be selected and prioritized."),
@@ -859,31 +888,70 @@ function ReaderDictionary:dismissLookupInfo()
end
function ReaderDictionary:onShowDictionaryLookup()
local buttons = {}
local preset_names = Presets.getPresets(self.preset_obj)
if preset_names and #preset_names > 0 then
table.insert(buttons, {
{
text = _("Search with preset"),
callback = function()
local text = self.dictionary_lookup_dialog:getInputText()
if text == "" or text:match("^%s*$") then return end
local current_dict_state = self:buildPreset()
local button_dialog, dialog_buttons = nil, {} -- CI won't like it if we call it buttons :( so dialog_buttons
for _, preset_name in ipairs(preset_names) do
table.insert(dialog_buttons, {
{
align = "left",
text = preset_name,
callback = function()
self:loadPreset(self.preset_obj.presets[preset_name], true)
UIManager:close(button_dialog)
UIManager:close(self.dictionary_lookup_dialog)
self:onLookupWord(text, true, nil, nil, nil,
function()
self:loadPreset(current_dict_state, true)
end
)
end,
}
})
end
button_dialog = ButtonDialog:new{
buttons = dialog_buttons,
shrink_unneeded_width = true,
}
UIManager:show(button_dialog)
end,
}
})
end
table.insert(buttons, {
{
text = _("Cancel"),
id = "close",
callback = function()
UIManager:close(self.dictionary_lookup_dialog)
end,
},
{
text = _("Search dictionary"),
is_enter_default = true,
callback = function()
if self.dictionary_lookup_dialog:getInputText() == "" then return end
UIManager:close(self.dictionary_lookup_dialog)
-- Trust that input text does not need any cleaning (allows querying for "-suffix")
self:onLookupWord(self.dictionary_lookup_dialog:getInputText(), true)
end,
},
})
self.dictionary_lookup_dialog = InputDialog:new{
title = _("Enter a word or phrase to look up"),
input = "",
input_type = "text",
buttons = {
{
{
text = _("Cancel"),
id = "close",
callback = function()
UIManager:close(self.dictionary_lookup_dialog)
end,
},
{
text = _("Search dictionary"),
is_enter_default = true,
callback = function()
if self.dictionary_lookup_dialog:getInputText() == "" then return end
UIManager:close(self.dictionary_lookup_dialog)
-- Trust that input text does not need any cleaning (allows querying for "-suffix")
self:onLookupWord(self.dictionary_lookup_dialog:getInputText(), true)
end,
},
}
},
buttons = buttons,
}
UIManager:show(self.dictionary_lookup_dialog)
self.dictionary_lookup_dialog:onShowKeyboard()
@@ -1459,4 +1527,64 @@ The current default (★) is enabled.]])
})
end
function ReaderDictionary:buildPreset()
local preset = { enabled_dict_names = {} } -- Only store the names of enabled dictionaries.
for _, name in ipairs(self.enabled_dict_names) do
preset.enabled_dict_names[name] = true
end
return preset
end
function ReaderDictionary:loadPreset(preset, skip_notification)
if not preset.enabled_dict_names then return end
-- build a list of currently available dictionary names for validation
local available_dict_names = {}
for _, ifo in ipairs(available_ifos) do
available_dict_names[ifo.name] = true
end
-- Only enable dictionaries from the preset that are still available, and re-build self.dicts_disabled
-- to make sure dicts added after the creation of the preset, are disabled as well.
local dicts_disabled, valid_enabled_names = {}, {}
for _, ifo in ipairs(available_ifos) do
if preset.enabled_dict_names[ifo.name] then
table.insert(valid_enabled_names, ifo.name)
else
dicts_disabled[ifo.file] = true
end
end
-- update both settings and save
self.dicts_disabled = dicts_disabled
self.enabled_dict_names = valid_enabled_names
G_reader_settings:saveSetting("dicts_disabled", self.dicts_disabled)
self:onSaveSettings()
self:updateSdcvDictNamesOptions()
-- Show a message if any dictionaries from the preset are missing.
if not skip_notification and util.tableSize(preset.enabled_dict_names) > #valid_enabled_names then
local missing_dicts = {}
for preset_name, _ in pairs(preset.enabled_dict_names) do
if not available_dict_names[preset_name] then
table.insert(missing_dicts, preset_name)
end
end
UIManager:show(InfoMessage:new{
text = _("Some dictionaries from this preset have been deleted or are no longer available:") .. "\n\n" .. table.concat(missing_dicts, "\n"),
})
end
end
function ReaderDictionary:onCycleDictionaryPresets()
return Presets.cycleThroughPresets(self.preset_obj, true)
end
function ReaderDictionary:onLoadDictionaryPreset(preset_name)
return Presets.onLoadPreset(self.preset_obj, preset_name, true)
end
function ReaderDictionary.getPresets() -- for Dispatcher
local dict_config = {
presets = G_reader_settings:readSetting("dict_presets", {})
}
return Presets.getPresets(dict_config)
end
return ReaderDictionary

View File

@@ -9,12 +9,10 @@ local FrameContainer = require("ui/widget/container/framecontainer")
local Geom = require("ui/geometry")
local HorizontalGroup = require("ui/widget/horizontalgroup")
local HorizontalSpan = require("ui/widget/horizontalspan")
local InfoMessage = require("ui/widget/infomessage")
local InputDialog = require("ui/widget/inputdialog")
local LeftContainer = require("ui/widget/container/leftcontainer")
local LineWidget = require("ui/widget/linewidget")
local MultiConfirmBox = require("ui/widget/multiconfirmbox")
local MultiInputDialog = require("ui/widget/multiinputdialog")
local Presets = require("ui/presets")
local ProgressWidget = require("ui/widget/progresswidget")
local RightContainer = require("ui/widget/container/rightcontainer")
local Size = require("ui/size")
@@ -25,7 +23,6 @@ local VerticalGroup = require("ui/widget/verticalgroup")
local VerticalSpan = require("ui/widget/verticalspan")
local WidgetContainer = require("ui/widget/container/widgetcontainer")
local datetime = require("datetime")
local ffiUtil = require("ffi/util")
local logger = require("logger")
local util = require("util")
local T = require("ffi/util").template
@@ -665,6 +662,13 @@ function ReaderFooter:init()
self.custom_text = G_reader_settings:readSetting("reader_footer_custom_text", "KOReader")
self.custom_text_repetitions =
tonumber(G_reader_settings:readSetting("reader_footer_custom_text_repetitions", "1"))
self.preset_obj = {
presets = G_reader_settings:readSetting("footer_presets", {}),
dispatcher_name = "load_footer_preset",
buildPreset = function() return self:buildPreset() end,
loadPreset = function(preset) self:loadPreset(preset) end,
}
end
function ReaderFooter:set_custom_text(touchmenu_instance)
@@ -1710,7 +1714,7 @@ With this feature enabled, the current page is factored in, resulting in the cou
text = _("Status bar presets"),
separator = true,
sub_item_table_func = function()
return self:genPresetMenuItemTable()
return Presets.genPresetMenuItemTable(self.preset_obj, nil, nil)
end,
})
table.insert(sub_items, {
@@ -1930,91 +1934,6 @@ function ReaderFooter:genAlignmentMenuItems(value)
}
end
function ReaderFooter:genPresetMenuItemTable()
local footer_presets = G_reader_settings:readSetting("footer_presets", {})
local items = {
{
text = _("Create new preset from current settings"),
keep_menu_open = true,
callback = function(touchmenu_instance)
self:createPresetFromCurrentSettings(touchmenu_instance)
end,
separator = true,
},
}
for preset_name in ffiUtil.orderedPairs(footer_presets) do
table.insert(items, {
text = preset_name,
keep_menu_open = true,
callback = function()
self:loadPreset(footer_presets[preset_name])
end,
hold_callback = function(touchmenu_instance, item)
UIManager:show(MultiConfirmBox:new{
text = T(_("What would you like to do with preset '%1'?"), preset_name),
choice1_text = _("Delete"),
choice1_callback = function()
footer_presets[preset_name] = nil
UIManager:broadcastEvent(Event:new("DispatcherActionValueChanged",
{ name = "load_footer_preset", old_value = preset_name, new_value = nil }))
table.remove(touchmenu_instance.item_table, item.idx)
touchmenu_instance:updateItems()
end,
choice2_text = _("Update"),
choice2_callback = function()
footer_presets[preset_name] = self:buildPreset()
UIManager:show(InfoMessage:new{
text = T(_("Preset '%1' was updated with current settings"), preset_name),
timeout = 2,
})
end,
})
end,
})
end
return items
end
function ReaderFooter:createPresetFromCurrentSettings(touchmenu_instance)
local input_dialog
input_dialog = InputDialog:new{
title = _("Enter preset name"),
buttons = {
{
{
text = _("Cancel"),
id = "close",
callback = function()
UIManager:close(input_dialog)
end,
},
{
text = _("Save"),
is_enter_default = true,
callback = function()
local preset_name = input_dialog:getInputText()
if preset_name == "" or preset_name:match("^%s*$") then return end
local footer_presets = G_reader_settings:readSetting("footer_presets")
if footer_presets[preset_name] then
UIManager:show(InfoMessage:new{
text = T(_("A preset named '%1' already exists. Please choose a different name."), preset_name),
timeout = 2,
})
else
footer_presets[preset_name] = self:buildPreset()
UIManager:close(input_dialog)
touchmenu_instance.item_table = self:genPresetMenuItemTable()
touchmenu_instance:updateItems()
end
end,
},
},
},
}
UIManager:show(input_dialog)
input_dialog:onShowKeyboard()
end
function ReaderFooter:buildPreset()
return {
footer = util.tableDeepCopy(self.settings),
@@ -2048,25 +1967,14 @@ function ReaderFooter:loadPreset(preset)
end
function ReaderFooter:onLoadFooterPreset(preset_name)
local footer_presets = G_reader_settings:readSetting("footer_presets")
if footer_presets and footer_presets[preset_name] then
self:loadPreset(footer_presets[preset_name])
end
return true
return Presets.onLoadPreset(self.preset_obj, preset_name, true)
end
function ReaderFooter.getPresets() -- for Dispatcher
local footer_presets = G_reader_settings:readSetting("footer_presets")
local actions = {}
if footer_presets and next(footer_presets) then
for preset_name in pairs(footer_presets) do
table.insert(actions, preset_name)
end
if #actions > 1 then
table.sort(actions)
end
end
return actions, actions
local footer_config = {
presets = G_reader_settings:readSetting("footer_presets", {})
}
return Presets.getPresets(footer_config)
end
function ReaderFooter:addAdditionalFooterContent(content_func)

View File

@@ -260,32 +260,40 @@ You can choose an existing folder, or use a default folder named "Wikipedia" in
separator = true,
},
{
text = _("Enable Wikipedia history"),
text = _("Wikipedia lookup history"),
checked_func = function()
return not self.disable_history
end,
callback = function()
self.disable_history = not self.disable_history
G_reader_settings:saveSetting("wikipedia_disable_history", self.disable_history)
end,
},
{
text = _("Clean Wikipedia history"),
enabled_func = function()
return wikipedia_history:has("wikipedia_history")
end,
keep_menu_open = true,
callback = function(touchmenu_instance)
UIManager:show(ConfirmBox:new{
text = _("Clean Wikipedia history?"),
ok_text = _("Clean"),
ok_callback = function()
-- empty data table to replace current one
wikipedia_history:reset{}
touchmenu_instance:updateItems()
sub_item_table = {
{
text = _("Enable Wikipedia history"),
checked_func = function()
return not self.disable_history
end,
})
end,
callback = function()
self.disable_history = not self.disable_history
G_reader_settings:saveSetting("wikipedia_disable_history", self.disable_history)
end,
},
{
text = _("Clean Wikipedia history"),
enabled_func = function()
return wikipedia_history:has("wikipedia_history")
end,
keep_menu_open = true,
callback = function(touchmenu_instance)
UIManager:show(ConfirmBox:new{
text = _("Clean Wikipedia history?"),
ok_text = _("Clean"),
ok_callback = function()
-- empty data table to replace current one
wikipedia_history:reset{}
touchmenu_instance:updateItems()
end,
})
end,
},
},
separator = true,
},
{ -- setting used in wikipedia.lua

View File

@@ -34,6 +34,7 @@ local Device = require("device")
local Event = require("ui/event")
local FileManager = require("apps/filemanager/filemanager")
local Notification = require("ui/widget/notification")
local ReaderDictionary = require("apps/reader/modules/readerdictionary")
local ReaderFooter = require("apps/reader/modules/readerfooter")
local ReaderHighlight = require("apps/reader/modules/readerhighlight")
local ReaderZooming = require("apps/reader/modules/readerzooming")
@@ -60,6 +61,8 @@ local settingsList = {
collections_search = {category="none", event="ShowCollectionsSearchDialog", title=_("Collections search"), general=true, separator=true},
----
dictionary_lookup = {category="none", event="ShowDictionaryLookup", title=_("Dictionary lookup"), general=true},
load_dictionary_preset = {category="string", event="LoadDictionaryPreset", title=_("Load dictionary preset"), args_func=ReaderDictionary.getPresets, general=true},
cycle_dictionary_preset = {category="none", event="CycleDictionaryPresets", title=_("Cycle through dictionary presets"), general=true,},
wikipedia_lookup = {category="none", event="ShowWikipediaLookup", title=_("Wikipedia lookup"), general=true, separator=true},
----
show_menu = {category="none", event="ShowMenu", title=_("Show menu"), general=true},
@@ -300,6 +303,8 @@ local dispatcher_menu_order = {
"collections_search",
----
"dictionary_lookup",
"load_dictionary_preset",
"cycle_dictionary_preset",
"wikipedia_lookup",
----
"show_menu",

325
frontend/ui/presets.lua Normal file
View File

@@ -0,0 +1,325 @@
--[[--
This module provides a unified interface for managing presets across different KOReader modules.
It handles creation, loading, updating, and deletion of presets, as well as menu generation.
Usage:
local Presets = require("ui/presets")
-- 1. In your module's init() method, set up a preset object:
self.preset_obj = {
presets = G_reader_settings:readSetting("my_module_presets", {}), -- or custom storage
cycle_index = G_reader_settings:readSetting("my_module_presets_cycle_index"), -- optional, only needed if cycling through presets
dispatcher_name = "load_my_module_preset", -- must match dispatcher.lua entry
saveCycleIndex = function(this) -- Save cycle index to persistent storage
G_reader_settings:saveSetting("my_module_presets_cycle_index", this.cycle_index)
end,
buildPreset = function() return self:buildPreset() end, -- Closure to build a preset from current state
loadPreset = function(preset) self:loadPreset(preset) end, -- Closure to apply a preset to the module
}
-- 2. Implement required methods in your module:
function MyModule:buildPreset()
return {
-- Return a table with the settings you want to save in the preset
setting1 = self.setting1,
setting2 = self.setting2,
enabled_features = self.enabled_features,
}
end
function MyModule:loadPreset(preset)
-- Apply the preset settings to your module
self.setting1 = preset.setting1
self.setting2 = preset.setting2
self.enabled_features = preset.enabled_features
-- Update UI or perform other necessary changes
self:refresh()
end
-- 3. Create menu items for presets: (Alternatively, you could call Presets.genPresetMenuItemTable directly from touchmenu_instance)
function MyModule:genPresetMenuItemTable(touchmenu_instance)
return Presets.genPresetMenuItemTable(
self.preset_obj, -- preset object
_("Create new preset from current settings"), -- optional: custom text for UI menu
function() return self:hasValidSettings() end, -- optional: function to enable/disable creating presets
)
end
-- 4. Load a preset by name (for dispatcher/event handling):
function MyModule:onLoadMyModulePreset(preset_name)
return Presets.onLoadPreset(
self.preset_obj,
preset_name,
true -- show notification
)
end
-- 5. Cycle through presets (for dispatcher/event handling):
function MyModule:onCycleMyModulePresets()
return Presets.cycleThroughPresets(
self.preset_obj,
true -- show notification
)
end
-- 6. Get list of available presets (for dispatcher):
function MyModule.getPresets() -- Note: This is a static method on MyModule
local config = {
presets = G_reader_settings:readSetting("my_module_presets", {})
}
return Presets.getPresets(config)
end
-- 7. Add to dispatcher.lua:
load_my_module_preset = {
category = "string",
event = "LoadMyModulePreset",
title = _("Load my module preset"),
args_func = MyModule.getPresets,
reader = true
},
cycle_my_module_preset = {
category = "none",
event = "CycleMyModulePresets",
title = _("Cycle through my module presets"),
reader = true
},
Required preset_obj fields:
- presets: table containing saved presets
- cycle_index: current index for cycling through presets (optional, defaults to 0)
- dispatcher_name: string matching the dispatcher action name (for dispatcher integration)
- saveCycleIndex(this): function to save cycle index (optional, only needed if cycling is used)
Required module methods:
- buildPreset(): returns a table with the current settings to save as a preset
- loadPreset(preset): applies the settings from the preset table to the module
The preset system handles:
- Creating, updating, deleting, and renaming presets through UI dialogs
- Generating menu items with hold actions for preset management
- Saving/loading presets to/from G_reader_settings (or custom storage)
- Cycling through presets with wrap-around
- User notifications when presets are loaded/updated/created
- Integration with Dispatcher for gesture/hotkey/profile support
- Broadcasting events to update dispatcher when presets change
- Input validation and duplicate name prevention
--]]
local ConfirmBox = require("ui/widget/confirmbox")
local Event = require("ui/event")
local InfoMessage = require("ui/widget/infomessage")
local InputDialog = require("ui/widget/inputdialog")
local Notification = require("ui/widget/notification")
local UIManager = require("ui/uimanager")
local ffiUtil = require("ffi/util")
local T = require("ffi/util").template
local _ = require("gettext")
local Presets = {}
function Presets.editPresetName(options, preset_obj, on_success_callback)
local input_dialog
input_dialog = InputDialog:new{
title = options.title or _("Enter preset name"),
input = options.initial_value or "",
buttons = {
{
{
text = _("Cancel"),
id = "close",
callback = function()
UIManager:close(input_dialog)
end,
},
{
text = options.confirm_button_text or _("Create"),
is_enter_default = true,
callback = function()
local entered_preset_name = input_dialog:getInputText()
if entered_preset_name == "" or entered_preset_name:match("^%s*$") then
UIManager:show(InfoMessage:new{
text = _("Invalid preset name. Please choose a different name."),
timeout = 2,
})
return false
end
if options.initial_value and entered_preset_name == options.initial_value then
UIManager:close(input_dialog)
return false
end
if preset_obj.presets[entered_preset_name] then
UIManager:show(InfoMessage:new{
text = T(_("A preset named '%1' already exists. Please choose a different name."), entered_preset_name),
timeout = 2,
})
return false
end
-- If all validation passes, call the success callback
on_success_callback(entered_preset_name)
UIManager:close(input_dialog)
end,
},
},
},
}
UIManager:show(input_dialog)
input_dialog:onShowKeyboard()
end
function Presets.genPresetMenuItemTable(preset_obj, text, enabled_func)
local presets = preset_obj.presets
local items = {
{
text = text or _("Create new preset from current settings"),
keep_menu_open = true,
enabled_func = enabled_func,
callback = function(touchmenu_instance)
Presets.editPresetName({}, preset_obj,
function(entered_preset_name)
local preset_data = preset_obj.buildPreset()
preset_obj.presets[entered_preset_name] = preset_data
touchmenu_instance.item_table = Presets.genPresetMenuItemTable(preset_obj)
touchmenu_instance:updateItems()
end
)
end,
separator = true,
},
}
for preset_name in ffiUtil.orderedPairs(presets) do
table.insert(items, {
text = preset_name,
keep_menu_open = true,
callback = function()
preset_obj.loadPreset(presets[preset_name])
-- There's no guarantee that it'll be obvious to the user that the preset was loaded so, we show a notification.
UIManager:show(InfoMessage:new{
text = T(_("Preset '%1' loaded successfully."), preset_name),
timeout = 2,
})
end,
hold_callback = function(touchmenu_instance, item)
UIManager:show(ConfirmBox:new{
text = T(_("What would you like to do with preset '%1'?"), preset_name),
icon = "notice-question",
ok_text = _("Update"),
ok_callback = function()
UIManager:show(ConfirmBox:new{
text = T(_("Are you sure you want to overwrite preset '%1' with current settings?"), preset_name),
ok_callback = function()
presets[preset_name] = preset_obj.buildPreset()
UIManager:show(InfoMessage:new{
text = T(_("Preset '%1' was updated with current settings"), preset_name),
timeout = 2,
})
end,
})
end,
other_buttons_first = true,
other_buttons = {
{
{
text = _("Delete"),
callback = function()
UIManager:show(ConfirmBox:new{
text = T(_("Are you sure you want to delete preset '%1'?"), preset_name),
ok_text = _("Delete"),
ok_callback = function()
presets[preset_name] = nil
local action_key = preset_obj.dispatcher_name
if action_key then
UIManager:broadcastEvent(Event:new("DispatcherActionValueChanged", {
name = action_key,
old_value = preset_name,
new_value = nil -- delete the action
}))
end
table.remove(touchmenu_instance.item_table, item.idx)
touchmenu_instance:updateItems()
end,
})
end,
},
{
text = _("Rename"),
callback = function()
Presets.editPresetName({
title = _("Enter new preset name"),
initial_value = preset_name,
confirm_button_text = _("Rename"),
}, preset_obj,
function(new_name)
presets[new_name] = presets[preset_name]
presets[preset_name] = nil
local action_key = preset_obj.dispatcher_name
if action_key then
UIManager:broadcastEvent(Event:new("DispatcherActionValueChanged", {
name = action_key,
old_value = preset_name,
new_value = new_name
}))
end
touchmenu_instance.item_table = Presets.genPresetMenuItemTable(preset_obj)
touchmenu_instance:updateItems()
end) -- editPresetName
end, -- rename callback
},
},
}, -- end of other_buttons
}) -- end of ConfirmBox
end, -- hold_callback
}) -- end of table.insert
end -- for each preset
return items
end
function Presets.onLoadPreset(preset_obj, preset_name, show_notification)
local presets = preset_obj.presets
if presets and presets[preset_name] then
preset_obj.loadPreset(presets[preset_name])
if show_notification then
Notification:notify(T(_("Preset '%1' was loaded"), preset_name))
end
end
return true
end
function Presets.cycleThroughPresets(preset_obj, show_notification)
local preset_names = Presets.getPresets(preset_obj)
if #preset_names == 0 then
Notification:notify(_("No presets available"), Notification.SOURCE_ALWAYS_SHOW)
return true -- we *must* return true here to prevent further event propagation, i.e multiple notifications
end
-- Get and increment index, wrap around if needed
local index = (preset_obj.cycle_index or 0) + 1
if index > #preset_names then
index = 1
end
local next_preset_name = preset_names[index]
preset_obj.loadPreset(preset_obj.presets[next_preset_name])
preset_obj.cycle_index = index
preset_obj:saveCycleIndex()
if show_notification then
Notification:notify(T(_("Loaded preset: %1"), next_preset_name))
end
return true
end
function Presets.getPresets(preset_obj)
local presets = preset_obj.presets
local actions = {}
if presets and next(presets) then
for preset_name in pairs(presets) do
table.insert(actions, preset_name)
end
if #actions > 1 then
table.sort(actions)
end
end
return actions, actions
end
return Presets

View File

@@ -21,6 +21,7 @@ local Size = require("ui/size")
local TextWidget = require("ui/widget/textwidget")
local TitleBar = require("ui/widget/titlebar")
local Translator = require("ui/translator")
local Presets = require("ui/presets")
local UIManager = require("ui/uimanager")
local VerticalGroup = require("ui/widget/verticalgroup")
local VerticalSpan = require("ui/widget/verticalspan")
@@ -1404,57 +1405,96 @@ function DictQuickLookup:onForwardingPanRelease(arg, ges)
end
function DictQuickLookup:onLookupInputWord(hint)
local buttons = {
{
{
text = _("Translate"),
callback = function()
local text = self.input_dialog:getInputText()
if text ~= "" then
UIManager:close(self.input_dialog)
Translator:showTranslation(text, true)
end
end,
},
{
text = _("Search Wikipedia"),
is_enter_default = self.is_wiki,
callback = function()
local text = self.input_dialog:getInputText()
if text ~= "" then
UIManager:close(self.input_dialog)
self.is_wiki = true
self:lookupWikipedia(false, text, true)
end
end,
},
},
{
{
text = _("Cancel"),
id = "close",
callback = function()
UIManager:close(self.input_dialog)
end,
},
{
text = _("Search dictionary"),
is_enter_default = not self.is_wiki,
callback = function()
local text = self.input_dialog:getInputText()
if text ~= "" then
UIManager:close(self.input_dialog)
self.is_wiki = false
self.ui:handleEvent(Event:new("LookupWord", text, true))
end
end,
},
},
}
local preset_names = Presets.getPresets(self.ui.dictionary.preset_obj)
if preset_names and #preset_names > 0 then
table.insert(buttons, 2, {
{
text = _("Search with preset"),
callback = function()
local text = self.input_dialog:getInputText()
if text == "" or text:match("^%s*$") then return end
local current_dict_state = self.ui.dictionary:buildPreset()
local button_dialog, dialog_buttons = nil, {} -- CI won't like it if we call it buttons :( so dialog_buttons
for _, preset_name in ipairs(preset_names) do
table.insert(dialog_buttons, {
{
align = "left",
text = preset_name,
callback = function()
self.ui.dictionary:loadPreset(self.ui.dictionary.preset_obj.presets[preset_name], true)
UIManager:close(button_dialog)
UIManager:close(self.input_dialog)
self.ui:handleEvent(Event:new("LookupWord", text, true, nil, nil, nil,
function()
-- Restore original preset _after_ lookup is complete
self.ui.dictionary:loadPreset(current_dict_state, true)
end
))
end
}
})
end
button_dialog = ButtonDialog:new{
buttons = dialog_buttons,
shrink_unneeded_width = true,
}
UIManager:show(button_dialog)
end,
}
})
end
self.input_dialog = InputDialog:new{
title = _("Enter a word or phrase to look up"),
input = hint,
input_hint = hint,
buttons = {
{
{
text = _("Translate"),
callback = function()
local text = self.input_dialog:getInputText()
if text ~= "" then
UIManager:close(self.input_dialog)
Translator:showTranslation(text, true)
end
end,
},
{
text = _("Search Wikipedia"),
is_enter_default = self.is_wiki,
callback = function()
local text = self.input_dialog:getInputText()
if text ~= "" then
UIManager:close(self.input_dialog)
self.is_wiki = true
self:lookupWikipedia(false, text, true)
end
end,
},
},
{
{
text = _("Cancel"),
id = "close",
callback = function()
UIManager:close(self.input_dialog)
end,
},
{
text = _("Search dictionary"),
is_enter_default = not self.is_wiki,
callback = function()
local text = self.input_dialog:getInputText()
if text ~= "" then
UIManager:close(self.input_dialog)
self.is_wiki = false
self.ui:handleEvent(Event:new("LookupWord", text, true))
end
end,
},
},
},
buttons = buttons,
}
UIManager:show(self.input_dialog)
self.input_dialog:onShowKeyboard()