mirror of
https://github.com/koreader/koreader.git
synced 2025-08-10 00:52:38 +00:00
Merge pull request #214 from houqp/filemanager
bug fix in class system & rewrite filemanager
This commit is contained in:
88
frontend/apps/filemanager/fm.lua
Normal file
88
frontend/apps/filemanager/fm.lua
Normal file
@@ -0,0 +1,88 @@
|
||||
require "ui/widget/filechooser"
|
||||
require "apps/filemanager/fmhistory"
|
||||
require "apps/filemanager/fmmenu"
|
||||
|
||||
|
||||
FileManager = InputContainer:extend{
|
||||
title = _("FileManager"),
|
||||
width = Screen:getWidth(),
|
||||
height = Screen:getHeight(),
|
||||
root_path = './',
|
||||
-- our own size
|
||||
dimen = Geom:new{ w = 400, h = 600 },
|
||||
onExit = function() end,
|
||||
}
|
||||
|
||||
function FileManager:init()
|
||||
local exclude_dirs = {"%.sdr$"}
|
||||
|
||||
self.show_parent = self.show_parent or self
|
||||
|
||||
local file_chooser = FileChooser:new{
|
||||
_name = 'fuck',
|
||||
is_popout = false,
|
||||
is_borderless = true,
|
||||
has_close_button = true,
|
||||
dir_filter = function(dirname)
|
||||
for _, pattern in ipairs(exclude_dirs) do
|
||||
if dirname:match(pattern) then return end
|
||||
end
|
||||
return true
|
||||
end,
|
||||
file_filter = function(filename)
|
||||
if DocumentRegistry:getProvider(filename) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
function file_chooser:onFileSelect(file)
|
||||
showReaderUI(file)
|
||||
return true
|
||||
end
|
||||
|
||||
self.banner = FrameContainer:new{
|
||||
padding = 0,
|
||||
bordersize = 0,
|
||||
TextWidget:new{
|
||||
face = Font:getFace("tfont", 24),
|
||||
text = self.title,
|
||||
}
|
||||
}
|
||||
|
||||
self.layout = VerticalGroup:new{
|
||||
_name = 'fm',
|
||||
self.banner,
|
||||
file_chooser,
|
||||
}
|
||||
|
||||
local fm_ui = FrameContainer:new{
|
||||
padding = 0,
|
||||
bordersize = 0,
|
||||
padding = self.padding,
|
||||
background = 0,
|
||||
self.layout,
|
||||
}
|
||||
|
||||
self[1] = fm_ui
|
||||
|
||||
self.menu = FileManagerMenu:new{
|
||||
ui = self
|
||||
}
|
||||
table.insert(self, self.menu)
|
||||
table.insert(self, FileManagerHistory:new{
|
||||
ui = self,
|
||||
menu = self.menu
|
||||
})
|
||||
|
||||
self:handleEvent(Event:new("SetDimensions", self.dimen))
|
||||
end
|
||||
|
||||
|
||||
function FileManager:onClose()
|
||||
UIManager:close(self)
|
||||
if self.onExit then
|
||||
self:onExit()
|
||||
end
|
||||
return true
|
||||
end
|
||||
73
frontend/apps/filemanager/fmhistory.lua
Normal file
73
frontend/apps/filemanager/fmhistory.lua
Normal file
@@ -0,0 +1,73 @@
|
||||
FileManagerHistory = InputContainer:extend{
|
||||
hist_menu_title = _("History"),
|
||||
}
|
||||
|
||||
function FileManagerHistory:init()
|
||||
self.ui.menu:registerToMainMenu(self)
|
||||
end
|
||||
|
||||
function FileManagerHistory:onSetDimensions(dimen)
|
||||
self.dimen = dimen
|
||||
end
|
||||
|
||||
function FileManagerHistory:onShowHist()
|
||||
self:updateItemTable()
|
||||
|
||||
local menu_container = CenterContainer:new{
|
||||
dimen = Screen:getSize(),
|
||||
}
|
||||
|
||||
local hist_menu = Menu:new{
|
||||
title = _("History"),
|
||||
item_table = self.hist,
|
||||
ui = self.ui,
|
||||
width = Screen:getWidth()-50,
|
||||
height = Screen:getHeight()-50,
|
||||
show_parent = menu_container,
|
||||
}
|
||||
|
||||
table.insert(menu_container, hist_menu)
|
||||
|
||||
hist_menu.close_callback = function()
|
||||
UIManager:close(menu_container)
|
||||
end
|
||||
|
||||
UIManager:show(menu_container)
|
||||
return true
|
||||
end
|
||||
|
||||
function FileManagerHistory:addToMainMenu(tab_item_table)
|
||||
-- insert table to main reader menu
|
||||
table.insert(tab_item_table.main, {
|
||||
text = self.hist_menu_title,
|
||||
callback = function()
|
||||
self:onShowHist()
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
function FileManagerHistory:updateItemTable()
|
||||
function readHistDir(order_arg, re)
|
||||
local pipe_out = io.popen("ls "..order_arg.." -1 ./history")
|
||||
for f in pipe_out:lines() do
|
||||
table.insert(re, {
|
||||
dir = DocSettings:getPathFromHistory(f),
|
||||
name = DocSettings:getNameFromHistory(f),
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
self.hist = {}
|
||||
local last_files = {}
|
||||
readHistDir("-c", last_files)
|
||||
for _,v in pairs(last_files) do
|
||||
table.insert(self.hist, {
|
||||
text = v.name,
|
||||
callback = function()
|
||||
showReaderUI(v.dir .. "/" .. v.name)
|
||||
end
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
131
frontend/apps/filemanager/fmmenu.lua
Normal file
131
frontend/apps/filemanager/fmmenu.lua
Normal file
@@ -0,0 +1,131 @@
|
||||
require "ui/widget/menu"
|
||||
require "ui/widget/touchmenu"
|
||||
|
||||
FileManagerMenu = InputContainer:extend{
|
||||
tab_item_table = nil,
|
||||
registered_widgets = {},
|
||||
}
|
||||
|
||||
function FileManagerMenu:init()
|
||||
self.tab_item_table = {
|
||||
main = {
|
||||
icon = "resources/icons/appbar.pokeball.png",
|
||||
},
|
||||
home = {
|
||||
icon = "resources/icons/appbar.home.png",
|
||||
callback = function()
|
||||
UIManager:close(self.menu_container)
|
||||
self.ui:onClose()
|
||||
end,
|
||||
},
|
||||
}
|
||||
self.registered_widgets = {}
|
||||
|
||||
if Device:hasKeyboard() then
|
||||
self.key_events = {
|
||||
ShowMenu = { { "Menu" }, doc = _("show menu") },
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
function FileManagerMenu:initGesListener()
|
||||
self.ges_events = {
|
||||
TapShowMenu = {
|
||||
GestureRange:new{
|
||||
ges = "tap",
|
||||
range = Geom:new{
|
||||
x = 0,
|
||||
y = 0,
|
||||
w = Screen:getWidth()*3/4,
|
||||
h = Screen:getHeight()/4,
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
function FileManagerMenu:setUpdateItemTable()
|
||||
for _, widget in pairs(self.registered_widgets) do
|
||||
widget:addToMainMenu(self.tab_item_table)
|
||||
end
|
||||
|
||||
if Device:hasFrontlight() then
|
||||
table.insert(self.tab_item_table.main, {
|
||||
text = _("Frontlight settings"),
|
||||
callback = function()
|
||||
ReaderFrontLight:onShowFlDialog()
|
||||
end
|
||||
})
|
||||
end
|
||||
table.insert(self.tab_item_table.main, {
|
||||
text = _("Help"),
|
||||
callback = function()
|
||||
UIManager:show(InfoMessage:new{
|
||||
text = _("Please report bugs to https://github.com/koreader/ koreader/issues, Click at the bottom of the page for more options"),
|
||||
})
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
function FileManagerMenu:onShowMenu()
|
||||
if #self.tab_item_table.main == 0 then
|
||||
self:setUpdateItemTable()
|
||||
end
|
||||
|
||||
local menu_container = CenterContainer:new{
|
||||
ignore = "height",
|
||||
dimen = Screen:getSize(),
|
||||
}
|
||||
|
||||
local main_menu = nil
|
||||
if Device:isTouchDevice() then
|
||||
main_menu = TouchMenu:new{
|
||||
width = Screen:getWidth(),
|
||||
tab_item_table = {
|
||||
self.tab_item_table.main,
|
||||
self.tab_item_table.home,
|
||||
},
|
||||
show_parent = menu_container,
|
||||
}
|
||||
else
|
||||
main_menu = Menu:new{
|
||||
title = _("File manager menu"),
|
||||
item_table = {},
|
||||
width = Screen:getWidth() - 100,
|
||||
}
|
||||
|
||||
for _,item_table in pairs(self.tab_item_table) do
|
||||
for k,v in ipairs(item_table) do
|
||||
table.insert(main_menu.item_table, v)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
main_menu.close_callback = function ()
|
||||
UIManager:close(menu_container)
|
||||
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:onTapShowMenu()
|
||||
self:onShowMenu()
|
||||
return true
|
||||
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
|
||||
|
||||
@@ -43,10 +43,24 @@ rather than class variables.
|
||||
--]]
|
||||
Widget = EventListener:new()
|
||||
|
||||
function Widget:new(o)
|
||||
--[[
|
||||
Use this method to define a class that's inherited from current class.
|
||||
It only setup the metabale (or prototype chain) and will not initiatie
|
||||
a real instance, i.e. call self:init()
|
||||
--]]
|
||||
function Widget:extend(o)
|
||||
local o = o or {}
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
return o
|
||||
end
|
||||
|
||||
--[[
|
||||
Use this method to initiatie a instance of a class, don't use it for class
|
||||
definition.
|
||||
--]]
|
||||
function Widget:new(o)
|
||||
o = self:extend(o)
|
||||
-- Both o._init and o.init are called on object create. But o._init is used
|
||||
-- for base widget initialization (basic component used to build other
|
||||
-- widgets). While o.init is for higher level widgets, for example Menu
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
require "ui/widget/menu"
|
||||
|
||||
FileChooser = Menu:new{
|
||||
FileChooser = Menu:extend{
|
||||
height = Screen:getHeight(),
|
||||
width = Screen:getWidth(),
|
||||
no_title = true,
|
||||
path = lfs.currentdir(),
|
||||
parent = nil,
|
||||
show_hidden = false,
|
||||
@@ -10,7 +11,8 @@ FileChooser = Menu:new{
|
||||
}
|
||||
|
||||
function FileChooser:init()
|
||||
self:changeToPath(self.path)
|
||||
self:updateItemTableFromPath(self.path)
|
||||
Menu.init(self) -- call parent's init()
|
||||
end
|
||||
|
||||
function FileChooser:compressPath(item_path)
|
||||
@@ -22,11 +24,12 @@ function FileChooser:compressPath(item_path)
|
||||
return path
|
||||
end
|
||||
|
||||
function FileChooser:changeToPath(path)
|
||||
function FileChooser:updateItemTableFromPath(path)
|
||||
path = self:compressPath(path)
|
||||
local dirs = {}
|
||||
local files = {}
|
||||
self.path = path
|
||||
|
||||
for f in lfs.dir(self.path) do
|
||||
if self.show_hidden or not string.match(f, "^%.[^.]") then
|
||||
local filename = self.path.."/"..f
|
||||
@@ -53,15 +56,16 @@ function FileChooser:changeToPath(path)
|
||||
for _, file in ipairs(files) do
|
||||
table.insert(self.item_table, { text = file, path = self.path.."/"..file })
|
||||
end
|
||||
end
|
||||
|
||||
Menu.init(self) -- call parent's init()
|
||||
function FileChooser:changeToPath(path)
|
||||
self:updateItemTableFromPath(path)
|
||||
self:updateItems(1)
|
||||
end
|
||||
|
||||
function FileChooser:onMenuSelect(item)
|
||||
if lfs.attributes(item.path, "mode") == "directory" then
|
||||
UIManager:close(self)
|
||||
self:changeToPath(item.path)
|
||||
UIManager:show(self)
|
||||
else
|
||||
self:onFileSelect(item.path)
|
||||
end
|
||||
|
||||
@@ -238,6 +238,9 @@ Menu = FocusManager:new{
|
||||
|
||||
-- set this to true to not paint as popup menu
|
||||
is_borderless = false,
|
||||
-- if you want to embed the menu widget into another widget, set
|
||||
-- this to false
|
||||
is_popout = true,
|
||||
-- set this to true to add close button
|
||||
has_close_button = true,
|
||||
-- close_callback is a function, which is executed when menu is closed
|
||||
@@ -260,7 +263,7 @@ function Menu:_recalculateDimen()
|
||||
-- we need to substract border, margin and padding
|
||||
self.item_dimen.w = self.item_dimen.w - 14
|
||||
end
|
||||
self.perpage = math.floor(self.dimen.h / self.item_dimen.h) - 2
|
||||
self.perpage = math.floor((self.dimen.h - self.dimen.x) / self.item_dimen.h) - 2
|
||||
self.page_num = math.ceil(#self.item_table / self.perpage)
|
||||
end
|
||||
|
||||
@@ -310,12 +313,15 @@ function Menu:init()
|
||||
self.page_info_text,
|
||||
self.page_info_right_chev
|
||||
}
|
||||
|
||||
-- group for menu layout
|
||||
local content = VerticalGroup:new{
|
||||
self.title_bar,
|
||||
self.item_group,
|
||||
self.page_info,
|
||||
}
|
||||
if not self.no_title then
|
||||
table.insert(content, 1, self.title_bar)
|
||||
end
|
||||
-- maintain reference to content so we can change it later
|
||||
self.content_group = content
|
||||
|
||||
@@ -348,16 +354,19 @@ function Menu:init()
|
||||
menu = self,
|
||||
})
|
||||
end
|
||||
self.ges_events.TapCloseAllMenus = {
|
||||
GestureRange:new{
|
||||
ges = "tap",
|
||||
range = Geom:new{
|
||||
x = 0, y = 0,
|
||||
w = Screen:getWidth(),
|
||||
h = Screen:getHeight(),
|
||||
-- watch for outer region if it's a self contained widget
|
||||
if self.is_popout then
|
||||
self.ges_events.TapCloseAllMenus = {
|
||||
GestureRange:new{
|
||||
ges = "tap",
|
||||
range = Geom:new{
|
||||
x = 0, y = 0,
|
||||
w = Screen:getWidth(),
|
||||
h = Screen:getHeight(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
self.ges_events.Swipe = {
|
||||
GestureRange:new{
|
||||
ges = "swipe",
|
||||
@@ -399,6 +408,11 @@ function Menu:updateItems(select_number)
|
||||
self.content_group:resetLayout()
|
||||
self:_recalculateDimen()
|
||||
|
||||
-- default to select the first item
|
||||
if not select_number then
|
||||
select_number = 1
|
||||
end
|
||||
|
||||
for c = 1, self.perpage do
|
||||
-- calculate index in item_table
|
||||
local i = (self.page - 1) * self.perpage + c
|
||||
|
||||
137
reader.lua
137
reader.lua
@@ -4,35 +4,16 @@ require "defaults"
|
||||
package.path = "./frontend/?.lua"
|
||||
package.cpath = "/usr/lib/lua/?.so"
|
||||
require "ui/uimanager"
|
||||
require "ui/widget/filechooser"
|
||||
require "ui/widget/infomessage"
|
||||
require "ui/readerui"
|
||||
require "document/document"
|
||||
require "settings"
|
||||
require "dbg"
|
||||
require "gettext"
|
||||
require "apps/filemanager/fm"
|
||||
|
||||
Profiler = nil
|
||||
|
||||
HomeMenu = InputContainer:new{
|
||||
item_table = {},
|
||||
key_events = {
|
||||
TapShowMenu = { {"Home"}, doc = _("Show Home Menu")},
|
||||
},
|
||||
ges_events = {
|
||||
TapShowMenu = {
|
||||
GestureRange:new{
|
||||
ges = "tap",
|
||||
range = Geom:new{
|
||||
x = 0, y = 0,
|
||||
w = Screen:getWidth(),
|
||||
h = 25,
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
function exitReader()
|
||||
if Profiler ~= nil then
|
||||
Profiler:stop()
|
||||
@@ -64,70 +45,7 @@ function exitReader()
|
||||
os.exit(0)
|
||||
end
|
||||
|
||||
function HomeMenu:setUpdateItemTable()
|
||||
function readHistDir(order_arg, re)
|
||||
local pipe_out = io.popen("ls "..order_arg.." -1 ./history")
|
||||
for f in pipe_out:lines() do
|
||||
table.insert(re, {
|
||||
dir = DocSettings:getPathFromHistory(f),
|
||||
name = DocSettings:getNameFromHistory(f),
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
local hist_sub_item_table = {}
|
||||
local last_files = {}
|
||||
readHistDir("-c", last_files)
|
||||
for _,v in pairs(last_files) do
|
||||
table.insert(hist_sub_item_table, {
|
||||
text = v.name,
|
||||
callback = function()
|
||||
showReader(v.dir .. "/" .. v.name)
|
||||
end
|
||||
})
|
||||
end
|
||||
table.insert(self.item_table, {
|
||||
text = _("Last documents"),
|
||||
sub_item_table = hist_sub_item_table,
|
||||
})
|
||||
|
||||
table.insert(self.item_table, {
|
||||
text = _("Exit"),
|
||||
callback = function()
|
||||
exitReader()
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
function HomeMenu:onTapShowMenu()
|
||||
self.item_table = {}
|
||||
self:setUpdateItemTable()
|
||||
|
||||
local menu_container = CenterContainer:new{
|
||||
ignore = "height",
|
||||
dimen = Screen:getSize(),
|
||||
}
|
||||
|
||||
local home_menu = Menu:new{
|
||||
show_parent = menu_container,
|
||||
title = _("Home menu"),
|
||||
item_table = self.item_table,
|
||||
width = Screen:getWidth() - 100,
|
||||
}
|
||||
|
||||
menu_container[1] = home_menu
|
||||
|
||||
home_menu.close_callback = function ()
|
||||
UIManager:close(menu_container)
|
||||
end
|
||||
|
||||
UIManager:show(menu_container)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
function showReader(file, pass)
|
||||
function showReaderUI(file, pass)
|
||||
local document = DocumentRegistry:openDocument(file)
|
||||
if not document then
|
||||
UIManager:show(InfoMessage:new{
|
||||
@@ -147,47 +65,14 @@ function showReader(file, pass)
|
||||
end
|
||||
|
||||
function showHomePage(path)
|
||||
local exclude_dirs = {"%.sdr$"}
|
||||
|
||||
local HomePage = InputContainer:new{
|
||||
}
|
||||
|
||||
local FileManager = FileChooser:new{
|
||||
show_parent = HomePage,
|
||||
title = _("FileManager"),
|
||||
path = path,
|
||||
width = Screen:getWidth(),
|
||||
height = Screen:getHeight(),
|
||||
is_borderless = true,
|
||||
has_close_button = true,
|
||||
dir_filter = function(dirname)
|
||||
for _, pattern in ipairs(exclude_dirs) do
|
||||
if dirname:match(pattern) then return end
|
||||
end
|
||||
return true
|
||||
end,
|
||||
file_filter = function(filename)
|
||||
if DocumentRegistry:getProvider(filename) then
|
||||
return true
|
||||
end
|
||||
UIManager:show(FileManager:new{
|
||||
dimen = Screen:getSize(),
|
||||
root_path = path,
|
||||
onExit = function()
|
||||
exitReader()
|
||||
UIManager:quit()
|
||||
end
|
||||
}
|
||||
|
||||
table.insert(HomePage, FileManager)
|
||||
table.insert(HomePage, HomeMenu)
|
||||
|
||||
function FileManager:onFileSelect(file)
|
||||
showReader(file)
|
||||
return true
|
||||
end
|
||||
|
||||
function FileManager:onClose()
|
||||
exitReader()
|
||||
--UIManager:quit()
|
||||
return true
|
||||
end
|
||||
|
||||
UIManager:show(HomePage)
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
@@ -282,11 +167,11 @@ if ARGV[argidx] and ARGV[argidx] ~= "" then
|
||||
if lfs.attributes(ARGV[argidx], "mode") == "directory" then
|
||||
showHomePage(ARGV[argidx])
|
||||
elseif lfs.attributes(ARGV[argidx], "mode") == "file" then
|
||||
showReader(ARGV[argidx])
|
||||
showReaderUI(ARGV[argidx])
|
||||
end
|
||||
UIManager:run()
|
||||
elseif last_file and lfs.attributes(last_file, "mode") == "file" then
|
||||
showReader(last_file)
|
||||
showReaderUI(last_file)
|
||||
UIManager:run()
|
||||
else
|
||||
return showusage()
|
||||
|
||||
Reference in New Issue
Block a user