Merge pull request #1817 from koreader/statistics_ui

migrate statistics ui to use KeyValuePage
pull/1819/head
Huang Xin 8 years ago
commit 271b79b039

@ -71,8 +71,8 @@ script:
- make all
- travis_retry make testfront
- luajit $(which luacheck) --no-color -q frontend | tee ./luacheck.out
- test $(grep Total ./luacheck.out | awk '{print $2}') -le 238
- test $(grep Total ./luacheck.out | awk '{print $2}') -le 196
after_success:
- make coverage
- cd koreader-*/koreader && luacov-coveralls -v
- cd koreader-*/koreader && luajit $(which luacov-coveralls) -v

@ -1 +1 @@
Subproject commit fe0a527ddb8918127917b244c8c2ceb54b6a2705
Subproject commit 8a305a81a7a04e2f6df5cb336ad79cb17432fb4d

@ -22,6 +22,10 @@ function DataStorage:getDataDir()
return data_dir
end
function DataStorage:getHistoryDir()
return self:getDataDir() .. "/history"
end
local function initDataDir()
local data_dir = DataStorage:getDataDir()
local sub_data_dirs = {"cache", "clipboard", "data", "history", "ota", "screenshots"}

@ -6,10 +6,11 @@ local DataStorage = require("datastorage")
local UIManager = require("ui/uimanager")
local DocSettings = require("docsettings")
local Menu = require("ui/widget/menu")
local joinPath = require("ffi/util").joinPath
local Screen = require("device").screen
local _ = require("gettext")
local history_dir = DataStorage:getDataDir() .. "/history/"
local history_dir = DataStorage:getHistoryDir()
local FileManagerHistory = InputContainer:extend{
hist_menu_title = _("History"),
@ -30,7 +31,7 @@ function FileManagerHistory:onMenuHold(item)
{
text = _("Remove this item from history"),
callback = function()
os.remove(history_dir..item.histfile)
os.remove(joinPath(history_dir, item.histfile))
self._manager:updateItemTable()
UIManager:close(self.histfile_dialog)
end,
@ -82,7 +83,7 @@ function FileManagerHistory:updateItemTable()
self.hist = {}
for f in lfs.dir(history_dir) do
local path = history_dir..f
local path = joinPath(history_dir, f)
if lfs.attributes(path, "mode") == "file" then
local name = DocSettings:getNameFromHistory(f)
table.insert(self.hist, {

@ -12,7 +12,6 @@ local BBoxWidget = require("ui/widget/bboxwidget")
local HorizontalSpan = require("ui/widget/horizontalspan")
local Button = require("ui/widget/button")
local Math = require("optmath")
local DEBUG = require("dbg")
local Blitbuffer = require("ffi/blitbuffer")
local PageCropDialog = VerticalGroup:new{

@ -2,7 +2,6 @@ local InputContainer = require("ui/widget/container/inputcontainer")
local RightContainer = require("ui/widget/container/rightcontainer")
local ImageWidget = require("ui/widget/imagewidget")
local GestureRange = require("ui/gesturerange")
local UIManager = require("ui/uimanager")
local Device = require("device")
local Geom = require("ui/geometry")
local Screen = require("device").screen

@ -8,7 +8,6 @@ local Screen = require("device").screen
local Input = require("device").input
local Event = require("ui/event")
local UIManager = require("ui/uimanager")
local DEBUG = require("dbg")
local T = require("ffi/util").template
local _ = require("gettext")

@ -14,7 +14,6 @@ local Screen = require("device").screen
local Geom = require("ui/geometry")
local Event = require("ui/event")
local Font = require("ui/font")
local DEBUG = require("dbg")
local _ = require("gettext")
local util = require("util")
@ -54,7 +53,7 @@ function ReaderFooter:init()
book_time_to_read = true,
chapter_time_to_read = true,
}
local text_default = ""
local text_default
if self.settings.all_at_once then
local info = {}
if self.settings.battery then

@ -1,5 +1,6 @@
local InputContainer = require("ui/widget/container/inputcontainer")
local UIManager = require("ui/uimanager")
local JSON = require("json")
local InfoMessage = require("ui/widget/infomessage")
local T = require("ffi/util").template
local _ = require("gettext")
@ -11,32 +12,35 @@ local ReaderHyphenation = InputContainer:new{
}
function ReaderHyphenation:init()
local lang_data_file = assert(io.open("./data/hyph/languages.json"), "r")
lang_data = json.decode(lang_data_file:read("*all"))
self.lang_table = {}
self.hyph_table = {}
self.hyph_alg = cre.getSelectedHyphDict()
for k,v in ipairs(lang_data) do
table.insert(self.hyph_table, {
text = v.name,
callback = function()
self.hyph_alg = v.filename
UIManager:show(InfoMessage:new{
text = T( _("Changed hyphenation to %1."), v.name),
})
self.ui.document:setHyphDictionary(v.filename)
self.ui.toc:onUpdateToc()
end,
checked_func = function()
return v.filename == self.hyph_alg
end
})
self.lang_table[v.language] = v.filename
if v.aliases then
for i,alias in ipairs(v.aliases) do
self.lang_table[alias] = v.filename
local lang_data_file = assert(io.open("./data/hyph/languages.json"), "r")
local ok, lang_data = pcall(JSON.decode, lang_data_file:read("*all"))
if ok and lang_data then
for k,v in ipairs(lang_data) do
table.insert(self.hyph_table, {
text = v.name,
callback = function()
self.hyph_alg = v.filename
UIManager:show(InfoMessage:new{
text = T(_("Changed hyphenation to %1."), v.name),
})
self.ui.document:setHyphDictionary(v.filename)
self.ui.toc:onUpdateToc()
end,
checked_func = function()
return v.filename == self.hyph_alg
end
})
self.lang_table[v.language] = v.filename
if v.aliases then
for i,alias in ipairs(v.aliases) do
self.lang_table[alias] = v.filename
end
end
end
end

@ -6,7 +6,6 @@ local Geom = require("ui/geometry")
local Screen = require("device").screen
local Device = require("device")
local Event = require("ui/event")
local DEBUG = require("dbg")
local _ = require("gettext")
local ReaderLink = InputContainer:new{

@ -318,17 +318,9 @@ function ReaderPaging:onSwipe(arg, ges)
elseif self.page_flipping_mode and self.original_page then
self:gotoPage(self.original_page)
elseif ges.direction == "west" then
if DCHANGE_WEST_SWIPE_TO_EAST then
self:onPagingRel(-1)
else
self:onPagingRel(1)
end
self:onPagingRel(1)
elseif ges.direction == "east" then
if DCHANGE_EAST_SWIPE_TO_WEST then
self:onPagingRel(1)
else
self:onPagingRel(-1)
end
self:onPagingRel(-1)
else
-- trigger full refresh
UIManager:setDirty(nil, "full")

@ -14,8 +14,7 @@ local ReaderPanning = InputContainer:new{
}
function ReaderPanning:init()
if Device:isTouchDevice() then
else
if Device:hasKeyboard() then
self.key_events = {
-- these will all generate the same event, just with different arguments
MoveUp = {

@ -261,17 +261,9 @@ end
function ReaderRolling:onSwipe(arg, ges)
if ges.direction == "west" or ges.direction == "north" then
if DCHANGE_WEST_SWIPE_TO_EAST then
self:onGotoViewRel(-1)
else
self:onGotoViewRel(1)
end
self:onGotoViewRel(1)
elseif ges.direction == "east" or ges.direction == "south" then
if DCHANGE_EAST_SWIPE_TO_WEST then
self:onGotoViewRel(1)
else
self:onGotoViewRel(-1)
end
self:onGotoViewRel(-1)
end
end

@ -38,14 +38,14 @@ function ReaderStatus:addToMainMenu(tab_item_table)
end
function ReaderStatus:showStatus()
local statusWidget = StatusWidget:new {
local status_page = StatusWidget:new {
thumbnail = self.document:getCoverPageImage(),
props = self.document:getProps(),
document = self.document,
settings = self.settings,
view = self.view,
}
UIManager:show(statusWidget)
UIManager:show(status_page)
end
function ReaderStatus:onPageUpdate(pageno)
@ -66,4 +66,3 @@ function ReaderStatus:onReadSettings(config)
end
return ReaderStatus

@ -9,7 +9,6 @@ local Screen = require("device").screen
local Device = require("device")
local Event = require("ui/event")
local Font = require("ui/font")
local DEBUG = require("dbg")
local _ = require("gettext")
local ReaderToc = InputContainer:new{
@ -143,7 +142,7 @@ function ReaderToc:getTocTicks(level)
depth = v.depth
end
else
local depth = nil
local depth
if level > 0 then
depth = level
else
@ -261,7 +260,6 @@ end
function ReaderToc:onShowToc()
self:fillToc()
local max_depth = self:getMaxDepth()
-- build menu items
if #self.toc > 0 and not self.toc[1].text then
for _,v in ipairs(self.toc) do

@ -4,7 +4,6 @@ local lfs = require("libs/libkoreader-lfs")
local UIManager = require("ui/uimanager")
local Screen = require("device").screen
local Event = require("ui/event")
local DEBUG = require("dbg")
local T = require("ffi/util").template
local _ = require("gettext")
@ -100,7 +99,6 @@ end
function ReaderTypeset:setStyleSheet(new_css)
if new_css ~= self.css then
--DEBUG("setting css to ", new_css)
self.css = new_css
self.ui.document:setStyleSheet(new_css)
self.ui:handleEvent(Event:new("UpdatePos"))

@ -185,7 +185,7 @@ function ReaderView:screenToPageTransform(pos)
end
else
pos.page = self.ui.document:getCurrentPage()
local last_y = self.ui.document:getCurrentPos()
-- local last_y = self.ui.document:getCurrentPos()
DEBUG("document has no pages at", pos)
return pos
end
@ -293,8 +293,8 @@ function ReaderView:getCurrentPageList()
end
function ReaderView:getScrollPagePosition(pos)
local x_p, y_p
local x_s, y_s = pos.x, pos.y
local x_p, y_p = nil, nil
for _, state in ipairs(self.page_states) do
if y_s < state.visible_area.h + state.offset.y then
y_p = (state.visible_area.y + y_s - state.offset.y) / state.zoom
@ -482,7 +482,6 @@ end
This method is supposed to be only used by ReaderPaging
--]]
function ReaderView:recalculate()
local page_size = nil
if self.ui.document.info.has_pages and self.state.page then
self.page_area = self:getPageArea(
self.state.page,

@ -1,7 +1,6 @@
local ReaderDictionary = require("apps/reader/modules/readerdictionary")
local Translator = require("ui/translator")
local Wikipedia = require("ui/wikipedia")
local Screen = require("device").screen
local DEBUG = require("dbg")
local _ = require("gettext")
@ -29,7 +28,8 @@ function ReaderWikipedia:onLookupWikipedia(word, box)
-- seems lower case phrase has higher hit rate
word = string.lower(word)
local results = {}
local ok, pages = pcall(Wikipedia.wikintro, Wikipedia, word, lang)
local pages
ok, pages = pcall(Wikipedia.wikintro, Wikipedia, word, lang)
if ok and pages then
for pageid, page in pairs(pages) do
local result = {

@ -424,6 +424,12 @@ function GestureDetector:handleSwipe(tev)
y = self.first_tevs[slot].y,
w = 0, h = 0,
}
-- TODO: dirty hack for some weird devices, replace it with better solution
if swipe_direction == "west" and DCHANGE_WEST_SWIPE_TO_EAST then
swipe_direction = "east"
elseif swipe_direction == "east" and DCHANGE_EAST_SWIPE_TO_WEST then
swipe_direction = "west"
end
DEBUG("swipe", swipe_direction, swipe_distance, "detected in slot", slot)
self:clearState(slot)
return {

@ -104,7 +104,7 @@ function NickelConf.frontLightLevel.set(new_intensity)
kobo_conf:close()
end
kobo_conf_w = assert(io.open(kobo_conf_path, "w"))
local kobo_conf_w = assert(io.open(kobo_conf_path, "w"))
for i, line in ipairs(lines) do
kobo_conf_w:write(line, "\n")
end

@ -1,6 +1,6 @@
local BasePowerD = require("device/generic/powerd")
local ffi = require("ffi")
local inkview = ffi.load("inkview")
-- local inkview = ffi.load("inkview")
ffi.cdef[[
int IsCharging();

@ -4,14 +4,14 @@ local dump = require("dump")
local DocSettings = {}
local history_dir = DataStorage:getDataDir() .. "/history/"
local history_dir = DataStorage:getHistoryDir()
function DocSettings:getSidecarDir(doc_path)
return doc_path:match("(.*)%.")..".sdr"
end
function DocSettings:getHistoryPath(fullpath)
return history_dir .. "[" .. fullpath:gsub("(.*/)([^/]+)","%1] %2"):gsub("/","#") .. ".lua"
return history_dir .. "/[" .. fullpath:gsub("(.*/)([^/]+)","%1] %2"):gsub("/","#") .. ".lua"
end
function DocSettings:getPathFromHistory(hist_name)

@ -1,11 +1,9 @@
local CreOptions = require("ui/data/creoptions")
local Document = require("document/document")
local Configurable = require("configurable")
local Blitbuffer = require("ffi/blitbuffer")
local lfs = require("libs/libkoreader-lfs")
local DataStorage = require("datastorage")
local Geom = require("ui/geometry")
local Device = require("device")
local Screen = require("device").screen
local Font = require("ui/font")
local DEBUG = require("dbg")
@ -190,7 +188,7 @@ function CreDocument:getTextFromPositions(pos0, pos1)
local text_range = self._document:getTextFromPositions(pos0.x, pos0.y, pos1.x, pos1.y)
DEBUG("CreDocument: get text range", text_range)
if text_range then
local line_boxes = self:getScreenBoxesFromPositions(text_range.pos0, text_range.pos1)
-- local line_boxes = self:getScreenBoxesFromPositions(text_range.pos0, text_range.pos1)
return {
text = text_range.text,
pos0 = text_range.pos0,

@ -1,10 +1,6 @@
local Geom = require("ui/geometry")
local Cache = require("cache")
local CacheItem = require("cacheitem")
local KoptOptions = require("ui/data/koptoptions")
local Document = require("document/document")
local DrawContext = require("ffi/drawcontext")
local Configurable = require("configurable")
local DjvuDocument = Document:new{
_document = false,

@ -33,8 +33,8 @@ local Document = {
is_edited = false,
}
function Document:new(o)
local o = o or {}
function Document:new(from_o)
local o = from_o or {}
setmetatable(o, self)
self.__index = self
if o._init then o:_init() end
@ -205,7 +205,7 @@ function Document:getUsedBBoxDimensions(pageno, zoom, rotation)
if bbox.y0 < 0 then bbox.y0 = 0 end
if bbox.x1 < 0 then bbox.x1 = 0 end
if bbox.y1 < 0 then bbox.y1 = 0 end
local ubbox_dimen = nil
local ubbox_dimen
if (bbox.x0 >= bbox.x1) or (bbox.y0 >= bbox.y1) then
-- if document's bbox info is corrupted, we use the page size
ubbox_dimen = self:getPageDimensions(pageno, zoom, rotation)
@ -282,7 +282,7 @@ function Document:renderPage(pageno, rect, zoom, rotation, gamma, render_mode)
end
-- prepare cache item with contained blitbuffer
local tile = TileCacheItem:new{
tile = TileCacheItem:new{
persistent = true,
size = size.w * size.h + 64, -- estimation
excerpt = size,

@ -31,9 +31,10 @@ function PdfDocument:init()
else
self:_readMetadata()
end
if not (self.info.number_of_pages > 0) then
-- TODO: handle this
-- if not (self.info.number_of_pages > 0) then
--error("No page found in PDF file")
end
-- end
end
function PdfDocument:unlock(password)

@ -10,6 +10,7 @@ local PicDocument = Document:new{
function PicDocument:init()
if not pic then pic = require("ffi/pic") end
local ok
ok, self._document = pcall(pic.openDocument, self.file)
if not ok then
error("Failed to open jpeg image")

@ -11,8 +11,8 @@ local GestureRange = {
scale = nil,
}
function GestureRange:new(o)
local o = o or {}
function GestureRange:new(from_o)
local o = from_o or {}
setmetatable(o, self)
self.__index = self
return o
@ -29,7 +29,7 @@ function GestureRange:match(gs)
-- e.g. range = function() return self.dimen end
-- for inputcontainer given that the x and y field of `self.dimen` is only
-- filled when the inputcontainer is painted into blitbuffer
local range = nil
local range
if type(self.range) == "function" then
range = self.range()
else

@ -18,7 +18,7 @@ local GlyphCache = Cache:new{
}
-- iterator over UTF8 encoded characters in a string
local function utf8Chars(input)
local function utf8Chars(input_text)
local function read_next_glyph(input, pos)
if string.len(input) < pos then return nil end
local value = string.byte(input, pos)
@ -60,7 +60,7 @@ local function utf8Chars(input)
return pos+bytes_left+1, glyph, string.sub(input, pos, pos+bytes_left)
end
end
return read_next_glyph, input, 1
return read_next_glyph, input_text, 1
end
function RenderText:getGlyph(face, charcode, bold)
@ -81,7 +81,7 @@ function RenderText:getGlyph(face, charcode, bold)
rendered_glyph = fb_face.ftface:renderGlyph(charcode, bold)
--DEBUG("fallback to font", font)
break
end
end
end
end
end

@ -9,7 +9,6 @@ local UIManager = require("ui/uimanager")
local Geom = require("ui/geometry")
local Device = require("device")
local Font = require("ui/font")
local DEBUG = require("dbg")
local _ = require("gettext")
--[[

@ -1,14 +1,24 @@
--[[--
Button widget that shows an "×" and handles closing window when tapped
Example:
local parent_widget = HorizontalGroup:new{}
table.insert(parent_widget, CloseButton:new{
window = parent_widget,
})
UIManager:show(parent_widget)
]]
local InputContainer = require("ui/widget/container/inputcontainer")
local FrameContainer = require("ui/widget/container/framecontainer")
local TextWidget = require("ui/widget/textwidget")
local GestureRange = require("ui/gesturerange")
local Font = require("ui/font")
--[[
a button widget that shows an "×" and handles closing window when tapped
--]]
local CloseButton = InputContainer:new{
align = "right",
overlap_align = "right",
window = nil,
}
@ -23,7 +33,7 @@ function CloseButton:init()
text_widget
}
self.dimen = text_widget:getSize():copy()
self.dimen = text_widget:getSize()
self.ges_events.Close = {
GestureRange:new{

@ -8,11 +8,15 @@ local WidgetContainer = Widget:new()
function WidgetContainer:init()
if self.dimen then
if not self.dimen.w then
self.dimen.w = self[1].getSize().w
end
if not self.dimen.h then
self.dimen.h = self[1].getSize().h
if self.initDimen then
self:initDimen()
else
if not self.dimen.w then
self.dimen.w = self[1].getSize().w
end
if not self.dimen.h then
self.dimen.h = self[1].getSize().h
end
end
end
end

@ -91,9 +91,7 @@ function DictQuickLookup:init()
},
}
table.insert(self.dict_bar,
CloseButton:new{
window = self,
})
CloseButton:new{ window = self, })
end
end

@ -39,6 +39,8 @@ function HorizontalGroup:paintTo(bb, x, y)
widget:paintTo(bb, x + self._offsets[i].x, y)
elseif self.align == "bottom" then
widget:paintTo(bb, x + self._offsets[i].x, y + size.h - self._offsets[i].y)
else
print("[!] invalid alignment for HorizontalGroup", self.align)
end
end
end

@ -0,0 +1,273 @@
--[[--
Widget that presents a multi-page to show key value pairs.
Example:
local Foo = KeyValuePage:new{
title = "Statistics",
kv_pairs = {
{"Current period", "00:00:00"},
-- single or more "-" will generate a solid line
"----------------------------",
{"Page to read", "5"},
{"Time to read", "00:01:00"},
{"Press me", "will invoke the callback",
callback = function() print("hello") end },
},
}
UIManager:show(Foo)
]]
local InputContainer = require("ui/widget/container/inputcontainer")
local FrameContainer = require("ui/widget/container/framecontainer")
local VerticalGroup = require("ui/widget/verticalgroup")
local VerticalSpan = require("ui/widget/verticalspan")
local OverlapGroup = require("ui/widget/overlapgroup")
local LeftContainer = require("ui/widget/container/leftcontainer")
local RightContainer = require("ui/widget/container/rightcontainer")
local LineWidget = require("ui/widget/linewidget")
local Blitbuffer = require("ffi/blitbuffer")
local CloseButton = require("ui/widget/closebutton")
local UIManager = require("ui/uimanager")
local TextWidget = require("ui/widget/textwidget")
local GestureRange = require("ui/gesturerange")
local Geom = require("ui/geometry")
local Font = require("ui/font")
local Device = require("device")
local Screen = Device.screen
local KeyValueTitle = VerticalGroup:new{
kv_page = nil,
title = "",
align = "left",
}
function KeyValueTitle:init()
self.close_button = CloseButton:new{ window = self }
table.insert(self, OverlapGroup:new{
dimen = { w = self.width },
TextWidget:new{
text = self.title,
face = Font:getFace("tfont", 26),
},
self.close_button,
})
self.page_cnt = FrameContainer:new{
padding = 4,
margin = 0,
bordersize = 0,
background = Blitbuffer.COLOR_WHITE,
overlap_offset = {0, -18},
TextWidget:new{
text = "", -- page count
fgcolor = Blitbuffer.COLOR_GREY,
face = Font:getFace("ffont", 16),
},
}
self.title_bottom = OverlapGroup:new{
dimen = { w = self.width, h = Screen:scaleBySize(2) },
LineWidget:new{
dimen = Geom:new{ w = self.width, h = Screen:scaleBySize(2) },
background = Blitbuffer.COLOR_GREY,
style = "solid",
},
self.page_cnt,
}
table.insert(self, self.title_bottom)
table.insert(self, VerticalSpan:new{ width = Screen:scaleBySize(5) })
end
function KeyValueTitle:setPageCount(curr, total)
if total == 1 then
-- remove page count if there is only one page
table.remove(self.title_bottom, 2)
return
end
self.page_cnt[1]:setText(curr .. "/" .. total)
self.page_cnt.overlap_offset[1] = (self.width - self.page_cnt:getSize().w
- self.close_button:getSize().w)
self.title_bottom[2] = self.page_cnt
end
function KeyValueTitle:onClose()
self.kv_page:onClose()
return true
end
local KeyValueItem = InputContainer:new{
key = nil,
value = nil,
cface = Font:getFace("cfont", 24),
width = nil,
height = nil,
}
function KeyValueItem:init()
self.dimen = Geom:new{w = self.width, h = self.height}
if self.callback and Device:isTouchDevice() then
self.ges_events.Tap = {
GestureRange:new{
ges = "tap",
range = self.dimen,
}
}
end
self[1] = OverlapGroup:new{
dimen = self.dimen:copy(),
LeftContainer:new{
dimen = self.dimen:copy(),
TextWidget:new{
text = self.key,
face = self.cface,
}
},
RightContainer:new{
dimen = self.dimen:copy(),
TextWidget:new{
text = self.value,
face = self.cface,
}
}
}
end
function KeyValueItem:onTap()
self.callback()
return true
end
local KeyValuePage = InputContainer:new{
title = "",
width = nil,
height = nil,
-- index for the first item to show
show_page = 1,
}
function KeyValuePage:init()
self.dimen = Geom:new{
w = self.width or Screen:getWidth(),
h = self.height or Screen:getHeight(),
}
if Device:isTouchDevice() then
self.ges_events.Swipe = {
GestureRange:new{
ges = "swipe",
range = self.dimen,
}
}
end
local padding = Screen:scaleBySize(10)
self.item_width = self.dimen.w - 2 * padding
self.item_height = Screen:scaleBySize(30)
-- setup title bar
self.title_bar = KeyValueTitle:new{
title = self.title,
width = self.item_width,
height = self.item_height,
kv_page = self,
}
-- setup main content
self.item_padding = self.item_height / 4
local line_height = self.item_height + 2 * self.item_padding
local content_height = self.dimen.h - self.title_bar:getSize().h
self.items_per_page = math.floor(content_height / line_height)
self.pages = math.ceil(#self.kv_pairs / self.items_per_page)
self.main_content = VerticalGroup:new{}
self:_populateItems()
-- assemble page
self[1] = FrameContainer:new{
height = self.dimen.h,
padding = padding,
bordersize = 0,
background = Blitbuffer.COLOR_WHITE,
VerticalGroup:new{
self.title_bar,
self.main_content,
},
}
end
function KeyValuePage:nextPage()
local new_page = math.min(self.show_page+1, self.pages)
if new_page > self.show_page then
self.show_page = new_page
self:_populateItems()
end
end
function KeyValuePage:prevPage()
local new_page = math.max(self.show_page-1, 1)
if new_page < self.show_page then
self.show_page = new_page
self:_populateItems()
end
end
-- make sure self.item_padding and self.item_height are set before calling this
function KeyValuePage:_populateItems()
self.main_content:clear()
local idx_offset = (self.show_page - 1) * self.items_per_page
for idx = 1, self.items_per_page do
local entry = self.kv_pairs[idx_offset + idx]
if entry == nil then break end
table.insert(self.main_content,
VerticalSpan:new{ width = self.item_padding })
if type(entry) == "table" then
table.insert(
self.main_content,
KeyValueItem:new{
height = self.item_height,
width = self.item_width,
key = entry[1],
value = entry[2],
callback = entry.callback,
}
)
elseif type(entry) == "string" then
local c = string.sub(entry, 1, 1)
if c == "-" then
table.insert(self.main_content, LineWidget:new{
background = Blitbuffer.COLOR_LIGHT_GREY,
dimen = Geom:new{
w = self.item_width,
h = Screen:scaleBySize(2)
},
style = "solid",
})
end
end
table.insert(self.main_content,
VerticalSpan:new{ width = self.item_padding })
end
self.title_bar:setPageCount(self.show_page, self.pages)
UIManager:setDirty(self, function()
return "ui", self.dimen
end)
end
function KeyValuePage:onSwipe(arg, ges_ev)
if ges_ev.direction == "west" then
self:nextPage()
return true
elseif ges_ev.direction == "east" then
self:prevPage()
return true
end
end
function KeyValuePage:onClose()
UIManager:close(self)
return true
end
return KeyValuePage

@ -19,13 +19,13 @@ function LineWidget:paintTo(bb, x, y)
else
if self.empty_segments then
bb:paintRect(x, y,
self.empty_segments[1].s,
self.dimen.h,
self.background)
self.empty_segments[1].s,
self.dimen.h,
self.background)
bb:paintRect(x + self.empty_segments[1].e, y,
self.dimen.w - x - self.empty_segments[1].e,
self.dimen.h,
self.background)
self.dimen.w - x - self.empty_segments[1].e,
self.dimen.h,
self.background)
else
bb:paintRect(x, y, self.dimen.w, self.dimen.h, self.background)
end

@ -8,7 +8,6 @@ local BottomContainer = require("ui/widget/container/bottomcontainer")
local UnderlineContainer = require("ui/widget/container/underlinecontainer")
local FocusManager = require("ui/widget/focusmanager")
local TextWidget = require("ui/widget/textwidget")
local LineWidget = require("ui/widget/linewidget")
local OverlapGroup = require("ui/widget/overlapgroup")
local VerticalSpan = require("ui/widget/verticalspan")
local HorizontalSpan = require("ui/widget/horizontalspan")
@ -82,7 +81,7 @@ NOTICE:
@menu entry must be provided in order to close the menu
--]]
local MenuCloseButton = InputContainer:new{
align = "right",
overlap_align = "right",
menu = nil,
dimen = Geom:new{},
}
@ -94,7 +93,10 @@ function MenuCloseButton:init()
}
local text_size = self[1]:getSize()
self.dimen.w, self.dimen.h = text_size.w*2, text_size.h*2
self.dimen = Geom:new{
w = text_size.w*2,
h = text_size.h*2,
}
self.ges_events.Close = {
GestureRange:new{
@ -110,45 +112,6 @@ function MenuCloseButton:onClose()
return true
end
--[[
Widget that displays a solid line in menu
--]]
local SeparatorMenuItem = InputContainer:new{
style = "solid",
dimen = nil,
_line_container = nil,
}
function SeparatorMenuItem:init()
self._line_container = CenterContainer:new{
vertical_align = "center",
dimen = Geom:new {
w = self.dimen.w,
h = self.dimen.h
},
HorizontalGroup:new {
align = "center",
OverlapGroup:new {
dimen = Geom:new { w = self.dimen.w, h = Screen:scaleBySize(2) },
LineWidget:new {
style = self.style,
dimen = Geom:new { w = self.dimen.w - 30, h = Screen:scaleBySize(2) },
}
},
}
}
self[1] = FrameContainer:new {
bordersize = 0,
padding = 0,
HorizontalGroup:new {
align = "center",
HorizontalSpan:new { width = 15 },
self._line_container
}
}
end
--[[
Widget that displays an item for menu
--]]
@ -430,7 +393,7 @@ function Menu:init()
-- start to set up widget layout --
-----------------------------------
self.menu_title = TextWidget:new{
align = "center",
overlap_align = "center",
text = self.title,
face = self.tface,
}
@ -578,9 +541,7 @@ function Menu:init()
if Device:isTouchDevice() then
if self.has_close_button then
table.insert(self.title_bar,
MenuCloseButton:new{
menu = self,
})
MenuCloseButton:new{ menu = self })
end
-- watch for outer region if it's a self contained widget
if self.is_popout then
@ -681,27 +642,20 @@ function Menu:updateItems(select_number)
item_shortcut = "Ent"
end
end
local item_tmp
if self.item_table[i].text == "-" then
item_tmp = SeparatorMenuItem:new{
dimen = self.item_dimen:new{ h = Screen:scaleBySize(10) },
}
else
item_tmp = MenuItem:new{
show_parent = self.show_parent,
state = self.item_table[i].state,
state_size = self.state_size or {},
text = self.item_table[i].text,
mandatory = self.item_table[i].mandatory,
bold = self.item_table.current == i,
face = self.cface,
dimen = self.item_dimen:new(),
shortcut = item_shortcut,
shortcut_style = shortcut_style,
table = self.item_table[i],
menu = self,
}
end
local item_tmp = MenuItem:new{
show_parent = self.show_parent,
state = self.item_table[i].state,
state_size = self.state_size or {},
text = self.item_table[i].text,
mandatory = self.item_table[i].mandatory,
bold = self.item_table.current == i,
face = self.cface,
dimen = self.item_dimen:new(),
shortcut = item_shortcut,
shortcut_style = shortcut_style,
table = self.item_table[i],
menu = self,
}
table.insert(self.item_group, item_tmp)
-- this is for focus manager
table.insert(self.layout, {item_tmp})
@ -923,17 +877,9 @@ end
function Menu:onSwipe(arg, ges_ev)
if ges_ev.direction == "west" then
if DCHANGE_WEST_SWIPE_TO_EAST then
self:onPrevPage()
else
self:onNextPage()
end
self:onNextPage()
elseif ges_ev.direction == "east" then
if DCHANGE_WEST_SWIPE_TO_EAST then
self:onNextPage()
else
self:onPrevPage()
end
self:onPrevPage()
end
end

@ -22,14 +22,22 @@ function OverlapGroup:getSize()
end
end
return self._size
end
function OverlapGroup:initDimen()
self:getSize() -- populate self._size
-- sync self._size with self.dimen, self.dimen has higher priority
if self.dimen.w then
self._size.w = self.dimen.w
else
self.dimen.w = self._size.w
end
if self.dimen.h then
self._size.h = self.dimen.h
else
self.dimen.h = self._size.h
end
return self._size
end
function OverlapGroup:paintTo(bb, x, y)
@ -37,10 +45,12 @@ function OverlapGroup:paintTo(bb, x, y)
for i, wget in ipairs(self) do
local wget_size = wget:getSize()
if wget.align == "right" then
if wget.overlap_align == "right" then
wget:paintTo(bb, x+size.w-wget_size.w, y)
elseif wget.align == "center" then
elseif wget.overlap_align == "center" then
wget:paintTo(bb, x+math.floor((size.w-wget_size.w)/2), y)
elseif wget.overlap_offset then
wget:paintTo(bb, x+wget.overlap_offset[1], y+wget.overlap_offset[2])
else
-- default to left
wget:paintTo(bb, x, y)

@ -25,23 +25,33 @@ local TextWidget = Widget:new{
--self._length = RenderText:renderUtf8Text(self._bb, 0, h*0.8, self.face, self.text, true, self.bold)
--end
function TextWidget:updateSize()
local tsize = RenderText:sizeUtf8Text(0, Screen:getWidth(), self.face, self.text, true, self.bold)
if not tsize then
self._length = 0
else
self._length = tsize.x
end
self._height = self.face.size * 1.5
end
function TextWidget:getSize()
--if not self._bb then
--self:_render()
--end
--return { w = self._length, h = self._bb:getHeight() }
local tsize = RenderText:sizeUtf8Text(0, Screen:getWidth(), self.face, self.text, true, self.bold)
if not tsize then
return Geom:new{}
end
self._length = tsize.x
self._height = self.face.size * 1.5
self:updateSize()
return Geom:new{
w = self._length,
h = self._height,
}
end
function TextWidget:setText(text)
self.text = text
self:updateSize()
end
function TextWidget:paintTo(bb, x, y)
--if not self._bb then
--self:_render()

@ -94,16 +94,13 @@ function TouchMenuItem:onTapSelect(arg, ges)
end
if enabled == false then return end
UIManager:scheduleIn(0.0, function()
self.item_frame.invert = true
UIManager:setDirty(self.show_parent, function()
return "ui", self.dimen
end)
self.item_frame.invert = true
UIManager:setDirty(self.show_parent, function()
return "ui", self.dimen
end)
-- yield to main UI loop to invert item
UIManager:scheduleIn(0.1, function()
self.menu:onMenuSelect(self.item)
end)
UIManager:scheduleIn(0.5, function()
self.item_frame.invert = false
UIManager:setDirty(self.show_parent, function()
return "ui", self.dimen

@ -18,8 +18,8 @@ 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 {}
function Widget:extend(from_o)
local o = from_o or {}
setmetatable(o, self)
self.__index = self
return o

13
kodev

@ -265,7 +265,7 @@ usage: test [front|base] <TEST_NAME>
if [ ! -z $2 ]; then
test_path="${test_path}/$2"
fi
busted --exclude-tags=notest ${test_path}
busted -o verbose_print --exclude-tags=notest ${test_path}
popd
}
@ -277,10 +277,13 @@ usage: $0 COMMAND <ARGS>
Supported commands:
build Build KOReader
clean Clean KOReader build
run Run KOReader
wbuilder Run wbuilder.lua script (useful for building new UI widget)
fetch-thirdparty Fetch thirdparty dependencies for build
build Build KOReader
clean Clean KOReader build
release Build KOReader release package
run Run KOReader
wbuilder Run wbuilder.lua script (useful for building new UI widget)
test Run tests
"
if [ $# -lt 1 ]; then

@ -1 +1 @@
Subproject commit 63f26f697fc2f1ce1ef2b0af61dd7875b2a8ce25
Subproject commit cc5c30286ade5151848a8dbb2be64e90fb2c8fcf

@ -1,21 +1,22 @@
local InputContainer = require("ui/widget/container/inputcontainer")
local MultiInputDialog = require("ui/widget/multiinputdialog")
local CenterContainer = require("ui/widget/container/centercontainer")
local KeyValuePage = require("ui/widget/keyvaluepage")
local UIManager = require("ui/uimanager")
local Screen = require("device").screen
local Menu = require("ui/widget/menu")
local Font = require("ui/font")
local TimeVal = require("ui/timeval")
local DataStorage = require("datastorage")
local lfs = require("libs/libkoreader-lfs")
local DEBUG = require("dbg")
local T = require("ffi/util").template
local joinPath = require("ffi/util").joinPath
local _ = require("gettext")
local util = require("util")
local tableutil = require("tableutil")
local statistics_dir = DataStorage:getDataDir() .. "/statistics/"
local history_dir = DataStorage:getDataDir() .. "/history/"
local history_dir = DataStorage:getHistoryDir()
local ReaderStatistics = InputContainer:new {
last_time = nil,
@ -51,37 +52,37 @@ function ReaderStatistics:init()
self.last_time = TimeVal:now()
end
function ReaderStatistics:getBookProperties()
local props = self.view.document:getProps()
if props.title == "No document" or props.title == "" then
-- FIXME: sometimes crengine returns "No document", try one more time
props = self.view.document:getProps()
end
return props
end
function ReaderStatistics:initData(config)
--first execution
-- first execution
if self.is_enabled then
local book_properties = self:getBookProperties()
self:savePropertiesInToData(book_properties)
if not self.data then
--first time merge data
self:inplaceMigration();
self.data = { performance_in_pages= {} }
self:inplaceMigration(); -- first time merge data
end
local book_properties = self:getBookProperties()
self.data.title = book_properties.title
self.data.authors = book_properties.authors
self.data.language = book_properties.language
self.data.series = book_properties.series
self.data.pages = self.view.document:getPageCount()
return
end
end
function ReaderStatistics:addToMainMenu(tab_item_table)
table.insert(tab_item_table.plugins, {
text = _("Statistics"),
sub_item_table = {
self:getStatisticEnabledMenuTable(),
self:getStatisticSettingsMenuTable(),
self:getStatisticForCurrentBookMenuTable(),
self:getStatisticTotalStatisticMenuTable(),
}
})
end
function ReaderStatistics:getStatisticEnabledMenuTable()
function ReaderStatistics:getStatisticEnabledMenuItem()
return {
text_func = function()
return _("Enabled")
end,
text = _("Enabled"),
checked_func = function() return self.is_enabled end,
callback = function()
-- if was enabled, have to save data to file
@ -99,18 +100,6 @@ function ReaderStatistics:getStatisticEnabledMenuTable()
}
end
function ReaderStatistics:getStatisticSettingsMenuTable()
return {
text_func = function()
return _("Settings")
end,
checked_func = function() return false end,
callback = function()
self:updateSettings()
end,
}
end
function ReaderStatistics:updateSettings()
self.settings_dialog = MultiInputDialog:new {
title = _("Statistics settings"),
@ -138,9 +127,9 @@ function ReaderStatistics:updateSettings()
{
text = _("Apply"),
callback = function()
self:saveSettings(MultiInputDialog:getFields())
self.settings_dialog:onClose()
UIManager:close(self.settings_dialog)
self:saveSettings(MultiInputDialog:getFields())
end
},
},
@ -153,101 +142,74 @@ function ReaderStatistics:updateSettings()
UIManager:show(self.settings_dialog)
end
function ReaderStatistics:getStatisticForCurrentBookMenuTable()
self.status_menu = {}
local book_status = Menu:new {
title = _("Status"),
item_table = self:updateCurrentStat(),
is_borderless = true,
is_popout = false,
is_enable_shortcut = false,
width = Screen:getWidth(),
height = Screen:getHeight(),
cface = Font:getFace("cfont", 20),
}
self.status_menu = CenterContainer:new {
dimen = Screen:getSize(),
book_status,
}
book_status.close_callback = function()
UIManager:close(self.status_menu)
end
book_status.show_parent = self.status_menu
return {
text = _("Current"),
enabled_func = function() return true end,
checked_func = function() return false end,
callback = function()
book_status:swithItemTable(nil, self:updateCurrentStat())
UIManager:show(self.status_menu)
return true
end
}
function ReaderStatistics:addToMainMenu(tab_item_table)
table.insert(tab_item_table.plugins, {
text = _("Statistics"),
sub_item_table = {
self:getStatisticEnabledMenuItem(),
{
text = _("Settings"),
callback = function() self:updateSettings() end,
},
{
text = _("Current book"),
callback = function()
UIManager:show(KeyValuePage:new{
title = _("Statistics"),
kv_pairs = self:getCurrentStat(),
})
end
},
{
text = _("All books"),
callback = function()
total_msg, kv_pairs = self:getTotalStats()
UIManager:show(KeyValuePage:new{
title = total_msg,
kv_pairs = kv_pairs,
})
end
},
},
})
end
function ReaderStatistics:getStatisticTotalStatisticMenuTable()
self.total_status = Menu:new {
title = _("Total"),
item_table = self:updateTotalStat(),
is_borderless = true,
is_popout = false,
is_enable_shortcut = false,
width = Screen:getWidth(),
height = Screen:getHeight(),
cface = Font:getFace("cfont", 20),
}
self.total_menu = CenterContainer:new {
dimen = Screen:getSize(),
self.total_status,
}
self.total_status.close_callback = function()
UIManager:close(self.total_menu)
function ReaderStatistics:getCurrentStat()
local dates = {}
for k, v in pairs(self.data.performance_in_pages) do
dates[os.date("%Y-%m-%d", k)] = ""
end
local total_days = util.tableSize(dates)
self.total_status.show_parent = self.total_menu
local read_pages = util.tableSize(self.data.performance_in_pages)
local current_page = self.view.state.page -- get current page from the view
local avg_time_per_page = self.data.total_time_in_sec / read_pages
return {
text = _("Total"),
callback = function()
self.total_status:swithItemTable(nil, self:updateTotalStat())
UIManager:show(self.total_menu)
return true
end
{ _("Current period"), util.secondsToClock(self.current_period, false) },
{ _("Time to read"), util.secondsToClock((self.data.pages - current_page) * avg_time_per_page, false) },
{ _("Total time"), util.secondsToClock(self.data.total_time_in_sec, false) },
{ _("Total highlights"), self.data.highlights },
{ _("Total notes"), self.data.notes },
{ _("Total days"), total_days },
{ _("Average time per page"), util.secondsToClock(avg_time_per_page, false) },
{ _("Read pages/Total pages"), read_pages .. "/" .. self.data.pages },
}
end
function ReaderStatistics:updateCurrentStat()
local stats = {}
local dates = {}
for k, v in pairs(self.data.performance_in_pages) do
dates[os.date("%Y-%m-%d", k)] = ""
function generateReadBooksTable(title, dates)
local result = {}
for k, v in tableutil.spairs(dates, function(t, a, b) return t[b].date < t[a].date end) do
table.insert(result, {
k,
T(_("Pages (%1) Time: %2"), v.count, util.secondsToClock(v.read, false))
})
end
local read_pages = util.tableSize(self.data.performance_in_pages)
local current_page = self.view.state.page --get current page from the view
local average_time_per_page = self.data.total_time_in_sec / read_pages
table.insert(stats, { text = _("Current period"), mandatory = util.secondsToClock(self.current_period, false) })
table.insert(stats, { text = _("Time to read"), mandatory = util.secondsToClock((self.data.pages - current_page) * average_time_per_page, false) })
table.insert(stats, { text = _("Total time"), mandatory = util.secondsToClock(self.data.total_time_in_sec, false) })
table.insert(stats, { text = _("Total highlights"), mandatory = self.data.highlights })
table.insert(stats, { text = _("Total notes"), mandatory = self.data.notes })
table.insert(stats, { text = _("Total days"), mandatory = util.tableSize(dates) })
table.insert(stats, { text = _("Average time per page"), mandatory = util.secondsToClock(average_time_per_page, false) })
table.insert(stats, { text = _("Read pages/Total pages"), mandatory = read_pages .. "/" .. self.data.pages })
return stats
return result
end
-- For backward compatibility
function ReaderStatistics:getDatesForBookOldFormat(book)
function getDatesForBookOldFormat(book)
local dates = {}
for k, v in pairs(book.details) do
@ -267,11 +229,10 @@ function ReaderStatistics:getDatesForBookOldFormat(book)
end
end
return self:generateReadBooksTable(book.title, dates)
return generateReadBooksTable(book.title, dates)
end
function ReaderStatistics:getDatesForBook(book)
function getDatesForBook(book)
local dates = {}
for k, v in pairs(book.performance_in_pages) do
@ -283,107 +244,96 @@ function ReaderStatistics:getDatesForBook(book)
count = 1
}
else
dates[date_text] = {
read = dates[date_text].read + v,
count = dates[date_text].count + 1,
date = dates[date_text].date
}
-- TODO: test this
local entry = dates[date_text]
entry.read = entry.read + v
entry.count = entry.count + 1
end
end
return self:generateReadBooksTable(book.title, dates)
end
function ReaderStatistics:generateReadBooksTable(title, dates)
local result = {}
table.insert(result, { text = title })
for k, v in tableutil.spairs(dates, function(t, a, b) return t[b].date < t[a].date end) do
table.insert(result, { text = k, mandatory = T(_("Pages (%1) Time: %2"), v.count, util.secondsToClock(v.read, false)) })
end
return result
return generateReadBooksTable(book.title, dates)
end
function ReaderStatistics:getTotalStats()
local total_stats = {
{
self.data.title,
util.secondsToClock(self.data.total_time_in_sec, false),
callback = function()
UIManager:show(KeyValuePage:new{
title = self.data.title,
kv_pairs = getDatesForBook(self.data),
})
end,
}
}
function ReaderStatistics:updateTotalStat()
local total_stats = {}
local total_books_time = 0
local proceded_titles = self:getStatisticsFromHistory(total_stats, total_books_time)
self:getOldStatisticsFromDirectory(proceded_titles, total_stats, total_books_time)
-- find stats for all other books in history
local proceded_titles, total_books_time = self:getStatisticsFromHistory(total_stats)
total_books_time = total_books_time + self:getOldStatisticsFromDirectory(proceded_titles, total_stats)
total_books_time = total_books_time + tonumber(self.data.total_time_in_sec)
table.insert(total_stats, 1, { text = _("Total hours read"), mandatory = util.secondsToClock(total_books_time, false) })
table.insert(total_stats, 2, { text = "-" })
table.insert(total_stats, 3, {
text = self.data.title,
mandatory = util.secondsToClock(self.data.total_time_in_sec, false),
callback = function()
self.total_status:swithItemTable(nil, self:getDatesForBook(self.data))
UIManager:show(self.total_menu)
return true
end,
})
return total_stats
return T(_("Total hours read %1"),
util.secondsToClock(total_books_time, false)),
total_stats
end
function ReaderStatistics:getStatisticsFromHistory(total_stats, total_books_time)
function ReaderStatistics:getStatisticsFromHistory(total_stats)
local titles = {}
local total_books_time = 0
for curr_file in lfs.dir(history_dir) do
local path = history_dir .. curr_file
local path = joinPath(history_dir, curr_file)
if lfs.attributes(path, "mode") == "file" then
local book_result = self:importFromFile(history_dir, curr_file)
local book_stats = book_result.stats
if book_stats and book_stats.title ~= self.data.title then
if book_stats and book_stats.total_time_in_sec > 0
and book_stats.title ~= self.data.title then
titles[book_stats.title] = true
table.insert(total_stats, {
text = book_stats.title,
mandatory = util.secondsToClock(book_stats.total_time_in_sec, false),
book_stats.title,
util.secondsToClock(book_stats.total_time_in_sec, false),
callback = function()
self.total_status:swithItemTable(nil, self:getDatesForBook(book_stats))
UIManager:show(self.total_menu)
return true
UIManager:show(KeyValuePage:new{
title = book_stats.title,
kv_pairs = getDatesForBook(book_stats),
})
end,
})
total_books_time = total_books_time + tonumber(book_stats.total_time_in_sec)
end
end
end
return titles
return titles, total_books_time
end
-- For backward compatibility
function ReaderStatistics:getOldStatisticsFromDirectory(exlude_titles, total_stats, total_books_time)
function ReaderStatistics:getOldStatisticsFromDirectory(exlude_titles, total_stats)
if lfs.attributes(statistics_dir, "mode") ~= "directory" then
return
return 0
end
local total_books_time = 0
for curr_file in lfs.dir(statistics_dir) do
local path = statistics_dir .. curr_file
if lfs.attributes(path, "mode") == "file" then
local book_result = self:importFromFile(statistics_dir, curr_file)
if book_result and book_result.title ~= self.data.title and not exlude_titles[book_result.title] then
if book_result and book_stats.total_time_in_sec > 0
and book_result.title ~= self.data.title
and not exlude_titles[book_result.title] then
table.insert(total_stats, {
text = book_result.title,
mandatory = util.secondsToClock(book_result.total_time, false),
book_result.title,
util.secondsToClock(book_result.total_time, false),
callback = function()
self.total_status:swithItemTable(nil, self:getDatesForBookOldFormat(book_result))
UIManager:show(self.total_menu)
return true
UIManager:show(KeyValuePage:new{
title = book_result.title,
kv_pairs = getDatesForBookOldFormat(book_result),
})
end,
})
total_books_time = total_books_time + tonumber(book_result.total_time)
end
end
end
end
function ReaderStatistics:getBookProperties()
local props = self.view.document:getProps()
if props.title == "No document" or props.title == "" then --sometime crengine returns "No document" try to get one more time
props = self.view.document:getProps()
end
return props
return total_books_time
end
function ReaderStatistics:onPageUpdate(pageno)
@ -411,14 +361,6 @@ function ReaderStatistics:onPageUpdate(pageno)
end
end
function ReaderStatistics:savePropertiesInToData(item)
self.data.title = item.title
self.data.authors = item.authors
self.data.language = item.language
self.data.series = item.series
end
-- For backward compatibility
function ReaderStatistics:inplaceMigration()
local oldData = self:importFromFile(statistics_dir, self.data.title .. ".stat")
@ -431,12 +373,12 @@ end
-- For backward compatibility
function ReaderStatistics:importFromFile(base_path, item)
item = string.gsub(item, "^%s*(.-)%s*$", "%1") --trim
if lfs.attributes(base_path .. item, "mode") == "directory" then
item = string.gsub(item, "^%s*(.-)%s*$", "%1") -- trim
local statistic_file = joinPath(base_path, item)
if lfs.attributes(statistic_file, "mode") == "directory" then
return
end
local statisticFile = base_path .. item
local ok, stored = pcall(dofile, statisticFile)
local ok, stored = pcall(dofile, statistic_file)
if ok then
return stored
else

@ -44,6 +44,7 @@ describe("ReaderBookmark module", function()
readerui = ReaderUI:new{
document = DocumentRegistry:openDocument(sample_epub),
}
readerui.status.enabled = false
end)
before_each(function()
UIManager:quit()
@ -117,6 +118,7 @@ describe("ReaderBookmark module", function()
readerui = ReaderUI:new{
document = DocumentRegistry:openDocument(sample_pdf),
}
readerui.status.enabled = false
end)
before_each(function()
UIManager:quit()

@ -64,8 +64,7 @@ function TestGrid:paintTo(bb)
end
function TestVisible:paintTo(bb)
--Draw three lines at the borders to assess what the maximum visible coordinates are
-- Draw three lines at the borders to assess what the maximum visible coordinates are
v_line = math.floor(bb:getWidth() / 50)
h_line = math.floor(bb:getHeight() / 50)
-- Paint white background for higher contrast
@ -165,8 +164,6 @@ function Background:onQuitApplication()
UIManager:quit()
end
-----------------------------------------------------
-- example widget: a clock
-----------------------------------------------------
@ -185,7 +182,6 @@ function Clock:schedFunc()
self[1][1]:free()
self[1][1] = self:getTextWidget()
UIManager:setDirty(self)
-- reschedule
-- TODO: wait until next real second shift
UIManager:scheduleIn(1, function() self:schedFunc() end)
end
@ -250,7 +246,6 @@ M = Menu:new{
height = 600,
}
-----------------------------------------------------
-- a reader view widget
-----------------------------------------------------
@ -277,72 +272,62 @@ touch_menu = TouchMenu:new{
icon = "resources/icons/appbar.pokeball.png",
{
text = "item1",
callback = function()
end,
callback = function() end,
},
{
text = "item2",
callback = function()
end,
callback = function() end,
},
{
text = "item3",
callback = function()
end,
callback = function() end,
},
{
text = "item4",
callback = function()
end,
callback = function() end,
},
{
text = "item5",
callback = function()
end,
callback = function() end,
},
{
text = "item6",
callback = function()
end,
callback = function() end,
},
{
text = "item7",
callback = function()
end,
callback = function() end,
},
{
text = "item8",
callback = function()
end,
callback = function() end,
},
{
text = "item9",
callback = function()
end,
callback = function() end,
},
},
{
icon = "resources/icons/appbar.page.corner.bookmark.png",
{
text = "item10",
callback = function()
end,
callback = function() end,
},
{
text = "item11",
callback = function()
end,
callback = function() end,
},
},
{
icon = "resources/icons/appbar.home.png",
callback = function()
DEBUG("hello world!")
end
callback = function() DEBUG("hello world!") end
}
},
}
-----------------------------------------------------
-- input box widget
-----------------------------------------------------
local TestInputText = InputText:new{
width = 400,
enter_callback = function() print("Entered") end,
@ -353,11 +338,43 @@ local TestInputText = InputText:new{
},
}
-----------------------------------------------------
-- key value page
-----------------------------------------------------
local KeyValuePage = require("ui/widget/keyvaluepage")
local kvp = KeyValuePage:new{
title = 'Statistics',
kv_pairs = {
{"1 Current period", "00:00:00"},
{"2 Time to read", "00:00:00"},
{"3 Time to read", "00:00:00"},
{"4 Time to read", "00:00:00"},
{"5 Time to read", "00:00:00"},
{"6 Time to read", "00:00:00"},
{"7 Time to read", "00:00:00"},
{"8 Time to read", "00:00:00"},
{"9 Time to read", "00:00:00"},
{"10 Time to read", "00:00:00"},
{"11 Time to read", "00:00:00"},
"----------------------------",
{"12 Time to read", "00:00:00"},
{"13 Time to read", "00:00:00"},
{"14 Time to read", "00:00:00"},
{"15 Time to read", "00:00:00"},
{"16 Time to read", "00:00:00"},
{"17 Time to read", "00:00:00"},
{"18 Time to read", "00:00:00"},
{"19 Time to read", "00:00:00"},
{"20 Time to read", "00:00:00"},
{"21 Time to read", "00:00:00"},
},
}
-----------------------------------------------------------------------
-- you may want to uncomment following show calls to see the changes
-----------------------------------------------------------------------
--UIManager:show(Background:new())
-- UIManager:show(TestGrid)
--UIManager:show(TestGrid)
UIManager:show(TestVisible)
UIManager:show(Clock:new())
--UIManager:show(M)
@ -365,7 +382,9 @@ UIManager:show(Clock:new())
--UIManager:show(readerwindow)
--UIManager:show(touch_menu)
--UIManager:show(keyboard)
UIManager:show(TestInputText)
TestInputText:onShowKeyboard()
--UIManager:show(TestInputText)
--TestInputText:onShowKeyboard()
UIManager:show(kvp)
UIManager:run()

Loading…
Cancel
Save