Files
koreader-mirror/frontend/dispatcher.lua
2025-12-02 16:01:18 +01:00

1263 lines
61 KiB
Lua

--[[--
This module is responsible for dispatching events.
To add a new action an entry must be added to `settingsList` & `dispatcher_menu_order`
This can also be done at runtime via @{registerAction}().
`settingsList` contains the list of dispatchable settings.
Each setting contains:
* category: one of:
* none: a direct event call
* arg: a event that expects a gesture object or an argument
* absolutenumber: event that sets a number
* incrementalnumber: event that increments a number & accepts a gesture object
* string: event with a list of arguments to chose from
* configurable: like string but instead of an event it updates the configurable (used by kopt)
* event: what to call.
* title: for use in ui.
* section: under which menu to display (currently: general, device, screen, filemanager, reader, rolling, paging)
and optionally
* min/max: for number
* step: for number
* default
* args: allowed values for string.
* toggle: display name for args
* separator: put a separator after in the menu list
* configurable: can be parsed from cre/kopt and used to set `document.configurable`. Should not be set manually
--]]--
local CreOptions = require("ui/data/creoptions")
local KoptOptions = require("ui/data/koptoptions")
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 ReaderTypography = require("apps/reader/modules/readertypography")
local ReaderZooming = require("apps/reader/modules/readerzooming")
local Screen = Device.screen
local UIManager = require("ui/uimanager")
local util = require("util")
local _ = require("gettext")
local NC_ = _.npgettext
local T = require("ffi/util").template
local Dispatcher = {
initialized = false,
}
-- See above for description.
local settingsList = {
-- General
gesture_overview = {category="none", event="ShowGestureOverview", title=_("Gesture overview"), general=true},
filemanager = {category="none", event="Home", title=_("File browser"), general=true},
open_previous_document = {category="none", event="OpenLastDoc", title=_("Open previous document"), general=true},
history = {category="none", event="ShowHist", title=_("History"), general=true},
history_search = {category="none", event="SearchHistory", title=_("History search"), general=true},
favorites = {category="none", event="ShowColl", title=_("Favorites"), general=true},
collections = {category="none", event="ShowCollList", title=_("Collections"), general=true},
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},
menu_search = {category="none", event="MenuSearch", title=_("Menu search"), general=true},
open_next_document_in_folder = {category="none", event="OpenNextOrPreviousFileInFolder", title=_("Open next file in last book folder"), general=true},
open_previous_document_in_folder = {category="none", event="OpenNextOrPreviousFileInFolder", arg=true, title=_("Open previous file in last book folder"), general=true},
notebook_file = {category="none", event="ShowNotebookFile", title=_("Notebook file"), general=true},
screenshot = {category="none", event="Screenshot", title=_("Screenshot"), general=true, separator=true},
----
-- Device
exit_screensaver = {category="none", event="ExitScreensaver", title=_("Exit sleep screen"), device=true, condition=Device:isTouchDevice()},
start_usbms = {category="none", event="RequestUSBMS", title=_("Start USB storage"), device=true, condition=Device:canToggleMassStorage()},
suspend = {category="none", event="RequestSuspend", title=_("Sleep"), device=true, condition=Device:canSuspend()},
restart = {category="none", event="Restart", title=_("Restart KOReader"), device=true, condition=Device:canRestart()},
reboot = {category="none", event="RequestReboot", title=_("Reboot the device"), device=true, condition=Device:canReboot()},
poweroff = {category="none", event="RequestPowerOff", title=_("Power off"), device=true, condition=Device:canPowerOff()},
exit = {category="none", event="Exit", title=_("Exit KOReader"), device=true, separator=true},
----
toggle_hold_corners = {category="none", event="IgnoreHoldCorners", title=_("Toggle long-press on corners"), device=true, condition=Device:isTouchDevice()},
touch_input_on = {category="none", event="IgnoreTouchInput", arg=false, title=_("Enable touch input"), device=true, condition=Device:isTouchDevice()},
touch_input_off = {category="none", event="IgnoreTouchInput", arg=true, title=_("Disable touch input"), device=true, condition=Device:isTouchDevice()},
toggle_touch_input = {category="none", event="IgnoreTouchInput", title=_("Toggle touch input"), device=true, separator=true, condition=Device:isTouchDevice()},
----
swap_left_page_turn_buttons = {category="none", event="SwapPageTurnButtons", arg="left", title=_("Invert left-side page-turn buttons"), device=true, condition= Device:hasDPad() and Device:useDPadAsActionKeys()},
swap_right_page_turn_buttons = {category="none", event="SwapPageTurnButtons", arg="right", title=_("Invert right-side page-turn buttons"), device=true, condition= Device:hasDPad() and Device:useDPadAsActionKeys()},
swap_page_turn_buttons = {category="none", event="SwapPageTurnButtons", title=_("Invert page-turn buttons"), device=true, condition=Device:hasKeys()},
set_page_turn_buttons = {category="string", event="SetPageTurnButtonDirection", title=_("Set page-turn button inversion"), device=true, condition=Device:hasKeys(), args = {true, false}, toggle = { _("on"), _("off")}, separator=true},
----
toggle_key_repeat = {category="none", event="ToggleKeyRepeat", title=_("Toggle key repeat"), device=true, condition=Device:hasKeys() and Device:canKeyRepeat(), separator=true},
toggle_gsensor = {category="none", event="ToggleGSensor", title=_("Toggle accelerometer"), device=true, condition=Device:hasGSensor()},
temp_gsensor_on = {category="none", event="TempGSensorOn", title=_("Enable accelerometer for 5 seconds"), device=true, condition=Device:hasGSensor()},
lock_gsensor = {category="none", event="LockGSensor", title=_("Toggle lock auto rotation to current orientation"), device=true, condition=Device:hasGSensor()},
set_lock_gsensor = {category="string", event="SetLockGSensor", title=_("Set lock auto rotation to current orientation"), device=true, condition=Device:hasGSensor(), args = {true, false}, toggle = { _("true"), _("false")}},
rotation_mode = {category="string", device=true}, -- title=_("Rotation"), parsed from CreOptions
toggle_rotation = {category="none", event="SwapRotation", title=_("Toggle orientation"), device=true},
invert_rotation = {category="none", event="InvertRotation", title=_("Invert rotation"), device=true},
iterate_rotation = {category="none", event="IterateRotation", title=_("Rotate by 90° CW"), device=true},
iterate_rotation_ccw = {category="none", event="IterateRotation", arg=true, title=_("Rotate by 90° CCW"), device=true, separator=true},
----
wifi_on = {category="none", event="InfoWifiOn", title=_("Turn on Wi-Fi"), device=true, condition=Device:hasWifiToggle()},
wifi_off = {category="none", event="InfoWifiOff", title=_("Turn off Wi-Fi"), device=true, condition=Device:hasWifiToggle()},
toggle_wifi = {category="none", event="ToggleWifi", title=_("Toggle Wi-Fi"), device=true, condition=Device:hasWifiToggle()},
toggle_fullscreen = {category="none", event="ToggleFullscreen", title=_("Toggle Fullscreen"), device=true, condition=not Device:isAlwaysFullscreen()},
show_network_info = {category="none", event="ShowNetworkInfo", title=_("Show network info"), device=true, separator=true},
----
-- Screen and lights
show_frontlight_dialog = {category="none", event="ShowFlDialog", title=_("Show frontlight dialog"), screen=true, condition=Device:hasFrontlight()},
toggle_frontlight = {category="none", event="ToggleFrontlight", title=_("Toggle frontlight"), screen=true, condition=Device:hasFrontlight()},
set_frontlight = {category="absolutenumber", event="SetFlIntensity", min=0, max=Device:getPowerDevice().fl_max, title=_("Set frontlight brightness"), screen=true, condition=Device:hasFrontlight()},
increase_frontlight = {category="incrementalnumber", event="IncreaseFlIntensity", min=1, max=Device:getPowerDevice().fl_max, title=_("Increase frontlight brightness"), screen=true, condition=Device:hasFrontlight()},
decrease_frontlight = {category="incrementalnumber", event="DecreaseFlIntensity", min=1, max=Device:getPowerDevice().fl_max, title=_("Decrease frontlight brightness"), screen=true, condition=Device:hasFrontlight()},
set_frontlight_warmth = {category="absolutenumber", event="SetFlWarmth", min=0, max=100, title=_("Set frontlight warmth"), screen=true, condition=Device:hasNaturalLight()},
increase_frontlight_warmth = {category="incrementalnumber", event="IncreaseFlWarmth", min=1, max=Device:getPowerDevice().fl_warmth_max, title=_("Increase frontlight warmth"), screen=true, condition=Device:hasNaturalLight()},
decrease_frontlight_warmth = {category="incrementalnumber", event="DecreaseFlWarmth", min=1, max=Device:getPowerDevice().fl_warmth_max, title=_("Decrease frontlight warmth"), screen=true, condition=Device:hasNaturalLight(), separator=true},
night_mode = {category="none", event="ToggleNightMode", title=_("Toggle night mode"), screen=true},
set_night_mode = {category="string", event="SetNightMode", title=_("Set night mode"), screen=true, args={true, false}, toggle={_("on"), _("off")}, separator=true},
----
full_refresh = {category="none", event="FullRefresh", title=_("Full screen refresh"), screen=true},
set_refresh_rate = {category="absolutenumber", event="SetBothRefreshRates", min=-1, max=200, title=_("Full refresh rate (always)"), screen=true, condition=Device:hasEinkScreen()},
set_day_refresh_rate = {category="absolutenumber", event="SetDayRefreshRate", min=-1, max=200, title=_("Full refresh rate (not in night mode)"), screen=true, condition=Device:hasEinkScreen()},
set_night_refresh_rate = {category="absolutenumber", event="SetNightRefreshRate", min=-1, max=200, title=_("Full refresh rate (in night mode)"), screen=true, condition=Device:hasEinkScreen()},
set_flash_on_chapter_boundaries = {category="string", event="SetFlashOnChapterBoundaries", title=_("Always flash on chapter boundaries"), screen=true, condition=Device:hasEinkScreen(), args={true, false}, toggle={_("on"), _("off")}},
toggle_flash_on_chapter_boundaries = {category="none", event="ToggleFlashOnChapterBoundaries", title=_("Toggle flashing on chapter boundaries"), screen=true, condition=Device:hasEinkScreen()},
set_no_flash_on_second_chapter_page = {category="string", event="SetNoFlashOnSecondChapterPage", title=_("Never flash on chapter's 2nd page"), screen=true, condition=Device:hasEinkScreen(), args={true, false}, toggle={_("on"), _("off")}},
toggle_no_flash_on_second_chapter_page = {category="none", event="ToggleNoFlashOnSecondChapterPage", title=_("Toggle flashing on chapter's 2nd page"), screen=true, condition=Device:hasEinkScreen()},
set_flash_on_pages_with_images = {category="string", event="SetFlashOnPagesWithImages", title=_("Always flash on pages with images"), screen=true, condition=Device:hasEinkScreen(), args={true, false}, toggle={_("on"), _("off")}},
toggle_flash_on_pages_with_images = {category="none", event="ToggleFlashOnPagesWithImages", title=_("Toggle flashing on pages with images"), screen=true, condition=Device:hasEinkScreen(), separator=true},
----
-- File browser
set_display_mode = {category="string", event="SetDisplayMode", title=_("Set display mode"), args_func=FileManager.getDisplayModeActions, filemanager=true},
set_sort_by = {category="string", event="SetSortBy", title=_("Sort by"), args_func=FileManager.getSortByActions, filemanager=true},
set_reverse_sorting = {category="string", event="SetReverseSorting", title=_("Reverse sorting"), args={true, false}, toggle={_("on"), _("off")}, filemanager=true},
set_mixed_sorting = {category="string", event="SetMixedSorting", title=_("Folders and files mixed"), args={true, false}, toggle={_("on"), _("off")}, filemanager=true, separator=true},
----
show_plus_menu = {category="none", event="ShowPlusMenu", title=_("Show plus menu"), filemanager=true},
toggle_select_mode = {category="none", event="ToggleSelectMode", title=_("Toggle select mode"), filemanager=true},
refresh_content = {category="none", event="RefreshContent", title=_("Refresh content"), filemanager=true},
folder_shortcuts = {category="none", event="ShowFolderShortcutsDialog", title=_("Folder shortcuts"), filemanager=true},
file_search = {category="none", event="ShowFileSearch", title=_("File search"), filemanager=true},
file_search_results = {category="none", event="ShowSearchResults", title=_("Last file search results"), filemanager=true},
----
folder_up = {category="none", event="FolderUp", title=_("Folder up"), filemanager=true},
fm_go_to = {category="none", event="ShowGotoDialog", title=_("Go to page"), filemanager=true},
fm_back = {category="none", event="Back", title=_("Back"), filemanager=true, separator=true},
----
cloud_storage = {category="none", event="ShowCloudStorage", title=_("Cloud storage"), filemanager=true},
-- Reader
show_config_menu = {category="none", event="ShowConfigMenu", title=_("Show bottom menu"), reader=true},
toggle_status_bar = {category="none", event="ToggleFooterMode", title=_("Toggle status bar"), reader=true},
toggle_chapter_progress_bar = {category="none", event="ToggleChapterProgressBar", title=_("Toggle chapter progress bar"), reader=true},
load_footer_preset = {category="string", event="LoadFooterPreset", title=_("Load status bar preset"), args_func=ReaderFooter.getPresets, reader=true, separator=true},
----
prev_chapter = {category="none", event="GotoPrevChapter", title=_("Previous chapter"), reader=true},
next_chapter = {category="none", event="GotoNextChapter", title=_("Next chapter"), reader=true},
first_page = {category="none", event="GoToBeginning", title=_("First page"), reader=true},
last_page = {category="none", event="GoToEnd", title=_("Last page"), reader=true},
random_page = {category="none", event="GoToRandomPage", title=_("Random page"), reader=true},
page_jmp = {category="absolutenumber", event="GotoViewRel", min=-100, max=100, title=_("Turn pages"), reader=true},
go_to = {category="none", event="ShowGotoDialog", title=_("Go to page"), reader=true},
skim = {category="none", event="ShowSkimtoDialog", title=_("Skim document"), reader=true},
pin_current_page = {category="none", event="PinPage", title=_("Pin current page"), reader=true},
go_to_pinned_page = {category="none", event="GoToPinnedPage", title=_("Go to pinned page"), reader=true, separator=true},
----
prev_bookmark = {category="none", event="GotoPreviousBookmarkFromPage", title=_("Previous bookmark"), reader=true},
next_bookmark = {category="none", event="GotoNextBookmarkFromPage", title=_("Next bookmark"), reader=true},
first_bookmark = {category="none", event="GotoFirstBookmark", title=_("First bookmark"), reader=true},
last_bookmark = {category="none", event="GotoLastBookmark", title=_("Last bookmark"), reader=true},
latest_bookmark = {category="none", event="GoToLatestBookmark", title=_("Latest bookmark"), reader=true, separator=true},
----
back = {category="none", event="Back", title=_("Back"), reader=true},
previous_location = {category="none", event="GoBackLink", arg=true, title=_("Back to previous location"), reader=true},
next_location = {category="none", event="GoForwardLink", arg=true, title=_("Forward to next location"), reader=true},
follow_nearest_link = {category="arg", event="GoToPageLink", arg={pos={x=0,y=0}}, title=_("Follow nearest link"), reader=true},
follow_nearest_internal_link = {category="arg", event="GoToInternalPageLink", arg={pos={x=0,y=0}}, title=_("Follow nearest internal link"), reader=true},
select_prev_page_link = { category="none", event = "SelectPrevPageLink", title=_("Select previous link in current page"), reader=true, condition=not Device:isTouchDevice()},
select_next_page_link = { category="none", event = "SelectNextPageLink", title=_("Select next link in current page"), reader=true, condition=not Device:isTouchDevice()},
toggle_tap_links = {category="none", event="ToggleTapLinks", title=_("Toggle tap-to-follow links"), reader=true, condition=Device:isTouchDevice()},
add_location_to_history = {category="none", event="AddCurrentLocationToStack", arg=true, title=_("Add current location to history"), reader=true},
clear_location_history = {category="none", event="ClearLocationStack", arg=true, title=_("Clear location history"), reader=true, separator=true},
----
fulltext_search = {category="none", event="ShowFulltextSearchInput", title=_("Fulltext search"), reader=true},
fulltext_search_findall_results = {category="none", event="ShowFindAllResults", title=_("Last fulltext search results"), reader=true},
fulltext_search_start_page = {category="none", event="GoToStartPage", title=_("Fulltext search: go back to original page"), reader=true},
toc = {category="none", event="ShowToc", title=_("Table of contents"), reader=true},
book_map = {category="none", event="ShowBookMap", title=_("Book map"), reader=true, condition=Device:isTouchDevice() or (Device:hasDPad() and Device:useDPadAsActionKeys())},
book_map_overview = {category="none", event="ShowBookMap", arg=true, title=_("Book map (overview)"), reader=true, condition=Device:isTouchDevice() or (Device:hasDPad() and Device:useDPadAsActionKeys())},
page_browser = {category="none", event="ShowPageBrowser", title=_("Page browser"), reader=true, condition=Device:isTouchDevice() or (Device:hasDPad() and Device:useDPadAsActionKeys())},
bookmarks = {category="none", event="ShowBookmark", title=_("Bookmarks"), reader=true},
bookmark_search = {category="none", event="SearchBookmark", title=_("Bookmark search"), reader=true},
toggle_bookmark = {category="none", event="ToggleBookmark", title=_("Toggle bookmark"), reader=true, separator=true},
----
book_status = {category="none", event="ShowBookStatus", title=_("Book status"), reader=true},
book_info = {category="none", event="ShowBookInfo", title=_("Book information"), reader=true},
book_description = {category="none", event="ShowBookDescription", title=_("Book description"), reader=true},
book_cover = {category="none", event="ShowBookCover", title=_("Book cover"), reader=true, separator=true},
----
translate_page = {category="none", event="TranslateCurrentPage", title=_("Translate current page"), reader=true, separator=true},
----
set_inverse_reading_order = {category="string", event="ToggleReadingOrder", title=_("Invert page turn taps and swipes"), reader=true, condition=Device:isTouchDevice(), args={true, false}, toggle={_("on"), _("off")}},
toggle_inverse_reading_order = {category="none", event="ToggleReadingOrder", title=_("Toggle page turn direction"), reader=true, condition=Device:isTouchDevice()},
toggle_page_change_animation = {category="none", event="TogglePageChangeAnimation", title=_("Toggle page turn animations"), reader=true, condition=Device:canDoSwipeAnimation()},
toggle_handmade_toc = {category="none", event="ToggleHandmadeToc", title=_("Toggle custom TOC"), reader=true, condition=Device:isTouchDevice() or (Device:hasDPad() and Device:useDPadAsActionKeys())},
toggle_handmade_flows = {category="none", event="ToggleHandmadeFlows", title=_("Toggle custom hidden flows"), reader=true, separator=true, condition=Device:isTouchDevice() or (Device:hasDPad() and Device:useDPadAsActionKeys())},
----
set_highlight_action = {category="string", event="SetHighlightAction", title=_("Set highlight action"), args_func=ReaderHighlight.getHighlightActions, reader=true},
cycle_highlight_action = {category="none", event="CycleHighlightAction", title=_("Cycle highlight action"), reader=true},
cycle_highlight_style = {category="none", event="CycleHighlightStyle", title=_("Cycle highlight style"), reader=true, separator=true},
----
flush_settings = {category="none", event="FlushSettings", arg=true, title=_("Save book metadata"), reader=true, separator=true},
----
export_annotations = {category="none", event="ExportAnnotations", title=_("Export annotations"), reader=true},
-- Reflowable documents
set_typography_lang = {category="string", event="SetTypographyLanguage", title=_("Set typography language"), args_func=ReaderTypography.getLangTags, rolling=true, separator=true},
set_font = {category="string", event="SetFont", title=_("Font face"), rolling=true, args_func=require("fontlist").getFontArgFunc,},
increase_font = {category="incrementalnumber", event="IncreaseFontSize", min=0.5, max=255, step=0.5, title=_("Increase font size"), rolling=true},
decrease_font = {category="incrementalnumber", event="DecreaseFontSize", min=0.5, max=255, step=0.5, title=_("Decrease font size"), rolling=true},
-- Fixed layout documents
toggle_page_flipping = {category="none", event="TogglePageFlipping", title=_("Toggle page flipping"), paging=true},
toggle_bookmark_flipping = {category="none", event="ToggleBookmarkFlipping", title=_("Toggle bookmark flipping"), paging=true},
toggle_reflow = {category="none", event="ToggleReflow", title=_("Toggle reflow"), paging=true},
zoom = {category="string", event="SetZoomMode", title=_("Zoom mode"), args_func=ReaderZooming.getZoomModeActions, paging=true},
zoom_factor_change = {category="none", event="ZoomFactorChange", title=_("Change zoom factor"), paging=true, separator=true},
----
panel_zoom_toggle = {category="none", event="TogglePanelZoomSetting", title=_("Toggle panel zoom"), paging=true, separator=true},
----
-- parsed from CreOptions
font_size = {category="absolutenumber", rolling=true, title=_("Font size"), step=0.5},
word_spacing = {category="string", rolling=true},
word_expansion = {category="string", rolling=true},
font_gamma = {category="string", rolling=true},
font_base_weight = {category="string", rolling=true},
font_hinting = {category="string", rolling=true},
font_kerning = {category="string", rolling=true, separator=true},
----
visible_pages = {category="string", rolling=true, separator=true},
----
h_page_margins = {category="string", rolling=true},
sync_t_b_page_margins = {category="string", rolling=true},
t_page_margin = {category="absolutenumber", rolling=true},
b_page_margin = {category="absolutenumber", rolling=true, separator=true},
----
view_mode = {category="string", rolling=true},
block_rendering_mode = {category="string", rolling=true},
render_dpi = {category="string", title=_("Zoom"), rolling=true},
line_spacing = {category="absolutenumber", rolling=true, separator=true},
----
status_line = {category="string", rolling=true},
embedded_css = {category="string", rolling=true},
embedded_fonts = {category="string", rolling=true},
smooth_scaling = {category="string", rolling=true},
nightmode_images = {category="string", rolling=true, separator=true},
----
-- parsed from KoptOptions
kopt_trim_page = {category="string", paging=true},
kopt_page_margin = {category="string", paging=true},
kopt_zoom_overlap_h = {category="absolutenumber", paging=true},
kopt_zoom_overlap_v = {category="absolutenumber", paging=true},
kopt_zoom_mode_type = {category="string", paging=true},
kopt_zoom_mode_genus = {category="string", paging=true},
kopt_zoom_range_number = {category="string", paging=true, title=_("Number of columns/rows to split page")},
kopt_zoom_factor = {category="string", paging=true},
kopt_zoom_direction = {category="string", paging=true},
kopt_page_scroll = {category="string", paging=true},
kopt_page_gap_height = {category="string", paging=true},
kopt_line_spacing = {category="configurable", paging=true},
kopt_justification = {category="configurable", paging=true},
kopt_font_size = {category="string", paging=true, title=_("Font Size")},
kopt_font_fine_tune = {category="string", paging=true, title=_("Change font size")},
kopt_word_spacing = {category="configurable", paging=true},
kopt_text_wrap = {category="string", paging=true},
kopt_contrast = {category="string", paging=true},
kopt_page_opt = {category="configurable", paging=true},
kopt_hw_dithering = {category="string", paging=true},
kopt_sw_dithering = {category="string", paging=true},
kopt_quality = {category="configurable", paging=true},
kopt_doc_language = {category="string", paging=true},
kopt_forced_ocr = {category="configurable", paging=true},
kopt_writing_direction = {category="configurable", paging=true},
kopt_defect_size = {category="string", paging=true}, -- not shown in the bottom menu
kopt_max_columns = {category="configurable", paging=true},
kopt_auto_straighten = {category="absolutenumber", paging=true},
settings = nil, -- reserved for per instance dispatcher settings
}
-- array for item order in menu
local dispatcher_menu_order = {
-- General
"gesture_overview",
"filemanager",
"open_previous_document",
"history",
"history_search",
"favorites",
"collections",
"collections_search",
----
"dictionary_lookup",
"load_dictionary_preset",
"cycle_dictionary_preset",
"wikipedia_lookup",
----
"show_menu",
"menu_search",
"open_next_document_in_folder",
"open_previous_document_in_folder",
"notebook_file",
"screenshot",
----
-- Device
"exit_screensaver",
"start_usbms",
"suspend",
"restart",
"reboot",
"poweroff",
"exit",
----
"toggle_hold_corners",
"touch_input_on",
"touch_input_off",
"toggle_touch_input",
----
"swap_left_page_turn_buttons",
"swap_right_page_turn_buttons",
"swap_page_turn_buttons",
"set_page_turn_buttons",
----
"toggle_key_repeat",
"toggle_gsensor",
"temp_gsensor_on",
"lock_gsensor",
"set_lock_gsensor",
"rotation_mode",
"toggle_rotation",
"invert_rotation",
"iterate_rotation",
"iterate_rotation_ccw",
----
"wifi_on",
"wifi_off",
"toggle_wifi",
"toggle_fullscreen",
"show_network_info",
----
-- Screen and lights
"show_frontlight_dialog",
"toggle_frontlight",
"set_frontlight",
"increase_frontlight",
"decrease_frontlight",
"set_frontlight_warmth",
"increase_frontlight_warmth",
"decrease_frontlight_warmth",
"night_mode",
"set_night_mode",
----
"full_refresh",
"set_refresh_rate",
"set_day_refresh_rate",
"set_night_refresh_rate",
"set_flash_on_chapter_boundaries",
"toggle_flash_on_chapter_boundaries",
"set_no_flash_on_second_chapter_page",
"toggle_no_flash_on_second_chapter_page",
"set_flash_on_pages_with_images",
"toggle_flash_on_pages_with_images",
----
-- File browser
"set_display_mode",
"set_sort_by",
"set_reverse_sorting",
"set_mixed_sorting",
----
"show_plus_menu",
"toggle_select_mode",
"refresh_content",
"folder_shortcuts",
"file_search",
"file_search_results",
----
"folder_up",
"fm_go_to",
"fm_back",
----
"cloud_storage",
-- Reader
"show_config_menu",
"toggle_status_bar",
"toggle_chapter_progress_bar",
"load_footer_preset",
----
"prev_chapter",
"next_chapter",
"first_page",
"last_page",
"random_page",
"page_jmp",
"go_to",
"skim",
"pin_current_page",
"go_to_pinned_page",
----
"prev_bookmark",
"next_bookmark",
"first_bookmark",
"last_bookmark",
"latest_bookmark",
----
"back",
"previous_location",
"next_location",
"follow_nearest_link",
"follow_nearest_internal_link",
"select_prev_page_link",
"select_next_page_link",
"toggle_tap_links",
"add_location_to_history",
"clear_location_history",
----
"fulltext_search",
"fulltext_search_findall_results",
"fulltext_search_start_page",
"toc",
"book_map",
"book_map_overview",
"page_browser",
"bookmarks",
"bookmark_search",
"toggle_bookmark",
----
"book_status",
"book_info",
"book_description",
"book_cover",
----
"translate_page",
----
"set_inverse_reading_order",
"toggle_inverse_reading_order",
"toggle_page_change_animation",
"toggle_handmade_toc",
"toggle_handmade_flows",
----
"set_highlight_action",
"cycle_highlight_action",
"cycle_highlight_style",
----
"flush_settings",
----
"export_annotations",
-- Reflowable documents
"set_typography_lang",
----
"set_font",
"increase_font",
"decrease_font",
"font_size",
"word_spacing",
"word_expansion",
"font_gamma",
"font_base_weight",
"font_hinting",
"font_kerning",
----
"visible_pages",
----
"h_page_margins",
"sync_t_b_page_margins",
"t_page_margin",
"b_page_margin",
----
"view_mode",
"block_rendering_mode",
"render_dpi",
"line_spacing",
----
"status_line",
"embedded_css",
"embedded_fonts",
"smooth_scaling",
"nightmode_images",
-- Fixed layout documents
"toggle_page_flipping",
"toggle_bookmark_flipping",
"toggle_reflow",
"zoom",
"zoom_factor_change",
----
"panel_zoom_toggle",
----
"kopt_trim_page",
"kopt_page_margin",
"kopt_zoom_overlap_h",
"kopt_zoom_overlap_v",
"kopt_zoom_mode_type",
"kopt_zoom_mode_genus",
"kopt_zoom_range_number",
"kopt_zoom_factor",
"kopt_zoom_direction",
"kopt_page_scroll",
"kopt_page_gap_height",
"kopt_line_spacing",
"kopt_justification",
"kopt_font_size",
"kopt_font_fine_tune",
"kopt_word_spacing",
"kopt_text_wrap",
"kopt_contrast",
"kopt_page_opt",
"kopt_hw_dithering",
"kopt_sw_dithering",
"kopt_quality",
"kopt_doc_language",
"kopt_forced_ocr",
"kopt_writing_direction",
"kopt_defect_size",
"kopt_max_columns",
"kopt_auto_straighten",
}
--[[--
add settings from CreOptions / KoptOptions
--]]--
function Dispatcher:init()
if Dispatcher.initialized then return end
local parseoptions = function(options, prefix)
for _, option in ipairs(options) do
local name = prefix and prefix .. option.name or option.name
if settingsList[name] ~= nil then
if option.name ~= nil and option.values ~= nil then
settingsList[name].configurable = {name = option.name, values = option.values}
end
if settingsList[name].event == nil then
settingsList[name].event = option.event
end
if settingsList[name].title == nil then
settingsList[name].title = option.name_text
end
if settingsList[name].condition == nil then
settingsList[name].condition = option.show
end
if settingsList[name].category == "string" or settingsList[name].category == "configurable" then
if settingsList[name].toggle == nil then
settingsList[name].toggle = option.toggle or option.labels
if settingsList[name].toggle == nil then
settingsList[name].toggle = {}
for z=1,#option.values do
if type(option.values[z]) == "table" then
settingsList[name].toggle[z] = option.values[z][1]
else
settingsList[name].toggle[z] = option.values[z]
end
end
end
end
if settingsList[name].args == nil then
settingsList[name].args = option.args or option.values
end
elseif settingsList[name].category == "absolutenumber" then
if settingsList[name].min == nil then
settingsList[name].min =
(option.more_options_param and (option.more_options_param.value_min or option.more_options_param.left_min))
or (option.args and option.args[1]) or option.values[1]
end
if settingsList[name].max == nil then
settingsList[name].max =
(option.more_options_param and (option.more_options_param.value_max or option.more_options_param.left_max))
or (option.args and option.args[#option.args]) or option.values[#option.values]
end
if settingsList[name].default == nil then
settingsList[name].default = option.default_value
end
end
settingsList[name].unit = option.more_options_param and option.more_options_param.unit
end
end
end
for i=1,#CreOptions do
parseoptions(CreOptions[i].options)
end
for i=2,#KoptOptions do -- #1 "Rotation" parsed from CreOptions
parseoptions(KoptOptions[i].options, "kopt_")
end
UIManager:broadcastEvent(Event:new("DispatcherRegisterActions"))
Dispatcher.initialized = true
end
--[[--
Adds settings at runtime.
@usage
function Hello:onDispatcherRegisterActions()
Dispatcher:registerAction("helloworld_action", {category="none", event="HelloWorld", title=_("Hello World"), general=true})
end
function Hello:init()
self:onDispatcherRegisterActions()
end
@param name the key to use in the table
@param value a table per settingsList above
--]]--
function Dispatcher:registerAction(name, value)
if settingsList[name] == nil then
settingsList[name] = value
table.insert(dispatcher_menu_order, name)
end
return true
end
--[[--
Removes settings at runtime.
@param name the key to use in the table
--]]--
function Dispatcher:removeAction(name)
local k = util.arrayContains(dispatcher_menu_order, name)
if k then
table.remove(dispatcher_menu_order, k)
settingsList[name] = nil
end
return true
end
function Dispatcher.iter_func(settings)
local order = util.tableGetValue(settings, "settings", "order")
if order and #order > 1 then
return ipairs(order)
else
return pairs(settings)
end
end
-- Returns the number of items present in the settings table
function Dispatcher:_itemsCount(settings)
if settings then
local count = util.tableSize(settings)
if count > 0 and settings.settings ~= nil then
count = count - 1
end
return count
end
end
-- Returns a display name for the item.
function Dispatcher:getNameFromItem(item, settings, dont_show_value)
if settingsList[item] == nil then
return _("Unknown item")
end
local value = settings and settings[item]
local title = settingsList[item].title
if dont_show_value or value == nil then
return title
end
local display_value
local category = settingsList[item].category
if category == "string" or category == "configurable" then
if type(value) == "table" then
display_value = string.format("%d / %d", unpack(value))
else
if not settingsList[item].args and settingsList[item].args_func then
settingsList[item].args, settingsList[item].toggle = settingsList[item].args_func()
end
local value_num = util.arrayContains(settingsList[item].args, value)
display_value = settingsList[item].toggle[value_num]
or (type(value) == "number" and string.format("%.1f", value) or value)
end
elseif category == "absolutenumber" then
display_value = tostring(value)
elseif category == "incrementalnumber" then
display_value = value == 0 and _("gesture distance") or tostring(value)
end
if display_value then
if settingsList[item].unit and (type(value) == "table" or tonumber(display_value)) then
-- do not show unit when the setting is "none" ^^
display_value = display_value .. "\u{202F}" .. settingsList[item].unit
end
title = title .. ": " .. display_value
end
return title
end
-- Converts copt/kopt-options values to args.
function Dispatcher:getArgFromValue(item, value)
local value_num = util.arrayContains(settingsList[item].configurable.values, value)
return settingsList[item].args[value_num]
end
-- Add the item to the end of the execution order.
-- If order is nil all items will be added.
function Dispatcher._addToOrder(location, settings, item)
local actions = location[settings]
local count = Dispatcher:_itemsCount(actions)
if count == 2 then
local first_item
for k in pairs(actions) do
if k ~= "settings" and k~= item then
first_item = k
break
end
end
actions.settings = actions.settings or {}
actions.settings.order = { first_item, item }
elseif count > 2 then
local order = util.tableGetValue(actions, "settings", "order")
if order then
if not util.arrayContains(order, item) then
table.insert(location[settings].settings.order, item)
end
else -- old unordered actions
util.tableSetValue(actions, {}, "settings", "order")
for k in pairs(actions) do
if settingsList[k] ~= nil then
table.insert(location[settings].settings.order, k)
end
end
end
end
end
-- Remove the item from the execution order.
-- If the resulting order is empty it will be nilled.
function Dispatcher._removeFromOrder(location, settings, item)
local actions = location[settings]
local order = util.tableGetValue(actions, "settings", "order")
if order then
local k = util.arrayContains(order, item)
if k then
table.remove(order, k)
if Dispatcher:_itemsCount(actions) < 2 then
util.tableRemoveValue(actions, "settings", "order")
end
end
end
util.tableRemoveValue(actions, "settings", "quickmenu_separators", item)
end
-- Get a textual representation of the enabled actions to display in a menu item.
function Dispatcher:menuTextFunc(settings)
if settings then
local count = Dispatcher:_itemsCount(settings)
if count == 0 then
return _("Nothing")
elseif count == 1 then
local item = next(settings)
if item == "settings" then item = next(settings, item) end
return Dispatcher:getNameFromItem(item, settings)
end
return T(NC_("Dispatcher", "1 action", "%1 actions", count), count)
end
return _("Pass through")
end
-- Get a list of all enabled actions to display in a menu.
function Dispatcher.getDisplayList(settings, for_sorting)
local item_table = {}
if not settings then return item_table end
local is_check_mark = for_sorting and settings.settings and settings.settings.show_as_quickmenu
for item, v in Dispatcher.iter_func(settings) do
if type(item) == "number" then item = v end
if settingsList[item] ~= nil and settingsList[item].condition ~= false then
table.insert(item_table, {
text = Dispatcher:getNameFromItem(item, settings),
key = item,
checked_func = is_check_mark and function()
return settings.settings.quickmenu_separators and settings.settings.quickmenu_separators[item]
end,
callback = is_check_mark and function()
if settings.settings.quickmenu_separators and settings.settings.quickmenu_separators[item] then
util.tableRemoveValue(settings.settings, "quickmenu_separators", item)
else
util.tableSetValue(settings.settings, true, "quickmenu_separators", item)
end
end,
})
end
end
return item_table
end
-- Display a SortWidget to sort the enable actions execution order.
function Dispatcher._sortActions(caller, actions)
local show_as_quickmenu = util.tableGetValue(actions, "settings", "show_as_quickmenu")
local display_list = Dispatcher.getDisplayList(actions, true)
local SortWidget = require("ui/widget/sortwidget")
local sort_widget = SortWidget:new{
title = show_as_quickmenu and _("Arrange actions and QuickMenu separators") or _("Arrange actions"),
underscore_checked_item = show_as_quickmenu,
item_table = display_list,
callback = function()
util.tableSetValue(actions, {}, "settings", "order")
for i, v in ipairs(display_list) do
actions.settings.order[i] = v.key
end
caller.updated = true
end
}
UIManager:show(sort_widget)
end
function Dispatcher:_addItem(caller, menu, location, settings, section)
local function setValue(k, value, touchmenu_instance)
if value ~= nil then
if location[settings] == nil then
location[settings] = {}
end
location[settings][k] = value
Dispatcher._addToOrder(location, settings, k)
else
location[settings][k] = nil
Dispatcher._removeFromOrder(location, settings, k)
end
caller.updated = true
if touchmenu_instance then
touchmenu_instance:updateItems()
end
end
for __, k in ipairs(dispatcher_menu_order) do
if settingsList[k][section] == true and settingsList[k].condition ~= false then
if settingsList[k].category == "none" or settingsList[k].category == "arg" then
table.insert(menu, {
text = settingsList[k].title,
checked_func = function()
return location[settings] ~= nil and location[settings][k] ~= nil
end,
callback = function(touchmenu_instance)
local value = (location[settings] == nil or location[settings][k] == nil) and true or nil
setValue(k, value, touchmenu_instance)
end,
separator = settingsList[k].separator,
})
elseif settingsList[k].category == "absolutenumber" then
table.insert(menu, {
text_func = function()
return Dispatcher:getNameFromItem(k, location[settings])
end,
checked_func = function()
return location[settings] ~= nil and location[settings][k] ~= nil
end,
callback = function(touchmenu_instance)
local SpinWidget = require("ui/widget/spinwidget")
local precision
if settingsList[k].step and math.floor(settingsList[k].step) ~= settingsList[k].step then
precision = "%0.1f"
end
local items = SpinWidget:new{
value = location[settings] ~= nil and location[settings][k] or settingsList[k].default or settingsList[k].min,
value_min = settingsList[k].min,
value_step = settingsList[k].step,
precision = precision,
value_hold_step = 5,
value_max = settingsList[k].max,
title_text = Dispatcher:getNameFromItem(k, location[settings], true),
unit = settingsList[k].unit,
ok_always_enabled = true,
callback = function(spin)
setValue(k, spin.value, touchmenu_instance)
end,
}
UIManager:show(items)
end,
hold_callback = function(touchmenu_instance)
if location[settings] ~= nil and location[settings][k] ~= nil then
setValue(k, nil, touchmenu_instance)
end
end,
separator = settingsList[k].separator,
})
elseif settingsList[k].category == "incrementalnumber" then
table.insert(menu, {
text_func = function()
return Dispatcher:getNameFromItem(k, location[settings])
end,
checked_func = function()
return location[settings] ~= nil and location[settings][k] ~= nil
end,
callback = function(touchmenu_instance)
local value = location[settings] and location[settings][k]
if value == nil or value < settingsList[k].min then
value = settingsList[k].min
end
local precision
if settingsList[k].step and math.floor(settingsList[k].step) ~= settingsList[k].step then
precision = "%0.1f"
end
local SpinWidget = require("ui/widget/spinwidget")
local items = SpinWidget:new{
value = value,
value_min = settingsList[k].min,
value_step = settingsList[k].step,
precision = precision,
value_hold_step = 5,
value_max = settingsList[k].max,
title_text = Dispatcher:getNameFromItem(k, location[settings], true),
ok_always_enabled = true,
callback = function(spin)
setValue(k, spin.value, touchmenu_instance)
end,
option_text = Device:isTouchDevice() and caller.profiles == nil and _("Use gesture distance"), -- Gesture manager only
option_callback = function()
setValue(k, 0, touchmenu_instance)
end,
}
UIManager:show(items)
end,
hold_callback = function(touchmenu_instance)
if location[settings] ~= nil and location[settings][k] ~= nil then
setValue(k, nil, touchmenu_instance)
end
end,
separator = settingsList[k].separator,
})
elseif settingsList[k].category == "string" or settingsList[k].category == "configurable" then
local function sub_item_table_func()
local item_table = {}
if settingsList[k].args_func then
settingsList[k].args, settingsList[k].toggle = settingsList[k].args_func()
end
for i=1,#settingsList[k].args do
table.insert(item_table, {
text = tostring(settingsList[k].toggle[i]),
checked_func = function()
if location[settings] ~= nil and location[settings][k] ~= nil then
if type(location[settings][k]) == "table" then
return location[settings][k][1] == settingsList[k].args[i][1]
else
return location[settings][k] == settingsList[k].args[i]
end
end
end,
radio = true,
callback = function()
setValue(k, settingsList[k].args[i])
end,
})
end
return item_table
end
table.insert(menu, {
text_func = function()
return Dispatcher:getNameFromItem(k, location[settings])
end,
checked_func = function()
return location[settings] ~= nil and location[settings][k] ~= nil
end,
sub_item_table_func = sub_item_table_func,
keep_menu_open = true,
hold_callback = function(touchmenu_instance)
if location[settings] ~= nil and location[settings][k] ~= nil then
setValue(k, nil, touchmenu_instance)
end
end,
separator = settingsList[k].separator,
})
end
end
end
end
function Dispatcher.removeActions(actions, do_remove)
local count = actions and Dispatcher:_itemsCount(actions) or 0
if count > 1 then
local ConfirmBox = require("ui/widget/confirmbox")
UIManager:show(ConfirmBox:new{
text = T(NC_("Dispatcher", "1 action will be removed.", "%1 actions will be removed.", count), count),
ok_callback = do_remove,
})
else
do_remove()
end
end
--[[--
Add a submenu to edit which items are dispatched
arguments are:
1) the caller so dispatcher can set the updated flag
2) the table representing the submenu (can be empty)
3) the object (table) in which the settings table is found
4) the name of the settings table
example usage:
Dispatcher:addSubMenu(self, sub_items, self.data, "profile1")
--]]--
function Dispatcher:addSubMenu(caller, menu, location, settings)
Dispatcher:init()
menu.ignored_by_menu_search = true -- all those would be duplicated
table.insert(menu, {
text = _("Nothing"),
checked_func = function()
return location[settings] ~= nil and Dispatcher:_itemsCount(location[settings]) == 0
end,
check_callback_updates_menu = true,
radio = true,
callback = function(touchmenu_instance)
local function do_remove()
local actions = location[settings]
local name = actions and actions.settings and actions.settings.name
location[settings] = name and { settings = { name = name } } or {}
caller.updated = true
touchmenu_instance:updateItems()
end
Dispatcher.removeActions(location[settings], do_remove)
end,
separator = true,
})
local section_list = {
{"general", _("General")},
{"device", _("Device")},
{"screen", _("Screen and lights")},
{"filemanager", _("File browser")},
{"reader", _("Reader")},
{"rolling", _("Reflowable documents (epub, fb2, txt…)")},
{"paging", _("Fixed layout documents (pdf, djvu, pics…)")},
}
for _, section in ipairs(section_list) do
local submenu = {}
Dispatcher:_addItem(caller, submenu, location, settings, section[1])
table.insert(menu, {
text = section[2],
checked_func = function()
if location[settings] ~= nil then
for k, _ in pairs(location[settings]) do
if settingsList[k] ~= nil and settingsList[k][section[1]] == true and
(settingsList[k].condition == nil or settingsList[k].condition)
then return true end
end
end
end,
hold_callback = function(touchmenu_instance)
if location[settings] ~= nil then
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
if touchmenu_instance then touchmenu_instance:updateItems() end
end
end,
sub_item_table = submenu,
})
end
menu.max_per_page = #menu -- next items in page 2
table.insert(menu, {
text_func = function()
return util.tableGetValue(location[settings], "settings", "show_as_quickmenu")
and _("Arrange actions and QuickMenu separators") or _("Arrange actions")
end,
enabled_func = function()
return location[settings] and Dispatcher:_itemsCount(location[settings]) > 1 or false
end,
callback = function(touchmenu_instance)
Dispatcher._sortActions(caller, location[settings])
end,
keep_menu_open = true,
separator = true,
})
table.insert(menu, {
text = _("Show as QuickMenu"),
checked_func = function()
return util.tableGetValue(location[settings], "settings", "show_as_quickmenu")
end,
callback = function()
local actions = location[settings]
if actions then
if util.tableGetValue(actions, "settings", "show_as_quickmenu") then
util.tableRemoveValue(actions, "settings", "show_as_quickmenu")
util.tableRemoveValue(actions, "settings", "quickmenu_separators")
util.tableRemoveValue(actions, "settings", "keep_open_on_apply")
util.tableRemoveValue(actions, "settings", "anchor_quickmenu")
else
util.tableSetValue(actions, true, "settings", "show_as_quickmenu")
end
caller.updated = true
end
end,
})
table.insert(menu, {
text = _("Keep QuickMenu open"),
enabled_func = function()
return util.tableGetValue(location[settings], "settings", "show_as_quickmenu") or false
end,
checked_func = function()
return util.tableGetValue(location[settings], "settings", "keep_open_on_apply")
end,
callback = function()
local actions = location[settings]
if actions then
if util.tableGetValue(actions, "settings", "keep_open_on_apply") then
util.tableRemoveValue(actions, "settings", "keep_open_on_apply")
else
util.tableSetValue(actions, true, "settings", "keep_open_on_apply")
end
caller.updated = true
end
end,
})
end
function Dispatcher:isActionEnabled(action)
local disabled = true
if action and (action.condition == nil or action.condition == true) then
local ui = require("apps/reader/readerui").instance
local context = ui and (ui.paging and "paging" or "rolling")
if context == "paging" then
disabled = action["rolling"]
elseif context == "rolling" then
disabled = action["paging"]
else -- FM
disabled = action["reader"] or action["rolling"] or action["paging"]
end
end
return not disabled
end
function Dispatcher._showAsMenu(settings, exec_props)
local title = settings.settings.name
local keep_open_on_apply = settings.settings.keep_open_on_apply
local display_list = Dispatcher.getDisplayList(settings)
local quickmenu
local buttons = {}
if exec_props and exec_props.qm_show then
table.insert(buttons, {{
text = _("Execute all"),
align = "left",
font_face = "smallinfofont",
font_size = 22,
callback = function()
UIManager:close(quickmenu)
Dispatcher:execute(settings, { qm_show = false })
end,
}})
end
for _, v in ipairs(display_list) do
table.insert(buttons, {{
text = v.text,
enabled = Dispatcher:isActionEnabled(settingsList[v.key]),
menu_style = true,
callback = function()
UIManager:close(quickmenu)
Dispatcher:execute({[v.key] = settings[v.key]})
if keep_open_on_apply and not util.stringStartsWith(v.key, "touch_input") then
quickmenu:setTitle(title)
UIManager:show(quickmenu)
end
end,
hold_callback = function()
if v.key:sub(1, 13) == "profile_exec_" then
UIManager:close(quickmenu)
UIManager:sendEvent(Event:new(settingsList[v.key].event, settingsList[v.key].arg, { qm_show = true }))
end
end,
}})
if settings.settings.quickmenu_separators and settings.settings.quickmenu_separators[v.key] then
table.insert(buttons, {})
end
end
local ButtonDialog = require("ui/widget/buttondialog")
quickmenu = ButtonDialog:new{
title = title,
title_align = "center",
shrink_unneeded_width = true,
shrink_min_width = math.floor(0.6 * Screen:getWidth()),
use_info_style = false,
buttons = buttons,
anchor = exec_props and exec_props.qm_anchor,
}
UIManager:show(quickmenu)
end
--[[--
Calls the events in a settings list
arguments are:
1) the settings table
2) execution management table: { qm_show = true|false} - forcibly show QM / run
{ qm_anchor = ges.pos } - anchor position
{ gesture = ges } - a `gestures` object
--]]--
function Dispatcher:execute(settings, exec_props)
if ((exec_props == nil or exec_props.qm_show == nil) and settings.settings and settings.settings.show_as_quickmenu)
or (exec_props and exec_props.qm_show) then
return Dispatcher._showAsMenu(settings, exec_props)
end
local has_many = Dispatcher:_itemsCount(settings) > 1
if has_many then
UIManager:broadcastEvent(Event:new("BatchedUpdate"))
UIManager:setSilentMode(true)
end
Notification:setNotifySource(Notification.SOURCE_DISPATCHER)
if settings.settings and settings.settings.notify then
Notification:notify(T(_("Executing profile: %1"), settings.settings.name))
end
local gesture = exec_props and exec_props.gesture
for k, v in Dispatcher.iter_func(settings) do
if type(k) == "number" then
k = v
v = settings[k]
end
if Dispatcher:isActionEnabled(settingsList[k]) then
if settingsList[k].configurable then
local value = v
if type(v) ~= "number" then
for i, r in ipairs(settingsList[k].args) do
if v == r then value = settingsList[k].configurable.values[i] break end
end
end
UIManager:sendEvent(Event:new("ConfigChange", settingsList[k].configurable.name, value))
end
local category = settingsList[k].category
local event = settingsList[k].event
local arg = settingsList[k].arg
if category == "none" then
if arg ~= nil then
UIManager:sendEvent(Event:new(event, arg, exec_props))
else
UIManager:sendEvent(Event:new(event))
end
elseif category == "absolutenumber" or category == "string" then
arg = arg ~= nil and { arg, v } or v
UIManager:sendEvent(Event:new(event, arg))
elseif category == "arg" then
-- the event can accept a gesture object or an argument
arg = gesture or arg
UIManager:sendEvent(Event:new(event, arg))
elseif category == "incrementalnumber" then
-- the event can accept a gesture object or a number
arg = v ~= 0 and v or gesture or 0
UIManager:sendEvent(Event:new(event, arg))
end
end
end
Notification:resetNotifySource()
if has_many then
UIManager:setSilentMode(false)
UIManager:broadcastEvent(Event:new("BatchedUpdateDone"))
end
end
return Dispatcher