mirror of
https://github.com/koreader/koreader.git
synced 2025-12-24 12:14:05 +01:00
TouchMenu: added options to menu items with the following defaults:
keep_menu_open = false
hold_keep_menu_open = true
So, default for Tap callback is to close menu, and for Hold callback
to keep menu open.
In both cases, provide the TouchMenu instance as the 1st argument to
the callback functions (instead of a refresh_menu_func I added in #3941)
so the callback can do more things, like closing, refreshing,
changing menu items text and re-ordering...
ReaderZooming: show symbol for default (like it was done for
ReaderFont, ReaderHyphenation...)
TextEditor plugin: update the previously opened files list in real
time, so the menu can be kept open and used as the TextEditor main
interface.
SSH plugin: keep menu open and update the Start/Stop state in real time
ReadTimer plugin: tried to do what feels right (but I don't use it)
Also remove forgotten cp in the move/paste file code
445 lines
15 KiB
Lua
445 lines
15 KiB
Lua
local CenterContainer = require("ui/widget/container/centercontainer")
|
|
local CloudStorage = require("apps/cloudstorage/cloudstorage")
|
|
local ConfirmBox = require("ui/widget/confirmbox")
|
|
local Device = require("device")
|
|
local FileSearcher = require("apps/filemanager/filemanagerfilesearcher")
|
|
local InputContainer = require("ui/widget/container/inputcontainer")
|
|
local PluginLoader = require("pluginloader")
|
|
local Search = require("apps/filemanager/filemanagersearch")
|
|
local SetDefaults = require("apps/filemanager/filemanagersetdefaults")
|
|
local UIManager = require("ui/uimanager")
|
|
local Screen = Device.screen
|
|
local dbg = require("dbg")
|
|
local logger = require("logger")
|
|
local util = require("util")
|
|
local _ = require("gettext")
|
|
local T = require("ffi/util").template
|
|
|
|
local FileManagerMenu = InputContainer:extend{
|
|
tab_item_table = nil,
|
|
menu_items = {},
|
|
registered_widgets = nil,
|
|
}
|
|
|
|
function FileManagerMenu:init()
|
|
self.menu_items = {
|
|
["KOMenu:menu_buttons"] = {
|
|
-- top menu
|
|
},
|
|
-- items in top menu
|
|
filemanager_settings = {
|
|
icon = "resources/icons/appbar.cabinet.files.png",
|
|
},
|
|
setting = {
|
|
icon = "resources/icons/appbar.settings.png",
|
|
},
|
|
tools = {
|
|
icon = "resources/icons/appbar.tools.png",
|
|
},
|
|
search = {
|
|
icon = "resources/icons/appbar.magnify.browse.png",
|
|
},
|
|
main = {
|
|
icon = "resources/icons/menu-icon.png",
|
|
},
|
|
}
|
|
|
|
self.registered_widgets = {}
|
|
|
|
if Device:hasKeys() then
|
|
self.key_events = {
|
|
ShowMenu = { { "Menu" }, doc = "show menu" },
|
|
}
|
|
end
|
|
self.activation_menu = G_reader_settings:readSetting("activate_menu")
|
|
if self.activation_menu == nil then
|
|
self.activation_menu = "swipe_tap"
|
|
end
|
|
end
|
|
|
|
function FileManagerMenu:initGesListener()
|
|
if not Device:isTouchDevice() then return end
|
|
|
|
self:registerTouchZones({
|
|
{
|
|
id = "filemanager_tap",
|
|
ges = "tap",
|
|
screen_zone = {
|
|
ratio_x = DTAP_ZONE_MENU.x, ratio_y = DTAP_ZONE_MENU.y,
|
|
ratio_w = DTAP_ZONE_MENU.w, ratio_h = DTAP_ZONE_MENU.h,
|
|
},
|
|
handler = function(ges) return self:onTapShowMenu(ges) end,
|
|
},
|
|
{
|
|
id = "filemanager_swipe",
|
|
ges = "swipe",
|
|
screen_zone = {
|
|
ratio_x = DTAP_ZONE_MENU.x, ratio_y = DTAP_ZONE_MENU.y,
|
|
ratio_w = DTAP_ZONE_MENU.w, ratio_h = DTAP_ZONE_MENU.h,
|
|
},
|
|
overrides = { "rolling_swipe", "paging_swipe", },
|
|
handler = function(ges) return self:onSwipeShowMenu(ges) end,
|
|
},
|
|
})
|
|
end
|
|
|
|
function FileManagerMenu:openLastDoc()
|
|
local last_file = G_reader_settings:readSetting("lastfile")
|
|
if not last_file or lfs.attributes(last_file, "mode") ~= "file" then
|
|
local InfoMessage = require("ui/widget/infomessage")
|
|
UIManager:show(InfoMessage:new{
|
|
text = _("Cannot open last document"),
|
|
})
|
|
return
|
|
end
|
|
local ReaderUI = require("apps/reader/readerui")
|
|
ReaderUI:showReader(last_file)
|
|
self:onCloseFileManagerMenu()
|
|
local FileManager = require("apps/filemanager/filemanager")
|
|
FileManager.instance:onClose()
|
|
end
|
|
|
|
function FileManagerMenu:setUpdateItemTable()
|
|
for _, widget in pairs(self.registered_widgets) do
|
|
local ok, err = pcall(widget.addToMainMenu, widget, self.menu_items)
|
|
if not ok then
|
|
logger.err("failed to register widget", widget.name, err)
|
|
end
|
|
end
|
|
|
|
-- setting tab
|
|
self.menu_items.show_hidden_files = {
|
|
text = _("Show hidden files"),
|
|
checked_func = function() return self.ui.file_chooser.show_hidden end,
|
|
callback = function() self.ui:toggleHiddenFiles() end
|
|
}
|
|
self.menu_items.items_per_page = {
|
|
text = _("Items per page"),
|
|
help_text = _([[This sets the number of items per page in:
|
|
- File browser and history in 'classic' display mode
|
|
- File and directory selection
|
|
- Table of content
|
|
- Bookmarks list]]),
|
|
keep_menu_open = true,
|
|
callback = function()
|
|
local SpinWidget = require("ui/widget/spinwidget")
|
|
local curr_items = G_reader_settings:readSetting("items_per_page") or 14
|
|
local items = SpinWidget:new{
|
|
width = Screen:getWidth() * 0.6,
|
|
value = curr_items,
|
|
value_min = 6,
|
|
value_max = 24,
|
|
ok_text = _("Set items"),
|
|
title_text = _("Items per page"),
|
|
callback = function(spin)
|
|
G_reader_settings:saveSetting("items_per_page", spin.value)
|
|
self.ui:onRefresh()
|
|
end
|
|
}
|
|
UIManager:show(items)
|
|
end
|
|
}
|
|
self.menu_items.sort_by = self.ui:getSortingMenuTable()
|
|
self.menu_items.reverse_sorting = {
|
|
text = _("Reverse sorting"),
|
|
checked_func = function() return self.ui.file_chooser.reverse_collate end,
|
|
callback = function() self.ui:toggleReverseCollate() end
|
|
}
|
|
self.menu_items.start_with = self.ui:getStartWithMenuTable()
|
|
if Device:supportsScreensaver() then
|
|
self.menu_items.screensaver = {
|
|
text = _("Screensaver"),
|
|
sub_item_table = require("ui/elements/screensaver_menu"),
|
|
}
|
|
end
|
|
-- insert common settings
|
|
for id, common_setting in pairs(require("ui/elements/common_settings_menu_table")) do
|
|
self.menu_items[id] = common_setting
|
|
end
|
|
|
|
-- tools tab
|
|
self.menu_items.advanced_settings = {
|
|
text = _("Advanced settings"),
|
|
callback = function()
|
|
SetDefaults:ConfirmEdit()
|
|
end,
|
|
hold_callback = function()
|
|
SetDefaults:ConfirmSave()
|
|
end,
|
|
}
|
|
self.menu_items.plugin_management = {
|
|
text = _("Plugin management"),
|
|
sub_item_table = PluginLoader:genPluginManagerSubItem()
|
|
}
|
|
|
|
self.menu_items.opds_catalog = {
|
|
text = _("OPDS catalog"),
|
|
callback = function()
|
|
local OPDSCatalog = require("apps/opdscatalog/opdscatalog")
|
|
local filemanagerRefresh = function() self.ui:onRefresh() end
|
|
function OPDSCatalog:onClose()
|
|
filemanagerRefresh()
|
|
UIManager:close(self)
|
|
end
|
|
OPDSCatalog:showCatalog()
|
|
end,
|
|
}
|
|
self.menu_items.developer_options = {
|
|
text = _("Developer options"),
|
|
sub_item_table = {
|
|
{
|
|
text = _("Clear readers' caches"),
|
|
callback = function()
|
|
UIManager:show(ConfirmBox:new{
|
|
text = _("Clear cache/ and cr3cache/ ?"),
|
|
ok_callback = function()
|
|
local purgeDir = require("ffi/util").purgeDir
|
|
local DataStorage = require("datastorage")
|
|
local cachedir = DataStorage:getDataDir() .. "/cache"
|
|
if lfs.attributes(cachedir, "mode") == "directory" then
|
|
purgeDir(cachedir)
|
|
end
|
|
lfs.mkdir(cachedir)
|
|
-- Also remove from Cache objet references to
|
|
-- the cache files we just deleted
|
|
local Cache = require("cache")
|
|
Cache.cached = {}
|
|
local InfoMessage = require("ui/widget/infomessage")
|
|
UIManager:show(InfoMessage:new{
|
|
text = _("Caches cleared. Please exit and restart KOReader."),
|
|
})
|
|
end,
|
|
})
|
|
end,
|
|
},
|
|
}
|
|
}
|
|
self.menu_items.cloud_storage = {
|
|
text = _("Cloud storage"),
|
|
callback = function()
|
|
local cloud_storage = CloudStorage:new{}
|
|
UIManager:show(cloud_storage)
|
|
local filemanagerRefresh = function() self.ui:onRefresh() end
|
|
function cloud_storage:onClose()
|
|
filemanagerRefresh()
|
|
UIManager:close(cloud_storage)
|
|
end
|
|
end,
|
|
}
|
|
|
|
-- search tab
|
|
self.menu_items.find_book_in_calibre_catalog = {
|
|
text = _("Find a book in calibre catalog"),
|
|
callback = function()
|
|
Search:getCalibre()
|
|
Search:ShowSearch()
|
|
end
|
|
}
|
|
self.menu_items.find_file = {
|
|
text = _("Find a file"),
|
|
callback = function()
|
|
FileSearcher:showSearch(self.ui.file_chooser.path)
|
|
end
|
|
}
|
|
|
|
-- main menu tab
|
|
self.menu_items.open_last_document = {
|
|
text_func = function()
|
|
if not G_reader_settings:isTrue("open_last_menu_show_filename") or not G_reader_settings:readSetting("lastfile") then
|
|
return _("Open last document")
|
|
end
|
|
local last_file = G_reader_settings:readSetting("lastfile")
|
|
local path, file_name = util.splitFilePathName(last_file); -- luacheck: no unused
|
|
return T(_("Last: %1"), file_name)
|
|
end,
|
|
enabled_func = function()
|
|
return G_reader_settings:readSetting("lastfile") ~= nil
|
|
end,
|
|
callback = function()
|
|
self:openLastDoc()
|
|
end,
|
|
hold_callback = function()
|
|
local last_file = G_reader_settings:readSetting("lastfile")
|
|
UIManager:show(ConfirmBox:new{
|
|
text = T(_("Would you like to open the last document: %1?"), last_file),
|
|
ok_text = _("OK"),
|
|
ok_callback = function()
|
|
self:openLastDoc()
|
|
end,
|
|
})
|
|
end
|
|
}
|
|
-- insert common info
|
|
for id, common_setting in pairs(require("ui/elements/common_info_menu_table")) do
|
|
self.menu_items[id] = common_setting
|
|
end
|
|
self.menu_items.exit_menu = {
|
|
text = _("Exit"),
|
|
hold_callback = function()
|
|
self:exitOrRestart()
|
|
end,
|
|
}
|
|
self.menu_items.exit = {
|
|
text = _("Exit"),
|
|
callback = function()
|
|
self:exitOrRestart()
|
|
end,
|
|
}
|
|
self.menu_items.restart_koreader = {
|
|
text = _("Restart KOReader"),
|
|
callback = function()
|
|
self:exitOrRestart(function() UIManager:restartKOReader() end)
|
|
end,
|
|
}
|
|
if not Device:isTouchDevice() then
|
|
--add a shortcut on non touch-device
|
|
--because this menu is not accessible otherwise
|
|
self.menu_items.plus_menu = {
|
|
icon = "resources/icons/appbar.plus.png",
|
|
remember = false,
|
|
callback = function()
|
|
self:onCloseFileManagerMenu()
|
|
self.ui:tapPlus()
|
|
end,
|
|
}
|
|
end
|
|
|
|
local order = require("ui/elements/filemanager_menu_order")
|
|
|
|
local MenuSorter = require("ui/menusorter")
|
|
self.tab_item_table = MenuSorter:mergeAndSort("filemanager", self.menu_items, order)
|
|
end
|
|
dbg:guard(FileManagerMenu, 'setUpdateItemTable',
|
|
function(self)
|
|
local mock_menu_items = {}
|
|
for _, widget in pairs(self.registered_widgets) do
|
|
-- make sure addToMainMenu works in debug mode
|
|
widget:addToMainMenu(mock_menu_items)
|
|
end
|
|
end)
|
|
|
|
function FileManagerMenu:exitOrRestart(callback)
|
|
if SetDefaults.settings_changed then
|
|
UIManager:show(ConfirmBox:new{
|
|
text = _("You have unsaved default settings. Save them now?\nTap \"Cancel\" to return to KOReader."),
|
|
ok_text = _("Save"),
|
|
ok_callback = function()
|
|
SetDefaults.settings_changed = false
|
|
SetDefaults:saveSettings()
|
|
self:exitOrRestart(callback)
|
|
end,
|
|
cancel_text = _("Don't save"),
|
|
cancel_callback = function()
|
|
SetDefaults.settings_changed = false
|
|
self:exitOrRestart(callback)
|
|
end,
|
|
other_buttons = {{
|
|
text = _("Cancel"),
|
|
}}
|
|
})
|
|
else
|
|
UIManager:close(self.menu_container)
|
|
self.ui:onClose()
|
|
if callback then
|
|
callback()
|
|
end
|
|
end
|
|
end
|
|
|
|
function FileManagerMenu:onShowMenu(tab_index)
|
|
if self.tab_item_table == nil then
|
|
self:setUpdateItemTable()
|
|
end
|
|
|
|
if not tab_index then
|
|
tab_index = G_reader_settings:readSetting("filemanagermenu_tab_index") or 1
|
|
end
|
|
|
|
local menu_container = CenterContainer:new{
|
|
ignore = "height",
|
|
dimen = Screen:getSize(),
|
|
}
|
|
|
|
local main_menu
|
|
if Device:isTouchDevice() or Device:hasDPad() then
|
|
local TouchMenu = require("ui/widget/touchmenu")
|
|
main_menu = TouchMenu:new{
|
|
width = Screen:getWidth(),
|
|
last_index = tab_index,
|
|
tab_item_table = self.tab_item_table,
|
|
show_parent = menu_container,
|
|
}
|
|
else
|
|
local Menu = require("ui/widget/menu")
|
|
main_menu = Menu:new{
|
|
title = _("File manager menu"),
|
|
item_table = Menu.itemTableFromTouchMenu(self.tab_item_table),
|
|
width = Screen:getWidth()-10,
|
|
show_parent = menu_container,
|
|
}
|
|
end
|
|
|
|
main_menu.close_callback = function ()
|
|
self:onCloseFileManagerMenu()
|
|
end
|
|
|
|
menu_container[1] = main_menu
|
|
-- maintain a reference to menu_container
|
|
self.menu_container = menu_container
|
|
UIManager:show(menu_container)
|
|
return true
|
|
end
|
|
|
|
function FileManagerMenu:onCloseFileManagerMenu()
|
|
local last_tab_index = self.menu_container[1].last_index
|
|
G_reader_settings:saveSetting("filemanagermenu_tab_index", last_tab_index)
|
|
UIManager:close(self.menu_container)
|
|
return true
|
|
end
|
|
|
|
function FileManagerMenu:_getTabIndexFromLocation(ges)
|
|
if self.tab_item_table == nil then
|
|
self:setUpdateItemTable()
|
|
end
|
|
local last_tab_index = G_reader_settings:readSetting("filemanagermenu_tab_index") or 1
|
|
if not ges then
|
|
return last_tab_index
|
|
-- if the start position is far right
|
|
elseif ges.pos.x > 2 * Screen:getWidth() / 3 then
|
|
return #self.tab_item_table
|
|
-- if the start position is far left
|
|
elseif ges.pos.x < Screen:getWidth() / 3 then
|
|
return 1
|
|
-- if center return the last index
|
|
else
|
|
return last_tab_index
|
|
end
|
|
end
|
|
|
|
function FileManagerMenu:onTapShowMenu(ges)
|
|
if self.activation_menu ~= "swipe" then
|
|
self:onShowMenu(self:_getTabIndexFromLocation(ges))
|
|
return true
|
|
end
|
|
end
|
|
|
|
function FileManagerMenu:onSwipeShowMenu(ges)
|
|
if self.activation_menu ~= "tap" and ges.direction == "south" then
|
|
self:onShowMenu(self:_getTabIndexFromLocation(ges))
|
|
return true
|
|
end
|
|
end
|
|
|
|
function FileManagerMenu:onSetDimensions(dimen)
|
|
-- update listening according to new screen dimen
|
|
if Device:isTouchDevice() then
|
|
self:initGesListener()
|
|
end
|
|
end
|
|
|
|
function FileManagerMenu:registerToMainMenu(widget)
|
|
table.insert(self.registered_widgets, widget)
|
|
end
|
|
|
|
return FileManagerMenu
|