mirror of
https://github.com/koreader/koreader
synced 2024-10-31 21:20:20 +00:00
772dda7e57
We shouldn't crash the whole KPV application just because for some reason we can't obtain the valid unpacked size of the zip archive.
253 lines
7.7 KiB
Lua
253 lines
7.7 KiB
Lua
require "rendertext"
|
|
require "keys"
|
|
require "graphics"
|
|
require "font"
|
|
require "inputbox"
|
|
require "dialog"
|
|
require "settings"
|
|
require "readerchooser"
|
|
|
|
FileInfo = {
|
|
title_H = 40, -- title height
|
|
spacing = 36, -- spacing between lines
|
|
foot_H = 28, -- foot height
|
|
margin_H = 10, -- horisontal margin
|
|
-- state buffer
|
|
pagedirty = true,
|
|
result = {},
|
|
commands = nil,
|
|
items = 0,
|
|
pathfile = "",
|
|
}
|
|
|
|
function FileInfo:FileCreated(fname, attr)
|
|
return os.date("%d %b %Y, %H:%M:%S", lfs.attributes(fname,attr))
|
|
end
|
|
|
|
function FileInfo:FormatSize(size)
|
|
if not tonumber(size) then
|
|
return "Invalid"
|
|
elseif size < 1024 then
|
|
return size.." Bytes"
|
|
elseif size < 2^20 then
|
|
return string.format("%.2f", size/2^10).."KB ("..size.." Bytes)"
|
|
elseif size < 2^30 then
|
|
return string.format("%.2f", size/2^20).."MB ("..size.." Bytes)"
|
|
else
|
|
return string.format("%.2f", size/2^30).."GB ("..size.." Bytes)"
|
|
end
|
|
end
|
|
|
|
function FileExists(path)
|
|
local f = io.open(path, "r")
|
|
if f then
|
|
f:close()
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
function getUnpackedZipSize(zipfile)
|
|
-- adding quotes allows us to avoid crash on zips which filename contains space(s)
|
|
local cmd='unzip -l \"'..zipfile..'\" | tail -1 | sed -e "s/^ *\\([0-9][0-9]*\\) *.*/\\1/"'
|
|
local p = io.popen(cmd, "r")
|
|
local res = p:read("*a")
|
|
p:close()
|
|
res = string.gsub(res, "[\n\r]+", "")
|
|
return tonumber(res)
|
|
end
|
|
|
|
function FileInfo:formatDiskSizeInfo()
|
|
local t, f = util.df(".")
|
|
return self:FormatSize(f)..string.format(", %.2f", 100*f/t).."%"
|
|
end
|
|
|
|
function FileInfo:getFolderContent()
|
|
InfoMessage:inform("Scanning folder...", nil, 1, MSG_AUX)
|
|
local tmp = io.popen('du -a \"'..self.pathfile..'\"', "r")
|
|
local dirs, files, books, size, name, output, ftype, j = -1, 0, 0, 0
|
|
for output in tmp:lines() do
|
|
j = output:find("/")
|
|
name = output:sub(j, -1)
|
|
size = tonumber(output:sub(1, j-1)) -- in kB
|
|
j = lfs.attributes(name, "mode")
|
|
if j == "file" then
|
|
files = files + 1
|
|
ftype = string.match(name, ".+%.([^.]+)")
|
|
if ftype and ReaderChooser:getReaderByType(string.lower(ftype)) then
|
|
books = books + 1
|
|
end
|
|
elseif j == "directory" then
|
|
dirs = dirs + 1
|
|
end
|
|
end
|
|
tmp:close()
|
|
-- add 2 entries; might be joined / splitted
|
|
table.insert(self.result, {dir = "Contents", name = dirs.." sub-folder(s) / "..files.." file(s) / "..books.." book(s)"})
|
|
table.insert(self.result, {dir = "Size", name = self:FormatSize(size*1024)})
|
|
end
|
|
|
|
function FileInfo:init(path, fname)
|
|
-- add commands only once
|
|
if not self.commands then
|
|
self:addAllCommands()
|
|
end
|
|
|
|
if fname then
|
|
self.pathfile = path.."/"..fname
|
|
table.insert(self.result, {dir = "Name", name = fname} )
|
|
self.commands:add({KEY_ENTER, KEY_FW_PRESS}, nil, "Enter",
|
|
"open document",
|
|
function(self)
|
|
openFile(self.pathfile)
|
|
self.pagedirty = true
|
|
end)
|
|
else
|
|
self.pathfile = path.."/"
|
|
-- extracting folder name
|
|
local i, j = 0, 0
|
|
while true do
|
|
i = string.find(path, "/", i+1)
|
|
if i == nil then break else j=i end
|
|
end
|
|
table.insert(self.result, {dir = "Name", name = path:sub(j+1,-1) } )
|
|
table.insert(self.result, {dir = "Path", name = path:sub(1,j) } )
|
|
self.commands:add({KEY_ENTER, KEY_FW_PRESS}, nil, "Enter",
|
|
"goto folder",
|
|
function(self)
|
|
return "goto"
|
|
end)
|
|
end
|
|
|
|
local tmp, output
|
|
if fname then -- file info
|
|
table.insert(self.result, {dir = "Path", name = path.."/"} )
|
|
table.insert(self.result, {dir = "Size", name = self:FormatSize(lfs.attributes(self.pathfile, "size"))} )
|
|
-- total size of all unzipped entries for zips
|
|
local match = string.match(fname, ".+%.([^.]+)")
|
|
if match and string.lower(match) == "zip" then
|
|
table.insert(self.result, {dir = "Unpacked", name = self:FormatSize(getUnpackedZipSize(self.pathfile))} )
|
|
end
|
|
else -- folder info
|
|
self:getFolderContent()
|
|
end
|
|
|
|
table.insert(self.result, {dir = "Free space", name = self:formatDiskSizeInfo()})
|
|
table.insert(self.result, {dir = "Status changed", name = self:FileCreated(self.pathfile, "change")})
|
|
table.insert(self.result, {dir = "Modified", name = self:FileCreated(self.pathfile, "modification")})
|
|
table.insert(self.result, {dir = "Accessed", name = self:FileCreated(self.pathfile, "access")})
|
|
|
|
if fname then
|
|
-- if the document was already opened
|
|
local history = DocToHistory(self.pathfile)
|
|
if not FileExists(history) then
|
|
table.insert(self.result, {dir = "Last read", name = "Never"})
|
|
else
|
|
table.insert(self.result, {dir = "Last read", name = self:FileCreated(history, "change")})
|
|
local file_type = string.lower(string.match(self.pathfile, ".+%.([^.]+)"))
|
|
local to_search, add, factor = "[\"last_percent\"]", "%", 100
|
|
if ReaderChooser:getReaderByType(file_type) ~= CREReader then
|
|
to_search = "[\"last_page\"]"
|
|
add = " pages"
|
|
factor = 1
|
|
end
|
|
for line in io.lines(history) do
|
|
if string.match(line, "%b[]") == to_search then
|
|
local cdc = tonumber(string.match(line, "%d+")) / factor
|
|
table.insert(self.result, {dir = "Completed", name = string.format("%d", cdc)..add })
|
|
end
|
|
end
|
|
end
|
|
end
|
|
self.items = #self.result
|
|
end
|
|
|
|
function FileInfo:show(path, name)
|
|
-- at first, one has to test whether the file still exists or not: necessary for last documents
|
|
if name and not FileExists(path.."/"..name) then return nil end
|
|
-- then goto main functions
|
|
self:init(path,name)
|
|
-- local variables
|
|
local cface, lface, tface, fface, width, xrcol, c, dy, ev, keydef, ret_code
|
|
while true do
|
|
if self.pagedirty then
|
|
-- refresh the fonts, if not yet defined or updated via 'F'
|
|
cface = Font:getFace("cfont", 22)
|
|
lface = Font:getFace("tfont", 22)
|
|
tface = Font:getFace("tfont", 25)
|
|
fface = Font:getFace("ffont", 16)
|
|
-- drawing
|
|
fb.bb:paintRect(0, 0, G_width, G_height, 0)
|
|
DrawTitle(name and "Document Information" or "Folder Information", self.margin_H, 0, self.title_H, 3, tface)
|
|
-- now calculating xrcol-position for the right column
|
|
width = 0
|
|
for c = 1, self.items do
|
|
width = math.max(sizeUtf8Text(0, G_width, lface, self.result[c].dir, true).x, width)
|
|
end
|
|
xrcol = self.margin_H + width + 25
|
|
dy = 5 -- to store the y-position correction 'cause of the multiline drawing
|
|
for c = 1, self.items do
|
|
y = self.title_H + self.spacing * c + dy
|
|
renderUtf8Text(fb.bb, self.margin_H, y, lface, self.result[c].dir, true)
|
|
dy = dy + renderUtf8Multiline(fb.bb, xrcol, y, cface, self.result[c].name, true,
|
|
G_width - self.margin_H - xrcol, 1.65).y - y
|
|
end
|
|
-- NuPogodi, 29.09.12: restored footer > to see 'Press H for help'
|
|
DrawFooter("Page 1 of 1",fface,self.foot_H)
|
|
fb:refresh(0)
|
|
self.pagedirty = false
|
|
end
|
|
-- waiting for user's commands
|
|
ev = input.saveWaitForEvent()
|
|
ev.code = adjustKeyEvents(ev)
|
|
if ev.type == EV_KEY and ev.value ~= EVENT_VALUE_KEY_RELEASE then
|
|
keydef = Keydef:new(ev.code, getKeyModifier())
|
|
command = self.commands:getByKeydef(keydef)
|
|
if command ~= nil then ret_code = command.func(self, keydef) end
|
|
if ret_code == "break" or ret_code == "goto" then break end
|
|
end -- if ev.type
|
|
end -- while true
|
|
self.pagedirty = true
|
|
self.result = {}
|
|
return ret_code
|
|
end
|
|
|
|
function FileInfo:addAllCommands()
|
|
self.commands = Commands:new{}
|
|
self.commands:add(KEY_SPACE, nil, "Space",
|
|
"refresh page manually",
|
|
function(self)
|
|
self.pagedirty = true
|
|
end
|
|
)
|
|
self.commands:add(KEY_H,nil,"H",
|
|
"show help page",
|
|
function(self)
|
|
HelpPage:show(0, G_height, self.commands)
|
|
self.pagedirty = true
|
|
end
|
|
)
|
|
self.commands:add({KEY_F, KEY_AA}, nil, "F, Aa",
|
|
"change font faces",
|
|
function(self)
|
|
Font:chooseFonts()
|
|
self.pagedirty = true
|
|
end
|
|
)
|
|
self.commands:add(KEY_L, nil, "L",
|
|
"last documents",
|
|
function(self)
|
|
FileHistory:init()
|
|
FileHistory:choose("")
|
|
self.pagedirty = true
|
|
end
|
|
)
|
|
self.commands:add({KEY_BACK, KEY_FW_LEFT}, nil, "Back, FW-Left",
|
|
"back",
|
|
function(self)
|
|
return "break"
|
|
end
|
|
)
|
|
end
|