2
0
mirror of https://github.com/koreader/koreader synced 2024-10-31 21:20:20 +00:00
koreader/fileinfo.lua
Tigran Aivazian 1a3371c5bf Two fixes from NuPogodi
1. ATM, the footers in selectmenu.lua & helppage.lua are left-adjusted,
these also contain the prompt for users how to call help
(selectmenu.lua) and how to go back (helppage.lua). By minor correction
to function DrawFooter() in filechooser.lua, one may readily make the
rest footers to look in a similar way.
2. When writing the code of inputbox.lua, I (NuPogodi) left the wrong
command to delete the 1st entry in the math function list
(called in calculator mode by pressing Alt-M).
2012-09-29 19:03:29 +01:00

260 lines
7.7 KiB
Lua

require "rendertext"
require "keys"
require "graphics"
require "font"
require "inputbox"
require "dialog"
require "settings"
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 = assert(p:read("*a"))
p:close()
res = string.gsub(res, "[\n\r]+", "")
return tonumber(res)
end
function getDiskSizeInfo()
local t, f = util.df(".")
return { total = t, free = f }
end
function FileInfo:formatDiskSizeInfo()
local s = getDiskSizeInfo()
if s then
return self:FormatSize(s.free)..string.format(", %.2f", 100*s.free/s.total).."%"
end
return "?"
end
function FileInfo:getFolderContent()
InfoMessage:show("Scanning folder...", 1)
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 ext:getReader(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 ext:getReader(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",
"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",
"back",
function(self)
return "break"
end
)
end