@ -15,6 +15,7 @@ local TextWidget = require("ui/widget/textwidget")
local UIManager = require ( " ui/uimanager " )
local UIManager = require ( " ui/uimanager " )
local WidgetContainer = require ( " ui/widget/container/widgetcontainer " )
local WidgetContainer = require ( " ui/widget/container/widgetcontainer " )
local util = require ( " util " )
local util = require ( " util " )
local T = require ( " ffi/util " ) . template
local _ = require ( " gettext " )
local _ = require ( " gettext " )
local Screen = Device.screen
local Screen = Device.screen
@ -32,6 +33,31 @@ local MODE = {
wifi_status = 10 ,
wifi_status = 10 ,
}
}
local symbol_prefix = {
letters = {
time = nil ,
pages_left = " => " ,
battery = " B: " ,
percentage = " R: " ,
book_time_to_read = " TB: " ,
chapter_time_to_read = " TC: " ,
frontlight = " L: " ,
mem_usage = " M: " ,
wifi_status = " W: " ,
} ,
icons = {
time = " ⌚ " ,
pages_left = " ⇒ " ,
battery = " ⚡ " ,
percentage = " ⤠ " ,
book_time_to_read = " ⏳ " ,
chapter_time_to_read = " ⤻ " ,
frontlight = " ☼ " ,
mem_usage = " ⌨ " ,
wifi_status = " ⚟ " ,
}
}
local MODE_NB = 0
local MODE_NB = 0
local MODE_INDEX = { }
local MODE_INDEX = { }
for k , v in pairs ( MODE ) do
for k , v in pairs ( MODE ) do
@ -42,57 +68,89 @@ end
-- functions that generates footer text for each mode
-- functions that generates footer text for each mode
local footerTextGeneratorMap = {
local footerTextGeneratorMap = {
empty = function ( ) return " " end ,
empty = function ( ) return " " end ,
frontlight = function ( )
frontlight = function ( footer )
if not Device : hasFrontlight ( ) then return " L: NA " end
local symbol_type = footer.settings . item_prefix or " icons "
local prefix = symbol_prefix [ symbol_type ] . frontlight
local powerd = Device : getPowerDevice ( )
local powerd = Device : getPowerDevice ( )
if powerd : isFrontlightOn ( ) then
if powerd : isFrontlightOn ( ) then
if Device : isCervantes ( ) or Device : isKobo ( ) then
if Device : isCervantes ( ) or Device : isKobo ( ) then
return ( " L: %d%%" ) : format ( powerd : frontlightIntensity ( ) )
return ( prefix .. " %d%%" ) : format ( powerd : frontlightIntensity ( ) )
else
else
return ( " L: %d" ) : format ( powerd : frontlightIntensity ( ) )
return ( prefix .. " %d" ) : format ( powerd : frontlightIntensity ( ) )
end
end
else
else
return " L: Off "
return T ( _ ( " %1 Off " ) , prefix )
end
end
end ,
end ,
battery = function ( )
battery = function ( footer )
local symbol_type = footer.settings . item_prefix or " icons "
local prefix = symbol_prefix [ symbol_type ] . battery
local powerd = Device : getPowerDevice ( )
local powerd = Device : getPowerDevice ( )
return " B: " .. ( powerd : isCharging ( ) and " + " or " " ) .. powerd : getCapacity ( ) .. " % "
return prefix .. " " .. ( powerd : isCharging ( ) and " + " or " " ) .. powerd : getCapacity ( ) .. " % "
end ,
end ,
time = function ( )
time = function ( footer )
return os.date ( " %H:%M " )
local symbol_type = footer.settings . item_prefix or " icons "
local prefix = symbol_prefix [ symbol_type ] . time
local clock
if footer.settings . time_format == " 12 " then
clock = os.date ( " %I:%M%p " )
else
clock = os.date ( " %H:%M " )
end
if not prefix then
return clock
else
return prefix .. " " .. clock
end
end ,
end ,
page_progress = function ( footer )
page_progress = function ( footer )
if footer.pageno then
if footer.pageno then
return ( " %d / %d " ) : format ( footer.pageno , footer.pages )
return ( " %d / %d " ) : format ( footer.pageno , footer.pages )
else
else if footer.position then
return ( " %d / %d " ) : format ( footer.position , footer.doc_height )
return ( " %d / %d " ) : format ( footer.position , footer.doc_height )
end
end
end ,
end ,
pages_left = function ( footer )
pages_left = function ( footer )
local symbol_type = footer.settings . item_prefix or " icons "
local prefix = symbol_prefix [ symbol_type ] . pages_left
local left = footer.ui . toc : getChapterPagesLeft (
local left = footer.ui . toc : getChapterPagesLeft (
footer.pageno , footer.toc_level )
footer.pageno , footer.toc_level )
return " => " .. ( left and left or footer.pages - footer.pageno )
return prefix .. " " .. ( left and left or footer.pages - footer.pageno )
end ,
end ,
percentage = function ( footer )
percentage = function ( footer )
return ( " R:%1.f%% " ) : format ( footer.progress_bar . percentage * 100 )
local symbol_type = footer.settings . item_prefix or " icons "
local prefix = symbol_prefix [ symbol_type ] . percentage
local digits = footer.settings . progress_pct_format or " 0 "
local string_percentage
if not prefix then
string_percentage = " %. " .. digits .. " f%% "
else
string_percentage = prefix .. " %. " .. digits .. " f%% "
end
return string_percentage : format ( footer.progress_bar . percentage * 100 )
end ,
end ,
book_time_to_read = function ( footer )
book_time_to_read = function ( footer )
local symbol_type = footer.settings . item_prefix or " icons "
local prefix = symbol_prefix [ symbol_type ] . book_time_to_read
local current_page
local current_page
if footer.view . document.info . has_pages then
if footer.view . document.info . has_pages then
current_page = footer.ui . paging.current_page
current_page = footer.ui . paging.current_page
else
else
current_page = footer.view . document : getCurrentPage ( )
current_page = footer.view . document : getCurrentPage ( )
end
end
return footer : getDataFromStatistics ( " TB: " , footer.pages - current_page )
return footer : getDataFromStatistics ( prefix .. " " , footer.pages - current_page )
end ,
end ,
chapter_time_to_read = function ( footer )
chapter_time_to_read = function ( footer )
local symbol_type = footer.settings . item_prefix or " icons "
local prefix = symbol_prefix [ symbol_type ] . chapter_time_to_read
local left = footer.ui . toc : getChapterPagesLeft (
local left = footer.ui . toc : getChapterPagesLeft (
footer.pageno , footer.toc_level )
footer.pageno , footer.toc_level )
return footer : getDataFromStatistics (
return footer : getDataFromStatistics (
" TC: " , ( left and left or footer.pages - footer.pageno ) )
prefix .. " " , ( left and left or footer.pages - footer.pageno ) )
end ,
end ,
mem_usage = function ( footer )
mem_usage = function ( footer )
local symbol_type = footer.settings . item_prefix or " icons "
local prefix = symbol_prefix [ symbol_type ] . mem_usage
local statm = io.open ( " /proc/self/statm " , " r " )
local statm = io.open ( " /proc/self/statm " , " r " )
if statm then
if statm then
local infos = statm : read ( " *all " )
local infos = statm : read ( " *all " )
@ -100,16 +158,18 @@ local footerTextGeneratorMap = {
local rss = infos : match ( " ^%S+ (%S+) " )
local rss = infos : match ( " ^%S+ (%S+) " )
-- we got the nb of 4Kb-pages used, that we convert to Mb
-- we got the nb of 4Kb-pages used, that we convert to Mb
rss = math.floor ( tonumber ( rss ) * 4096 / 1024 / 1024 )
rss = math.floor ( tonumber ( rss ) * 4096 / 1024 / 1024 )
return ( " M: %d" ) : format ( rss )
return ( prefix .. " %d" ) : format ( rss )
end
end
return " "
return " "
end ,
end ,
wifi_status = function ( )
wifi_status = function ( footer )
local symbol_type = footer.settings . item_prefix or " icons "
local prefix = symbol_prefix [ symbol_type ] . wifi_status
local NetworkMgr = require ( " ui/network/manager " )
local NetworkMgr = require ( " ui/network/manager " )
if NetworkMgr : isWifiOn ( ) then
if NetworkMgr : isWifiOn ( ) then
return " W:On "
return T ( _ ( " %1 On " ) , prefix )
else
else
return " W:Off "
return T ( _ ( " %1 Off " ) , prefix )
end
end
end ,
end ,
}
}
@ -151,6 +211,7 @@ function ReaderFooter:init()
frontlight = false ,
frontlight = false ,
mem_usage = false ,
mem_usage = false ,
wifi_status = false ,
wifi_status = false ,
item_prefix = " icons "
}
}
if self.settings . disabled then
if self.settings . disabled then
@ -359,21 +420,40 @@ function ReaderFooter:updateFooterTextGenerator()
return true
return true
end
end
function ReaderFooter : progressPercentage ( digits )
local symbol_type = self.settings . item_prefix or " icons "
local prefix = symbol_prefix [ symbol_type ] . percentage
local string_percentage
if not prefix then
string_percentage = " %. " .. digits .. " f%% "
else
string_percentage = prefix .. " %. " .. digits .. " f%% "
end
return string_percentage : format ( self.progress_bar . percentage * 100 )
end
function ReaderFooter : textOptionTitles ( option )
local symbol = self.settings . item_prefix or " icons "
local option_titles = {
local option_titles = {
all_at_once = _ ( " Show all at once " ) ,
all_at_once = _ ( " Show all at once " ) ,
reclaim_height = _ ( " Reclaim bar height from bottom margin " ) ,
reclaim_height = _ ( " Reclaim bar height from bottom margin " ) ,
toc_markers = _ ( " Show chapter markers " ) ,
toc_markers = _ ( " Show chapter markers " ) ,
page_progress = _ ( " Current page " ) ,
page_progress = T ( _ ( " Current page (%1) " ) , " / " ) ,
time = _ ( " Current time " ) ,
time = symbol_prefix [ symbol ] . time
pages_left = _ ( " Pages left in chapter " ) ,
and T ( _ ( " Current time (%1) " ) , symbol_prefix [ symbol ] . time ) or _ ( " Current time " ) ,
battery = _ ( " Battery status " ) ,
pages_left = T ( _ ( " Pages left in chapter (%1) " ) , symbol_prefix [ symbol ] . pages_left ) ,
percentage = _ ( " Progress percentage " ) ,
battery = T ( _ ( " Battery status (%1) " ) , symbol_prefix [ symbol ] . battery ) ,
book_time_to_read = _ ( " Book time to read " ) ,
percentage = symbol_prefix [ symbol ] . percentage
chapter_time_to_read = _ ( " Chapter time to read " ) ,
and T ( _ ( " Progress percentage (%1) " ) , symbol_prefix [ symbol ] . percentage ) or ( " Progress percentage " ) ,
frontlight = _ ( " Frontlight level " ) ,
book_time_to_read = T ( _ ( " Book time to read (%1) " ) , symbol_prefix [ symbol ] . book_time_to_read ) ,
mem_usage = _ ( " KOReader memory usage " ) ,
chapter_time_to_read = T ( _ ( " Chapter time to read (%1) " ) , symbol_prefix [ symbol ] . chapter_time_to_read ) ,
wifi_status = _ ( " Wi-Fi status " ) ,
frontlight = T ( _ ( " Frontlight level (%1) " ) , symbol_prefix [ symbol ] . frontlight ) ,
mem_usage = T ( _ ( " KOReader memory usage (%1) " ) , symbol_prefix [ symbol ] . mem_usage ) ,
wifi_status = T ( _ ( " Wi-Fi status (%1) " ) , symbol_prefix [ symbol ] . wifi_status ) ,
}
}
return option_titles [ option ]
end
function ReaderFooter : addToMainMenu ( menu_items )
function ReaderFooter : addToMainMenu ( menu_items )
local sub_items = { }
local sub_items = { }
@ -400,7 +480,9 @@ function ReaderFooter:addToMainMenu(menu_items)
local getMinibarOption = function ( option , callback )
local getMinibarOption = function ( option , callback )
return {
return {
text = option_titles [ option ] ,
text_func = function ( )
return self : textOptionTitles ( option )
end ,
checked_func = function ( )
checked_func = function ( )
return self.settings [ option ] == true
return self.settings [ option ] == true
end ,
end ,
@ -456,30 +538,14 @@ function ReaderFooter:addToMainMenu(menu_items)
end ,
end ,
}
}
end
end
table.insert ( sub_items ,
getMinibarOption ( " all_at_once " , self.updateFooterTextGenerator ) )
table.insert ( sub_items ,
getMinibarOption ( " reclaim_height " ) )
table.insert ( sub_items , {
table.insert ( sub_items , {
text = _ ( " Progress bar " ) ,
text = _ ( " Settings " ) ,
sub_item_table = {
sub_item_table = {
getMinibarOption ( " all_at_once " , self.updateFooterTextGenerator ) ,
getMinibarOption ( " reclaim_height " ) ,
{
{
text = _ ( " Show progress bar " ) ,
checked_func = function ( )
return not self.settings . disable_progress_bar
end ,
callback = function ( )
self.settings . disable_progress_bar = not self.settings . disable_progress_bar
self : updateFooter ( )
UIManager : setDirty ( nil , " ui " )
end ,
} ,
getMinibarOption ( " toc_markers " , self.setTocMarkers ) ,
}
} )
table.insert ( sub_items , {
text = _ ( " Auto refresh time " ) ,
text = _ ( " Auto refresh time " ) ,
separator = true ,
checked_func = function ( )
checked_func = function ( )
return self.settings . auto_refresh_time == true
return self.settings . auto_refresh_time == true
end ,
end ,
@ -495,23 +561,12 @@ function ReaderFooter:addToMainMenu(menu_items)
self.onCloseDocument = nil
self.onCloseDocument = nil
end
end
end
end
} )
} ,
table.insert ( sub_items , getMinibarOption ( " page_progress " ) )
{
table.insert ( sub_items , getMinibarOption ( " time " ) )
table.insert ( sub_items , getMinibarOption ( " pages_left " ) )
table.insert ( sub_items , getMinibarOption ( " battery " ) )
table.insert ( sub_items , getMinibarOption ( " percentage " ) )
table.insert ( sub_items , getMinibarOption ( " book_time_to_read " ) )
table.insert ( sub_items , getMinibarOption ( " chapter_time_to_read " ) )
if Device : hasFrontlight ( ) then
table.insert ( sub_items , getMinibarOption ( " frontlight " ) )
end
table.insert ( sub_items , getMinibarOption ( " mem_usage " ) )
if Device : isAndroid ( ) then
table.insert ( sub_items , getMinibarOption ( " wifi_status " ) )
end
table.insert ( sub_items , {
text = _ ( " Alignment " ) ,
text = _ ( " Alignment " ) ,
enabled_func = function ( )
return self.settings . disable_progress_bar
end ,
sub_item_table = {
sub_item_table = {
{
{
text = _ ( " Center " ) ,
text = _ ( " Center " ) ,
@ -553,7 +608,198 @@ function ReaderFooter:addToMainMenu(menu_items)
end ,
end ,
} ,
} ,
}
}
} ,
{
text = _ ( " Prefix " ) ,
sub_item_table = {
{
text = _ ( " Icons " ) ,
checked_func = function ( )
return self.settings . item_prefix == " icons " or self.settings . item_prefix == nil
end ,
callback = function ( )
self.settings . item_prefix = " icons "
self : updateFooter ( )
UIManager : setDirty ( nil , " ui " )
end ,
} ,
{
text = _ ( " Letters " ) ,
checked_func = function ( )
return self.settings . item_prefix == " letters "
end ,
callback = function ( )
self.settings . item_prefix = " letters "
self : updateFooter ( )
UIManager : setDirty ( nil , " ui " )
end ,
} ,
} ,
} ,
{
text = _ ( " Separator " ) ,
sub_item_table = {
{
text = _ ( " Vertical line " ) .. " (|) " ,
checked_func = function ( )
return self.settings . items_separator == " bar " or self.settings . items_separator == nil
end ,
callback = function ( )
self.settings . items_separator = " bar "
self : updateFooter ( )
UIManager : setDirty ( nil , " ui " )
end ,
} ,
{
text = _ ( " Bullet " ) .. " (•) " ,
checked_func = function ( )
return self.settings . items_separator == " bullet "
end ,
callback = function ( )
self.settings . items_separator = " bullet "
self : updateFooter ( )
UIManager : setDirty ( nil , " ui " )
end ,
} ,
{
text = _ ( " No separator " ) ,
checked_func = function ( )
return self.settings . items_separator == " none "
end ,
callback = function ( )
self.settings . items_separator = " none "
self : updateFooter ( )
UIManager : setDirty ( nil , " ui " )
end ,
} ,
} ,
} ,
{
text = _ ( " Progress percentage format " ) ,
sub_item_table = {
{
text = T ( _ ( " No decimal point (%1) " ) , self : progressPercentage ( 0 ) ) ,
checked_func = function ( )
return self.settings . progress_pct_format == " 0 " or self.settings . progress_pct_format == nil
end ,
callback = function ( )
self.settings . progress_pct_format = " 0 "
self : updateFooter ( )
UIManager : setDirty ( nil , " ui " )
end ,
} ,
{
text = T ( _ ( " 1 digit after decimal point (%1) " ) , self : progressPercentage ( 1 ) ) ,
checked_func = function ( )
return self.settings . progress_pct_format == " 1 "
end ,
callback = function ( )
self.settings . progress_pct_format = " 1 "
self : updateFooter ( )
UIManager : setDirty ( nil , " ui " )
end ,
} ,
{
text = T ( _ ( " 2 digits after decimal point (%1) " ) , self : progressPercentage ( 2 ) ) ,
checked_func = function ( )
return self.settings . progress_pct_format == " 2 "
end ,
callback = function ( )
self.settings . progress_pct_format = " 2 "
self : updateFooter ( )
UIManager : setDirty ( nil , " ui " )
end ,
} ,
} ,
} ,
{
text = _ ( " Time format " ) ,
sub_item_table = {
{
text = _ ( " 24-hour " ) ,
checked_func = function ( )
return self.settings . time_format == " 24 " or self.settings . time_format == nil
end ,
callback = function ( )
self.settings . time_format = " 24 "
self : updateFooter ( )
UIManager : setDirty ( nil , " ui " )
end ,
} ,
{
text = _ ( " 12-hour " ) ,
checked_func = function ( )
return self.settings . time_format == " 12 "
end ,
callback = function ( )
self.settings . time_format = " 12 "
self : updateFooter ( )
UIManager : setDirty ( nil , " ui " )
end ,
} ,
}
} ,
{
text = _ ( " Durations format " ) ,
sub_item_table = {
{
text = _ ( " Modern " ) ,
checked_func = function ( )
return self.settings . duration_format == " modern " or self.settings . duration_format == nil
end ,
callback = function ( )
self.settings . duration_format = " modern "
self : updateFooter ( )
UIManager : setDirty ( nil , " ui " )
end ,
} ,
{
text = _ ( " Classic " ) ,
checked_func = function ( )
return self.settings . duration_format == " classic "
end ,
callback = function ( )
self.settings . duration_format = " classic "
self : updateFooter ( )
UIManager : setDirty ( nil , " ui " )
end ,
} ,
}
} ,
}
} )
} )
table.insert ( sub_items , {
text = _ ( " Progress bar " ) ,
separator = true ,
sub_item_table = {
{
text = _ ( " Show progress bar " ) ,
checked_func = function ( )
return not self.settings . disable_progress_bar
end ,
callback = function ( )
self.settings . disable_progress_bar = not self.settings . disable_progress_bar
self : updateFooter ( )
UIManager : setDirty ( nil , " ui " )
end ,
} ,
getMinibarOption ( " toc_markers " , self.setTocMarkers ) ,
}
} )
table.insert ( sub_items , getMinibarOption ( " page_progress " ) )
table.insert ( sub_items , getMinibarOption ( " time " ) )
table.insert ( sub_items , getMinibarOption ( " pages_left " ) )
table.insert ( sub_items , getMinibarOption ( " battery " ) )
table.insert ( sub_items , getMinibarOption ( " percentage " ) )
table.insert ( sub_items , getMinibarOption ( " book_time_to_read " ) )
table.insert ( sub_items , getMinibarOption ( " chapter_time_to_read " ) )
if Device : hasFrontlight ( ) then
table.insert ( sub_items , getMinibarOption ( " frontlight " ) )
end
table.insert ( sub_items , getMinibarOption ( " mem_usage " ) )
if Device : isAndroid ( ) then
table.insert ( sub_items , getMinibarOption ( " wifi_status " ) )
end
end
end
-- this method will be updated at runtime based on user setting
-- this method will be updated at runtime based on user setting
@ -561,10 +807,16 @@ function ReaderFooter:genFooterText() end
function ReaderFooter : genAllFooterText ( )
function ReaderFooter : genAllFooterText ( )
local info = { }
local info = { }
local separator = " "
if self.settings . items_separator == " bar " or self.settings . items_separator == nil then
separator = " | "
elseif self.settings . items_separator == " bullet " then
separator = " • "
end
for _ , gen in ipairs ( self.footerTextGenerators ) do
for _ , gen in ipairs ( self.footerTextGenerators ) do
table.insert ( info , gen ( self ) )
table.insert ( info , gen ( self ) )
end
end
return table.concat ( info , " | " )
return table.concat ( info , separator )
end
end
-- this method should never get called when footer is disabled
-- this method should never get called when footer is disabled
@ -608,7 +860,11 @@ function ReaderFooter:getDataFromStatistics(title, pages)
local sec = ' na '
local sec = ' na '
local average_time_per_page = self : getAvgTimePerPage ( )
local average_time_per_page = self : getAvgTimePerPage ( )
if average_time_per_page then
if average_time_per_page then
if self.settings . duration_format == " classic " then
sec = util.secondsToClock ( pages * average_time_per_page , true )
sec = util.secondsToClock ( pages * average_time_per_page , true )
else
sec = util.secondsToHClock ( pages * average_time_per_page , true )
end
end
end
return title .. sec
return title .. sec
end
end