diff --git a/Makefile b/Makefile
index 42fa72b3c..98d57980c 100644
--- a/Makefile
+++ b/Makefile
@@ -9,7 +9,8 @@ KOR_BASE=koreader-base
VERSION=$(shell git describe HEAD)
# subdirectory we use to build the installation bundle
-INSTALL_DIR=koreader-$(MACHINE)
+INSTALL_DIR=koreader
+INSTALL_DIR_KOBO=mnt/onboard/.kobo
# files to link from main directory
INSTALL_FILES=reader.lua frontend resources koreader.sh \
@@ -72,6 +73,42 @@ customupdate: all
-x "koreader/resources/fonts/*"
# @TODO write an installation script for KUAL (houqp)
+koboupdate: all
+ # ensure that the binaries were built for ARM
+ file $(KOR_BASE)/koreader-base | grep ARM || exit 1
+ file $(KOR_BASE)/extr | grep ARM || exit 1
+ # remove old package and dir if any
+ rm -f koreader-kobo-$(VERSION).zip
+ rm -rf $(INSTALL_DIR)
+ # create new dir for package
+ mkdir -p $(INSTALL_DIR)/{history,screenshots,clipboard,libs}
+ cp -p README.md COPYING $(KOR_BASE)/{koreader-base,extr,sdcv} koreader.sh koreader_kobo.sh $(LUA_FILES) $(INSTALL_DIR)
+ $(STRIP) --strip-unneeded $(INSTALL_DIR)/koreader-base $(INSTALL_DIR)/extr $(INSTALL_DIR)/sdcv
+ mkdir $(INSTALL_DIR)/data $(INSTALL_DIR)/data/dict $(INSTALL_DIR)/data/tessdata
+ cp -L koreader-base/$(DJVULIB) $(KOR_BASE)/$(CRELIB) \
+ $(KOR_BASE)/$(LUALIB) $(KOR_BASE)/$(K2PDFOPTLIB) \
+ $(KOR_BASE)/$(LEPTONICALIB) $(KOR_BASE)/$(TESSERACTLIB) \
+ $(INSTALL_DIR)/libs
+ $(STRIP) --strip-unneeded $(INSTALL_DIR)/libs/*
+ cp -rpL $(KOR_BASE)/data/*.css $(INSTALL_DIR)/data
+ cp -rpL $(KOR_BASE)/data/hyph $(INSTALL_DIR)/data/hyph
+ cp -rpL $(KOR_BASE)/fonts $(INSTALL_DIR)
+ cp -rp $(MO_DIR) $(INSTALL_DIR)
+ rm $(INSTALL_DIR)/fonts/droid/DroidSansFallbackFull.ttf
+ echo $(VERSION) > git-rev
+ cp -r git-rev resources $(INSTALL_DIR)
+ rm -r $(INSTALL_DIR)/resources/fonts
+ cp -rpL frontend $(INSTALL_DIR)
+ cp defaults.lua $(INSTALL_DIR)
+ mkdir $(INSTALL_DIR)/fonts/host
+ mkdir -p $(INSTALL_DIR_KOBO)/fmon
+ cp -rpL fmon $(INSTALL_DIR_KOBO)
+ cp -p resources/koreader.png $(INSTALL_DIR_KOBO)/..
+ tar -zcvf KoboRoot.tgz mnt/
+ zip -9 -r koreader-kobo-$(VERSION).zip $(INSTALL_DIR) KoboRoot.tgz
+ rm KoboRoot.tgz
+ rm -rf mnt/
+ rm -rf $(INSTALL_DIR)
pot:
$(XGETTEXT_BIN) reader.lua `find frontend -iname "*.lua"` \
diff --git a/fmon/koreader.sh b/fmon/koreader.sh
new file mode 100644
index 000000000..03ba8f433
--- /dev/null
+++ b/fmon/koreader.sh
@@ -0,0 +1 @@
+$root/.kobo/fmon/fmon $root/koreader.png $root/.kobo/koreader/koreader_kobo.sh &
diff --git a/frontend/apps/filemanager/fm.lua b/frontend/apps/filemanager/fm.lua
new file mode 100644
index 000000000..4396f2c00
--- /dev/null
+++ b/frontend/apps/filemanager/fm.lua
@@ -0,0 +1,87 @@
+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
+
+ self.banner = FrameContainer:new{
+ padding = 0,
+ bordersize = 0,
+ TextWidget:new{
+ face = Font:getFace("tfont", 24),
+ text = self.title,
+ }
+ }
+
+ local file_chooser = FileChooser:new{
+ -- remeber to adjust the height when new item is added to the group
+ height = Screen:getHeight() - self.banner:getSize().h,
+ 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.layout = VerticalGroup:new{
+ self.banner,
+ file_chooser,
+ }
+
+ local fm_ui = FrameContainer:new{
+ padding = 0,
+ bordersize = 0,
+ 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
diff --git a/frontend/apps/filemanager/fmhistory.lua b/frontend/apps/filemanager/fmhistory.lua
new file mode 100644
index 000000000..2b9dcb265
--- /dev/null
+++ b/frontend/apps/filemanager/fmhistory.lua
@@ -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
+
+
diff --git a/frontend/apps/filemanager/fmmenu.lua b/frontend/apps/filemanager/fmmenu.lua
new file mode 100644
index 000000000..b499fd9b9
--- /dev/null
+++ b/frontend/apps/filemanager/fmmenu.lua
@@ -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
+
diff --git a/frontend/lulip.lua b/frontend/lulip.lua
new file mode 100644
index 000000000..aee1c65a5
--- /dev/null
+++ b/frontend/lulip.lua
@@ -0,0 +1,190 @@
+-- lulip: LuaJIT line level profiler
+--
+-- Copyright (c) 2013 John Graham-Cumming
+--
+-- License: http://opensource.org/licenses/MIT
+
+local io_lines = io.lines
+local io_open = io.open
+local pairs = pairs
+local print = print
+local debug = debug
+local tonumber = tonumber
+local setmetatable = setmetatable
+local table_sort = table.sort
+local table_insert = table.insert
+local string_find = string.find
+local string_sub = string.sub
+local string_gsub = string.gsub
+local string_format = string.format
+local ffi = require("ffi")
+
+ffi.cdef[[
+ typedef long time_t;
+
+ typedef struct timeval {
+ time_t tv_sec;
+ time_t tv_usec;
+ } timeval;
+
+ int gettimeofday(struct timeval* t, void* tzp);
+]]
+
+module(...)
+
+local gettimeofday_struct = ffi.new("timeval")
+local function gettimeofday()
+ ffi.C.gettimeofday(gettimeofday_struct, nil)
+ return tonumber(gettimeofday_struct.tv_sec) * 1000000 + tonumber(gettimeofday_struct.tv_usec)
+end
+
+local mt = { __index = _M }
+
+-- new: create new profiler object
+function new(self)
+ return setmetatable({
+
+ -- Time when start() and stop() were called in microseconds
+
+ start_time = 0,
+ stop_time = 0,
+
+ -- Per line timing information
+
+ lines = {},
+
+ -- The current line being processed and when it was startd
+
+ current_line = nil,
+ current_start = 0,
+
+ -- List of files to ignore. Set patterns using dont()
+
+ ignore = {},
+
+ -- List of short file names used as a cache
+
+ short = {},
+
+ -- Maximum number of rows of output data, set using maxrows()
+
+ rows = 20,
+ }, mt)
+end
+
+-- event: called when a line is executed
+function event(self, event, line)
+ local now = gettimeofday()
+
+ local f = string_sub(debug.getinfo(3).source,2)
+ for i=1,#self.ignore do
+ if string_find(f, self.ignore[i], 1, true) then
+ return
+ end
+ end
+
+ local short = self.short[f]
+ if not short then
+ local start = string_find(f, "[^/]+$")
+ self.short[f] = string_sub(f, start)
+ short = self.short[f]
+ end
+
+ if self.current_line ~= nil then
+ self.lines[self.current_line][1] =
+ self.lines[self.current_line][1] + 1
+ self.lines[self.current_line][2] =
+ self.lines[self.current_line][2] + (now - self.current_start)
+ end
+
+ self.current_line = short .. ':' .. line
+
+ if self.lines[self.current_line] == nil then
+ self.lines[self.current_line] = {0, 0.0, f}
+ end
+
+ self.current_start = gettimeofday()
+end
+
+-- dont: tell the profiler to ignore files that match these patterns
+function dont(self, file)
+ table_insert(self.ignore, file)
+end
+
+-- maxrows: set the maximum number of rows of output
+function maxrows(self, max)
+ self.rows = max
+end
+
+-- start: begin profiling
+function start(self)
+ self:dont('lulip.lua')
+ self.start_time = gettimeofday()
+ self.current_line = nil
+ self.current_start = 0
+ debug.sethook(function(e,l) self:event(e, l) end, "l")
+end
+
+-- stop: end profiling
+function stop(self)
+ self.stop_time = gettimeofday()
+ debug.sethook()
+end
+
+-- readfile: turn a file into an array for line-level access
+local function readfile(file)
+ local lines = {}
+ local ln = 1
+ for line in io_lines(file) do
+ lines[ln] = string_gsub(line, "^%s*(.-)%s*$", "%1")
+ ln = ln + 1
+ end
+ return lines
+end
+
+-- dump: dump profile information to the named file
+function dump(self, file)
+ local t = {}
+ for l,d in pairs(self.lines) do
+ table_insert(t, {line=l, data=d})
+ end
+ table_sort(t, function(a,b) return a["data"][2] > b["data"][2] end)
+
+ local files = {}
+
+ local f = io_open(file, "w")
+ if not f then
+ print("Failed to open output file " .. file)
+ return
+ end
+ f:write([[
+
+
+
+
+
+
+
+file:line | count |
+elapsed (ms) | line |
+
+
+]])
+
+ for j=1,self.rows do
+ if not t[j] then break end
+ local l = t[j]["line"]
+ local d = t[j]["data"]
+ if not files[d[3]] then
+ files[d[3]] = readfile(d[3])
+ end
+ local ln = tonumber(string_sub(l, string_find(l, ":", 1, true)+1))
+ f:write(string_format([[
+%s | %i | %.3f |
+%s |
]],
+l, d[1], d[2]/1000, files[d[3]][ln]))
+ end
+ f:write('
self.max and self.max or intensity
+ self.intensity = intensity
+end
+
+function KindleFrontLight:init()
+ require "liblipclua"
+ self.lipc_handle = lipc.init("com.github.koreader")
+ if self.lipc_handle then
+ self.intensity = self.lipc_handle:get_int_property("com.lab126.powerd", "flIntensity")
+ end
+end
+
+function KindleFrontLight:toggle()
+ local f = io.open(self.kpw_fl, "r")
+ local sysint = tonumber(f:read("*all"):match("%d+"))
+ f:close()
+ if sysint == 0 then
+ self:setIntensity(self.intensity)
+ else
+ os.execute("echo -n 0 > " .. self.kpw_fl)
+ end
+end
+
+KindleFrontLight.intensityCheckBounds = BaseFrontLight.intensityCheckBounds
+
+function KindleFrontLight:setIntensity(intensity)
+ if self.lipc_handle ~= nil then
+ self:intensityCheckBounds(intensity)
+ self.lipc_handle:set_int_property("com.lab126.powerd", "flIntensity", self.intensity)
+ end
+end
+
+function KoboFrontLight:init()
+ self.fl = kobolight.open()
+end
+
+function KoboFrontLight:toggle()
+ if self.fl ~= nil then
+ self.fl:toggle()
+ end
+end
+
+KoboFrontLight.intensityCheckBounds = BaseFrontLight.intensityCheckBounds
+
+function KoboFrontLight:setIntensity(intensity)
+ if self.fl ~= nil then
+ self:intensityCheckBounds(intensity)
+ self.fl:setBrightness(self.intensity)
+ end
+end
diff --git a/frontend/ui/inputevent.lua b/frontend/ui/inputevent.lua
index a6bcaee9c..eb003e594 100644
--- a/frontend/ui/inputevent.lua
+++ b/frontend/ui/inputevent.lua
@@ -3,7 +3,6 @@ require "ui/device"
require "ui/time"
require "ui/gesturedetector"
require "ui/geometry"
-require "ui/reader/readerfrontlight"
-- constants from
EV_SYN = 0
@@ -273,9 +272,9 @@ function Input:init()
if util.isEmulated() == 1 then
self:initKeyMap()
- os.remove("emu_event")
- os.execute("mkfifo emu_event")
- input.open("emu_event")
+ os.remove("/tmp/emu_event")
+ os.execute("mkfifo /tmp/emu_event")
+ input.open("/tmp/emu_event")
-- SDL key codes
self.event_map = self.sdl_event_map
else
@@ -316,12 +315,14 @@ function Input:init()
end
print(_("Auto-detected Kindle Touch"))
elseif Device:isKobo() then
+ firm_rev = Device:getFirmVer()
input.open("/dev/input/event1")
Device:setTouchInputDev("/dev/input/event1")
input.open("/dev/input/event0") -- Light button and sleep slider
print(_("Auto-detected Kobo"))
self:adjustKoboEventMap()
- if dev_mod ~= 'Kobo_trilogy' then
+ if dev_mod ~= 'Kobo_trilogy' and firm_rev == "2.6.1"
+ or dev_mod == 'Kobo_dragon' then
function Input:eventAdjustHook(ev)
if ev.type == EV_ABS then
if ev.code == ABS_X then
@@ -339,6 +340,19 @@ function Input:init()
end
return ev
end
+ else
+ function Input:eventAdjustHook(ev)
+ if ev.code == ABS_X then
+ -- We always have to substract from the physical x,
+ -- regardless of the orientation
+ if (Screen.width 24 and 24 or intensity
- self.intensity = intensity
- self.lipc_handle:set_int_property("com.lab126.powerd", "flIntensity", intensity)
- UIManager:show(Notification:new{
- text = msg..intensity,
- timeout = 1
- })
- end
- if Device:isKobo() then
- if self.fl == nil then
- ReaderFrontLight:init()
- end
- if self.fl ~= nil then
- self.fl:setBrightness(intensity)
- self.intensity = intensity
- end
- end
- return true
+function ReaderFrontLight:addToMainMenu(tab_item_table)
+ -- insert fldial command to main reader menu
+ table.insert(tab_item_table.main, {
+ text = _("Frontlight settings"),
+ callback = function()
+ self:onShowFlDialog()
+ end,
+ })
end
-function ReaderFrontLight:toggle()
- if Device:isKobo() then
- if self.fl == nil then
- ReaderFrontLight:init()
- end
- if self.fl ~= nil then
- self.fl:toggle()
- end
+function ReaderFrontLight:onShowFlDialog()
+ local fl = Device:getFrontlight()
+ self.fl_dialog = InputDialog:new{
+ title = _("Frontlight Level"),
+ input_hint = ("(%d - %d)"):format(fl.min, fl.max),
+ buttons = {
+ {
+ {
+ text = _("Toggle"),
+ enabled = true,
+ callback = function()
+ fl:toggle()
+ end,
+ },
+ {
+ text = _("Apply"),
+ enabled = true,
+ callback = function()
+ self:fldialIntensity()
+ end,
+ },
+ {
+ text = _("OK"),
+ enabled = true,
+ callback = function()
+ self:fldialIntensity()
+ self:close()
+ end,
+ },
+
+ },
+ },
+ input_type = "number",
+ width = Screen:getWidth() * 0.8,
+ height = Screen:getHeight() * 0.2,
+ }
+ self.fl_dialog:onShowKeyboard()
+ UIManager:show(self.fl_dialog)
+end
+
+function ReaderFrontLight:close()
+ self.fl_dialog:onClose()
+ G_reader_settings:saveSetting("frontlight_intensity", Device:getFrontlight().intensity)
+ UIManager:close(self.fl_dialog)
+end
+
+function ReaderFrontLight:fldialIntensity()
+ local number = tonumber(self.fl_dialog:getInputText())
+ if number ~= nil then
+ Device:getFrontlight():setIntensity(number)
end
- return true
end
diff --git a/frontend/ui/reader/readermenu.lua b/frontend/ui/reader/readermenu.lua
index e0d297a56..157c17f3e 100644
--- a/frontend/ui/reader/readermenu.lua
+++ b/frontend/ui/reader/readermenu.lua
@@ -56,7 +56,6 @@ function ReaderMenu:setUpdateItemTable()
for _, widget in pairs(self.registered_widgets) do
widget:addToMainMenu(self.tab_item_table)
end
-
table.insert(self.tab_item_table.main, {
text = _("Help"),
callback = function()
diff --git a/frontend/ui/reader/readerview.lua b/frontend/ui/reader/readerview.lua
index 1967790a0..b6d1b652d 100644
--- a/frontend/ui/reader/readerview.lua
+++ b/frontend/ui/reader/readerview.lua
@@ -1,3 +1,4 @@
+require "ui/widget/group"
require "ui/reader/readerflip"
require "ui/reader/readerfooter"
require "ui/reader/readerdogear"
diff --git a/frontend/ui/readerui.lua b/frontend/ui/readerui.lua
index 96b8fd079..171283245 100644
--- a/frontend/ui/readerui.lua
+++ b/frontend/ui/readerui.lua
@@ -108,13 +108,12 @@ function ReaderUI:init()
}
table.insert(self, highlight)
-- goto
- local goto = ReaderGoto:new{
+ table.insert(self, ReaderGoto:new{
dialog = self.dialog,
view = self[1],
ui = self,
document = self.document,
- }
- table.insert(self, goto)
+ })
-- dictionary
local dict = ReaderDictionary:new{
dialog = self.dialog,
@@ -129,14 +128,15 @@ function ReaderUI:init()
view = self[1],
ui = self
}
- -- frontlight controller
- local reader_fl = ReaderFrontLight:new{
- dialog = self.dialog,
- view = self[1],
- ui = self
- }
table.insert(self.active_widgets, reader_ss)
- table.insert(self.active_widgets, reader_fl)
+ if Device:getFrontlight() then
+ -- frontlight controller
+ table.insert(self, ReaderFrontLight:new{
+ dialog = self.dialog,
+ view = self[1],
+ ui = self
+ })
+ end
if self.document.info.has_pages then
-- for page specific controller
diff --git a/frontend/ui/uimanager.lua b/frontend/ui/uimanager.lua
index a54560616..68853b053 100644
--- a/frontend/ui/uimanager.lua
+++ b/frontend/ui/uimanager.lua
@@ -1,6 +1,7 @@
require "ui/geometry"
require "ui/device"
require "ui/inputevent"
+require "ui/widget/container"
require "ui/screen"
require "debug"
require "gettext"
@@ -290,6 +291,8 @@ function UIManager:run()
Device:usbPlugIn()
elseif input_event == "NotCharging" then
Device:usbPlugOut()
+ elseif input_event == "Light" then
+ Device:getFrontlight():toggle()
else
self:sendEvent(input_event)
end
diff --git a/frontend/ui/widget/base.lua b/frontend/ui/widget/base.lua
index 6d4d85cb4..b66b6e49d 100644
--- a/frontend/ui/widget/base.lua
+++ b/frontend/ui/widget/base.lua
@@ -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
diff --git a/frontend/ui/widget/filechooser.lua b/frontend/ui/widget/filechooser.lua
index 38d70bbff..fc17fd1fd 100644
--- a/frontend/ui/widget/filechooser.lua
+++ b/frontend/ui/widget/filechooser.lua
@@ -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
diff --git a/frontend/ui/widget/menu.lua b/frontend/ui/widget/menu.lua
index fc157a2df..41649daed 100644
--- a/frontend/ui/widget/menu.lua
+++ b/frontend/ui/widget/menu.lua
@@ -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
diff --git a/koreader-base b/koreader-base
index 698fb1764..2dfda0da6 160000
--- a/koreader-base
+++ b/koreader-base
@@ -1 +1 @@
-Subproject commit 698fb1764ffc0eafbd5cdb2dcc6d8165cca8d8f0
+Subproject commit 2dfda0da69b721c0145b174cf3e5fb578c2894e1
diff --git a/koreader.sh b/koreader.sh
index 81fff38e5..f10015fc7 100755
--- a/koreader.sh
+++ b/koreader.sh
@@ -36,7 +36,7 @@ fi
#killall -stop cvm
# finally call reader
-./reader.lua "$1" 2> crash.log
+./reader.lua "$@" 2> crash.log
# clean up forked process in case the reader crashed
killall reader.lua
diff --git a/koreader_kobo.sh b/koreader_kobo.sh
index 16e7b1dfb..2cd418578 100644
--- a/koreader_kobo.sh
+++ b/koreader_kobo.sh
@@ -14,7 +14,7 @@ export STARDICT_DATA_DIR="data/dict"
killall nickel
# finally call reader
-./reader.lua "$1" 2> crash.log
+./reader.lua /mnt/onboard 2> crash.log
# continue with nickel
diff --git a/reader.lua b/reader.lua
index e90860bab..469476e1f 100755
--- a/reader.lua
+++ b/reader.lua
@@ -4,35 +4,22 @@ 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"
-
-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,
- }
- }
- },
- },
-}
+Profiler = nil
function exitReader()
+ if Profiler ~= nil then
+ Profiler:stop()
+ Profiler:dump("./profile.html")
+ end
+
G_reader_settings:close()
input.closeAll()
@@ -58,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{
@@ -141,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
@@ -189,6 +80,7 @@ end
-- option parsing:
longopts = {
debug = "d",
+ profile = "p",
help = "h",
}
@@ -197,6 +89,7 @@ function showusage()
print(_("Read all the books on your E-Ink reader"))
print("")
print(_("-d start in debug mode"))
+ print(_("-p [rows] enable Lua code profiling"))
print(_("-h show this usage help"))
print("")
print(_("If you give the name of a directory instead of a file path, a file"))
@@ -209,15 +102,38 @@ function showusage()
return
end
-if ARGV[1] == "-h" then
- return showusage()
-end
-
local argidx = 1
-if ARGV[1] == "-d" then
- Dbg:turnOn()
+while argidx <= #ARGV do
+ local arg = ARGV[argidx]
argidx = argidx + 1
-else
+ if arg == "--" then break end
+ -- parse longopts
+ if arg:sub(1,2) == "--" then
+ local opt = longopts[arg:sub(3)]
+ if opt ~= nil then arg = "-"..opt end
+ end
+ -- code for each option
+ if arg == "-h" then
+ return showusage()
+ elseif arg == "-d" then
+ Dbg:turnOn()
+ elseif arg == "-p" then
+ require "lulip"
+ Profiler = lulip:new()
+ pcall(function()
+ -- set maxrows only if the optional arg is numeric
+ Profiler:maxrows(ARGV[argidx] + 0)
+ argidx = argidx + 1
+ end)
+ Profiler:start()
+ else
+ -- not a recognized option, should be a filename
+ argidx = argidx - 1
+ break
+ end
+end
+
+if not Dbg.is_on then
DEBUG = function() end
end
@@ -238,16 +154,24 @@ local last_file = G_reader_settings:readSetting("lastfile")
--@TODO we can read version here, refer to commit in master tree: (houqp)
--87712cf0e43fed624f8a9f610be42b1fe174b9fe
+do
+ local fl = Device:getFrontlight()
+ if fl and fl.restore_settings then
+ local intensity = G_reader_settings:readSetting("frontlight_intensity")
+ intensity = intensity or fl.intensity
+ fl:setIntensity(intensity)
+ end
+end
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()
diff --git a/resources/koreader.png b/resources/koreader.png
new file mode 100644
index 000000000..1e6043247
Binary files /dev/null and b/resources/koreader.png differ