mirror of
https://github.com/koreader/koreader
synced 2024-10-31 21:20:20 +00:00
Merge pull request #352 from hwhw/NuPogodi-InfoMessages
New InfoMessage Concept
This commit is contained in:
commit
e846f2089b
@ -168,7 +168,7 @@ function Commands:new(obj)
|
||||
--os.execute("echo 'screensaver in' >> /mnt/us/event_test.txt")
|
||||
if G_charging_mode == false and G_screen_saver_mode == false then
|
||||
Screen:saveCurrentBB()
|
||||
InfoMessage:show("Going into screensaver... ", 0)
|
||||
InfoMessage:inform("Going into screensaver... ", nil, 0, MSG_AUX)
|
||||
Screen.kpv_rotation_mode = Screen.cur_rotation_mode
|
||||
fb:setOrientation(Screen.native_rotation_mode)
|
||||
util.sleep(1)
|
||||
@ -199,7 +199,7 @@ function Commands:new(obj)
|
||||
Screen:saveCurrentBB()
|
||||
Screen.kpv_rotation_mode = Screen.cur_rotation_mode
|
||||
fb:setOrientation(Screen.native_rotation_mode)
|
||||
InfoMessage:show("Going into USB mode... ", 0)
|
||||
InfoMessage:inform("Going into USB mode... ", nil, 0, MSG_AUX)
|
||||
util.sleep(1)
|
||||
os.execute("killall -cont cvm")
|
||||
end
|
||||
|
226
dialog.lua
226
dialog.lua
@ -1,7 +1,43 @@
|
||||
require "widget"
|
||||
require "font"
|
||||
|
||||
-- some definitions for developers
|
||||
MSG_AUX = 1
|
||||
MSG_WARN = 2
|
||||
MSG_ERROR = 3
|
||||
MSG_CONFIRM = 4
|
||||
MSG_BUG = 5
|
||||
|
||||
InfoMessage = {
|
||||
InfoMethod = { --[[
|
||||
The items define how to inform user about various types of events, the values should be 0..3:
|
||||
the lowest bit is responcible for showing popup windows,
|
||||
while the 2nd bit allows using TTS-voice messages.
|
||||
The current default values {1,1,1,1,1} correspond to previous kpdfviewer-settings
|
||||
when every message is shown in popup window. ]]
|
||||
1, -- auxiliary messages = 0 or 2 (nothing or TTS)
|
||||
1, -- warnings = 1 or 2 (popup or TTS)
|
||||
1, -- errors = 1 or 3 (popup or popup & TTS)
|
||||
1, -- confirmations (must not be silent!) = 1 or 3 (popup or popup & TTS)
|
||||
1, -- bugs (must not be silent!) = 1 or 3 (popup or popup & TTS)
|
||||
},
|
||||
-- images for various message types
|
||||
Images = {
|
||||
"resources/info-aux.png",
|
||||
"resources/info-warn.png",
|
||||
"resources/info-error.png",
|
||||
"resources/info-confirm.png",
|
||||
"resources/info-bug.png",
|
||||
},
|
||||
ImageFile = "resources/info-warn.png",
|
||||
-- TTS-related parameters
|
||||
TTSspeed = nil,
|
||||
SoundVolume = nil,
|
||||
|
||||
--[[ as Kindle3-volume has nonlinear scale, one need to define the 'VolumeLevels'-values
|
||||
TODO: test whether VolumeLevels are different for other sound-equipped Kindle models (K2, KDX)
|
||||
by running self.VolumeLevels = self:getVolumeLevels() ]]
|
||||
VolumeLevels = { 0, 1, 2, 4, 6, 7, 14, 21, 28, 35, 42, 49, 56, 63, 70, 77}
|
||||
}
|
||||
|
||||
function InfoMessage:show(text,refresh_mode)
|
||||
@ -14,7 +50,7 @@ function InfoMessage:show(text,refresh_mode)
|
||||
HorizontalGroup:new({
|
||||
align = "center",
|
||||
ImageWidget:new({
|
||||
file = "resources/info-i.png"
|
||||
file = self.ImageFile
|
||||
}),
|
||||
Widget:new({
|
||||
dimen = { w = 10, h = 0 }
|
||||
@ -54,3 +90,191 @@ function showInfoMsgWithDelay(text, msec, refresh_mode)
|
||||
Screen:restoreFromSavedBB()
|
||||
fb:refresh(refresh_mode)
|
||||
end
|
||||
|
||||
--[[ Unified function to inform user about smth. It is generally intended to replace showInfoMsgWithDelay() & InfoMessage:show().
|
||||
Since the former function is used in Lua-code more often than the latter, I kept here the same sequence of parameters as used in
|
||||
showInfoMsgWithDelay() + added two not obligatory parameters (see description below).
|
||||
|
||||
Thus, this trick allows multiple text replaces thoughout the whole Lua-code: 'showInfoMsgWithDelay(' to 'InfoMessage:inform('
|
||||
Yet, it would be much better to accompany such replaces by adding the 'message_importance' and, if needed, by
|
||||
'alternative_voice_message' that is not so restricted in length as 'text'
|
||||
|
||||
But replacing InfoMessage:show(...) by InfoMessage:inform(...) MUST be accompanied by adding the 2nd parameter -- either msec=nil or msec=0.
|
||||
Adding new parameters -- 'message_importance' & 'alternative_voice_message' -- is also appreciated.
|
||||
|
||||
Brief description of the function parameters
|
||||
-- text : is the text message for visual and (if 'alternative_voice_message' isn't defined) voice notification
|
||||
-- msec : parameter to define visual notification method
|
||||
msec=0: one calls InfoMessage:show(), otherwise one calls showInfoMsgWithDelay()
|
||||
msec>0: with either predefines msec-value or
|
||||
msec<0: autocalculated from the text length: one may eventually add user-configurable
|
||||
parameter 'reading_speed' that would define the popup exposition for this regime
|
||||
-- message_importance : parameter separating various messages on
|
||||
1 - not obligatory messages that might be readily avoided
|
||||
2 - warnings (important messages)
|
||||
3 - errors
|
||||
4 - confirmations
|
||||
5 - bugs
|
||||
-- alternative_voice_message: not obligatory parameter that allows to send longer messages to TTS-engine
|
||||
if not defined, the default 'text' will be TTS-voiced
|
||||
]]
|
||||
|
||||
function InfoMessage:inform(text, msec, refresh_mode, message_importance, alternative_voice_message)
|
||||
-- temporary test for 'message_importance'; it might be further removed as soon
|
||||
-- as every message will be properly marked by 'importance'
|
||||
if not message_importance then message_importance = 5 end
|
||||
local popup, voice = InfoMessage:getMethodForEvent(message_importance)
|
||||
if voice then
|
||||
alternative_voice_message = alternative_voice_message or text
|
||||
say(alternative_voice_message)
|
||||
-- here one may set pause -- it might be useful only if one sound message
|
||||
-- is directly followed by another, otherwise it's just wasting of time.
|
||||
--[[ if msec and msec ~=0 then
|
||||
-- pause = 0.5sec + 40ms/character * string.len() / normalized_voice_speed
|
||||
util.usleep(500000 + 40*alternative_voice_message:len*10000/self.TTSspeed)
|
||||
end ]]
|
||||
end
|
||||
if not popup then return end -- to avoid drawing popup window
|
||||
self.ImageFile = self.Images[message_importance] -- select proper image for window
|
||||
if not msec or msec == 0 then
|
||||
InfoMessage:show(text, refresh_mode)
|
||||
else
|
||||
if msec < 0 then msec = 500 + string.len(text) * 50 end
|
||||
showInfoMsgWithDelay(text, msec, refresh_mode)
|
||||
end
|
||||
end
|
||||
|
||||
function InfoMessage:getMethodForEvent(event)
|
||||
local popup, voice = true, true
|
||||
if self.InfoMethod[event] %2 == 0 then popup = false end
|
||||
if self.InfoMethod[event] < 2 then voice = false end
|
||||
return popup, voice
|
||||
end
|
||||
|
||||
-- GUI-methods for user to choose the way to inform about various events --
|
||||
|
||||
function InfoMessage:chooseMethodForEvent(event)
|
||||
local popup, voice = self:getMethodForEvent(event)
|
||||
local items_menu = SelectMenu:new{
|
||||
menu_title = "Choose the way how to inform you",
|
||||
item_array = {"Avoid any notifications",
|
||||
"Show popup window",
|
||||
"Use TTS-voice",
|
||||
"Popup window and TTS-voice",
|
||||
},
|
||||
current_entry = (popup and 1 or 0) + (voice and 1 or 0) * 2,
|
||||
}
|
||||
local item_no = items_menu:choose(0, fb.bb:getHeight())
|
||||
if item_no then
|
||||
self.InfoMethod[event] = item_no - 1
|
||||
-- just to illustrate the way how the selected method works; might be removed
|
||||
self:inform("Event = "..event..", Method = "..self.InfoMethod[event], -1500, 1, event,
|
||||
"You have chosen the method number "..self.InfoMethod[event].." for the event item number "..event)
|
||||
end
|
||||
end
|
||||
|
||||
function InfoMessage:chooseEventForMethod(event)
|
||||
event = event or 0
|
||||
local item_no = 0
|
||||
local event_list = {
|
||||
"Messages (e.g. 'Scanning folder...')",
|
||||
"Warnings (e.g. 'Already first jump!')",
|
||||
"Errors (e.g. 'Zip contains improper content!')",
|
||||
"Confirmations (e.g. 'Press Y to confirm deleting')",
|
||||
"Bugs",
|
||||
}
|
||||
while item_no ~= event and item_no < #event_list do
|
||||
item_no = item_no + 1
|
||||
end
|
||||
local event_menu = SelectMenu:new{
|
||||
menu_title = "Select the event type to tune",
|
||||
item_array = event_list,
|
||||
current_entry = item_no - 1,
|
||||
}
|
||||
item_no = event_menu:choose(0, G_height)
|
||||
return item_no
|
||||
end
|
||||
|
||||
function InfoMessage:chooseNotificatonMethods()
|
||||
local event = 1 -- default: auxiliary messages
|
||||
while event do
|
||||
event = self:chooseEventForMethod(event)
|
||||
if event then self:chooseMethodForEvent(event) end
|
||||
end
|
||||
end
|
||||
|
||||
---------------- audio-related functions ----------------
|
||||
|
||||
function InfoMessage:incrTTSspeed(direction) -- either +1 or -1
|
||||
-- make sure new TTS-speed is within reasonable range
|
||||
self.TTSspeed = math.max(self.TTSspeed + direction * 20, 40) -- min = 40%
|
||||
self.TTSspeed = math.min(self.TTSspeed, 200) -- max = 200%
|
||||
-- set new value & give an example for more convenient tuning
|
||||
os.execute('lipc-set-prop com.lab126.tts TtsISpeed '..self.TTSspeed)
|
||||
say("The current voice speed is "..self.TTSspeed.." percent.")
|
||||
end
|
||||
|
||||
function InfoMessage:getTTSspeed()
|
||||
local tmp = io.popen('lipc-get-prop com.lab126.tts TtsISpeed', "r")
|
||||
local speed = tmp:read("*number")
|
||||
tmp:close()
|
||||
return speed or 100 -- nominal TTS-speed
|
||||
end
|
||||
|
||||
function InfoMessage:incrSoundVolume(direction) -- either +1 or -1
|
||||
-- make sure that new volume is within reasonable range
|
||||
self.SoundVolume = math.max(self.SoundVolume + direction, 1)
|
||||
self.SoundVolume = math.min(self.SoundVolume, #self.VolumeLevels)
|
||||
-- set new value & give an example for more convenient tuning
|
||||
os.execute('lipc-set-prop com.lab126.audio Volume '..(self.SoundVolume-1))
|
||||
-- that is not exactly the volume percents, but more conventional values,
|
||||
-- than abstract units returned by 'lipc-get-prop com.lab126.audio Volume'
|
||||
local percents = math.floor(100*self.VolumeLevels[self.SoundVolume]/self.VolumeLevels[#self.VolumeLevels])
|
||||
say("The current sound volume is "..percents.." percent.")
|
||||
end
|
||||
|
||||
function InfoMessage:getSoundVolume()
|
||||
local tmp = io.popen('lipc-get-prop com.lab126.audio Volume', "r")
|
||||
local volume = tmp:read("*number")
|
||||
tmp:close()
|
||||
local i = 1
|
||||
while self.VolumeLevels[i] < volume and i < #self.VolumeLevels do
|
||||
i = i + 1
|
||||
end
|
||||
return i or 16 -- maximum volume
|
||||
end
|
||||
|
||||
--[[ -- to determine self.VolumeLevels in various Kindle-models
|
||||
function InfoMessage:getVolumeLevels()
|
||||
local levels, v, i = {}, 0, 0
|
||||
while i < 16 do -- proper K3-range 0..15 might be different for other models
|
||||
os.execute('lipc-set-prop com.lab126.audio Volume '..i)
|
||||
v = self:getSoundVolume()
|
||||
table.insert(levels, v)
|
||||
i = i + 1
|
||||
end
|
||||
return levels
|
||||
end ]]
|
||||
|
||||
function say(text)
|
||||
os.execute("say \""..text.."\"")
|
||||
end
|
||||
|
||||
-- The read/write global InfoMessage settings. When properly tested, the
|
||||
-- condition 'if FileChooser.filemanager_expert_mode == ...' might be deleted
|
||||
|
||||
function InfoMessage:initInfoMessageSettings()
|
||||
if FileChooser.filemanager_expert_mode == FileChooser.ROOT_MODE then
|
||||
InfoMessage.InfoMethod = G_reader_settings:readSetting("info_message_methods") or InfoMessage.InfoMethod
|
||||
InfoMessage.TTSspeed = G_reader_settings:readSetting("tts_speed") or InfoMessage:getTTSspeed()
|
||||
InfoMessage.SoundVolume = G_reader_settings:readSetting("sound_volume") or InfoMessage:getSoundVolume()
|
||||
end
|
||||
end
|
||||
|
||||
function InfoMessage:saveInfoMessageSettings()
|
||||
if FileChooser.filemanager_expert_mode == FileChooser.ROOT_MODE then
|
||||
G_reader_settings:saveSetting("info_message_methods", InfoMessage.InfoMethod)
|
||||
G_reader_settings:saveSetting("sound_volume", InfoMessage.SoundVolume-1)
|
||||
G_reader_settings:saveSetting("tts_speed", InfoMessage.TTSspeed)
|
||||
end
|
||||
end
|
||||
|
381
filechooser.lua
381
filechooser.lua
@ -29,33 +29,27 @@ FileChooser = {
|
||||
pagedirty = true,
|
||||
markerdirty = false,
|
||||
perpage,
|
||||
clipboard = lfs.currentdir() .. "/clipboard", -- NO finishing slash
|
||||
|
||||
-- NuPogodi, 04.09.2012: introduced modes that configures the filechoser
|
||||
-- for users with various purposes & skills
|
||||
clipboard = lfs.currentdir() .. "/clipboard", -- NO finishing slash
|
||||
before_clipboard, -- NuPogodi, 30.09.12: to store the path where jump to clipboard was made from
|
||||
|
||||
-- modes that configures the filechoser for users with various purposes & skills
|
||||
filemanager_expert_mode, -- default value is defined in reader.lua
|
||||
-- the definitions
|
||||
BEGINNERS_MODE = 1, -- the filemanager content is restricted by files with reader-related extensions; safe renaming (no extension)
|
||||
ADVANCED_MODE = 2, -- no extension-based filtering; renaming with extensions; appreciable danger to crash crengine by improper docs
|
||||
ROOT_MODE = 3, -- TODO: all functions (including non-stable and dangerous)
|
||||
|
||||
}
|
||||
|
||||
function getProperTitleLength(txt,font_face,max_width)
|
||||
local tw = TextWidget:new({ text = txt, face = font_face})
|
||||
-- 1st approximation for a point where to start title
|
||||
local n = math.floor(string.len(txt) * (1 - max_width / tw:getSize().w)) - 2
|
||||
n = math.max(n, 1)
|
||||
while tw:getSize().w >= max_width do
|
||||
tw:free()
|
||||
tw = TextWidget:new({ text = string.sub(txt,n,-1), face = font_face})
|
||||
n = n + 1
|
||||
-- NuPogodi, 29.09.12: simplified the code
|
||||
function getProperTitleLength(txt, font_face, max_width)
|
||||
while sizeUtf8Text(0, G_width, font_face, txt, true).x > max_width do
|
||||
txt = txt:sub(2, -1)
|
||||
end
|
||||
return string.sub(txt,n-1,-1)
|
||||
return txt
|
||||
end
|
||||
|
||||
function BatteryLevel()
|
||||
-- NuPogodi, 18.05.12: This command seems to work even without Amazon Kindle framework
|
||||
local p = io.popen("gasgauge-info -s 2> /dev/null", "r") -- io.popen() _never_ fails!
|
||||
local battery = p:read("*a") or "?"
|
||||
if battery == "" then battery = "?" end
|
||||
@ -63,36 +57,30 @@ function BatteryLevel()
|
||||
return string.gsub(battery, "[\n\r]+", "")
|
||||
end
|
||||
|
||||
-- NuPogodi, 29.09.12: avoid using widgets
|
||||
function DrawTitle(text,lmargin,y,height,color,font_face)
|
||||
local r = 6 -- radius for round corners
|
||||
color = 3 -- redefine to ignore the input for background color
|
||||
|
||||
fb.bb:paintRect(1, 1, fb.bb:getWidth() - 2, height - r, color)
|
||||
blitbuffer.paintBorder(fb.bb, 1, height/2, fb.bb:getWidth() - 2, height/2, height/2, color, r)
|
||||
-- to have a horisontal gap between text & background rectangle
|
||||
t = BatteryLevel() .. os.date(" %H:%M")
|
||||
local tw = TextWidget:new({ text = t, face = font_face})
|
||||
twidth = tw:getSize().w
|
||||
renderUtf8Text(fb.bb, fb.bb:getWidth()-twidth-lmargin, height-10, font_face, t, true)
|
||||
tw:free()
|
||||
|
||||
tw = TextWidget:new({ text = text, face = font_face})
|
||||
local max_width = fb.bb:getWidth() - 2*lmargin - twidth
|
||||
if tw:getSize().w < max_width then
|
||||
fb.bb:paintRect(1, 1, G_width-2, height - r, color)
|
||||
blitbuffer.paintBorder(fb.bb, 1, height/2, G_width-2, height/2, height/2, color, r)
|
||||
local t = BatteryLevel() .. os.date(" %H:%M")
|
||||
r = sizeUtf8Text(0, G_width, font_face, t, true).x
|
||||
renderUtf8Text(fb.bb, G_width-r-lmargin, height-10, font_face, t, true)
|
||||
r = G_width - r - 2 * lmargin - 10 -- let's leave small gap
|
||||
if sizeUtf8Text(0, G_width, font_face, text, true).x <= r then
|
||||
renderUtf8Text(fb.bb, lmargin, height-10, font_face, text, true)
|
||||
else
|
||||
local w = renderUtf8Text(fb.bb, lmargin, height-10, font_face, "...", true)
|
||||
local txt = getProperTitleLength(text, font_face, max_width-w)
|
||||
renderUtf8Text(fb.bb, w+lmargin, height-10, font_face, txt, true)
|
||||
t = renderUtf8Text(fb.bb, lmargin, height-10, font_face, "...", true)
|
||||
text = getProperTitleLength(text, font_face, r-t)
|
||||
renderUtf8Text(fb.bb, lmargin+t, height-10, font_face, text, true)
|
||||
end
|
||||
tw:free()
|
||||
end
|
||||
|
||||
function DrawFooter(text,font_face,h)
|
||||
local y = G_height - 7
|
||||
-- NuPogodi, 29.09.12: just dirty fix to have the same footer everywhere
|
||||
-- just dirty fix to have the same footer everywhere
|
||||
local x = FileChooser.margin_H --(G_width / 2) - 50
|
||||
renderUtf8Text(fb.bb, x, y, font_face, text.." - Press H for help", true)
|
||||
renderUtf8Text(fb.bb, x, y, font_face, text.." - Press H for help", true)
|
||||
end
|
||||
|
||||
function DrawFileItem(name,x,y,image)
|
||||
@ -106,11 +94,11 @@ function DrawFileItem(name,x,y,image)
|
||||
-- then drawing filenames
|
||||
local cface = Font:getFace("cfont", 22)
|
||||
local xleft = x + iw:getSize().w + 9 -- the gap between icon & filename
|
||||
local width = fb.bb:getWidth() - xleft - x
|
||||
local width = G_width - xleft - x
|
||||
-- now printing the name
|
||||
if sizeUtf8Text(xleft, fb.bb:getWidth() - x, cface, name, true).x < width then
|
||||
if sizeUtf8Text(xleft, G_width - x, cface, name, true).x < width then
|
||||
renderUtf8Text(fb.bb, xleft, y, cface, name, true)
|
||||
else
|
||||
else
|
||||
local lgap = sizeUtf8Text(0, width, cface, " ...", true).x
|
||||
local handle = renderUtf8TextWidth(fb.bb, xleft, y, cface, name, true, width - lgap - x)
|
||||
renderUtf8Text(fb.bb, handle.x + lgap + x, y, cface, " ...", true)
|
||||
@ -162,6 +150,10 @@ end
|
||||
|
||||
function FileChooser:setPath(newPath)
|
||||
local curr_path = self.path
|
||||
if self.before_clipboard then -- back from clipboard
|
||||
newPath = self.before_clipboard
|
||||
self.before_clipboard = nil
|
||||
end
|
||||
self.path = getAbsolutePath(newPath)
|
||||
local readdir_ok, exc = pcall(self.readDir,self)
|
||||
if(not readdir_ok) then
|
||||
@ -173,8 +165,20 @@ function FileChooser:setPath(newPath)
|
||||
if self.items == 0 then
|
||||
return nil
|
||||
end
|
||||
self.page = 1
|
||||
self.current = 1
|
||||
-- NuPogodi, 02.10.12: 1) changing the current item position ONLY IF the path was changed
|
||||
-- 2) trying to set marker under the folder that was just left by ".."
|
||||
if self.path ~= curr_path then
|
||||
local i = 2
|
||||
while i <= #self.dirs and not string.find(curr_path, self.dirs[i]) do
|
||||
i = i + 1
|
||||
end
|
||||
if i <= #self.dirs then -- found
|
||||
self.current, self.page = gotoTargetItem(i, self.items, self.current, self.page, self.perpage)
|
||||
else -- set defaults
|
||||
self.page = 1
|
||||
self.current = 1
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
@ -210,7 +214,7 @@ function FileChooser:choose(ypos, height)
|
||||
local msg = self.exception_message and self.exception_message:match("[^%:]+:%d+: (.*)") or self.path
|
||||
self.exception_message = nil
|
||||
-- draw header
|
||||
DrawTitle(msg,self.margin_H,ypos,self.title_H,4,tface)
|
||||
DrawTitle(msg,self.margin_H,ypos,self.title_H,3,tface)
|
||||
self.markerdirty = true
|
||||
end
|
||||
|
||||
@ -260,7 +264,7 @@ function FileChooser:choose(ypos, height)
|
||||
end -- while
|
||||
end
|
||||
|
||||
-- NuPogodi, 20.05.12: add available commands
|
||||
-- add available commands
|
||||
function FileChooser:addAllCommands()
|
||||
self.commands = Commands:new{}
|
||||
|
||||
@ -270,35 +274,8 @@ function FileChooser:addAllCommands()
|
||||
self.pagedirty = true
|
||||
end
|
||||
)
|
||||
self.commands:add({KEY_PGFWD, KEY_LPGFWD}, nil, ">",
|
||||
"goto next page",
|
||||
function(self)
|
||||
if self.page < (self.items / self.perpage) then
|
||||
if self.current + self.page*self.perpage > self.items then
|
||||
self.current = self.items - self.page*self.perpage
|
||||
end
|
||||
self.page = self.page + 1
|
||||
self.pagedirty = true
|
||||
else
|
||||
self.current = self.items - (self.page-1)*self.perpage
|
||||
self.markerdirty = true
|
||||
end
|
||||
end
|
||||
)
|
||||
self.commands:add({KEY_PGBCK, KEY_LPGBCK}, nil, "<",
|
||||
"goto previous page",
|
||||
function(self)
|
||||
if self.page > 1 then
|
||||
self.page = self.page - 1
|
||||
self.pagedirty = true
|
||||
else
|
||||
self.current = 1
|
||||
self.markerdirty = true
|
||||
end
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_FW_DOWN, nil, "joypad down",
|
||||
"goto next item",
|
||||
"next item",
|
||||
function(self)
|
||||
if self.current == self.perpage then
|
||||
if self.page < (self.items / self.perpage) then
|
||||
@ -316,7 +293,7 @@ function FileChooser:addAllCommands()
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_FW_UP, nil, "joypad up",
|
||||
"goto previous item",
|
||||
"previous item",
|
||||
function(self)
|
||||
if self.current == 1 then
|
||||
if self.page > 1 then
|
||||
@ -330,16 +307,69 @@ function FileChooser:addAllCommands()
|
||||
end
|
||||
end
|
||||
)
|
||||
self.commands:add({KEY_FW_RIGHT, KEY_I}, nil, "joypad right",
|
||||
-- NuPogodi, 01.10.12: fast jumps to items at positions 10, 20, .. 90, 0% within the list
|
||||
local numeric_keydefs, i = {}
|
||||
for i=1, 10 do numeric_keydefs[i]=Keydef:new(KEY_1+i-1, nil, tostring(i%10)) end
|
||||
self.commands:addGroup("[1, 2 .. 9, 0]", numeric_keydefs,
|
||||
"item at position 0%, 10% .. 90%, 100%",
|
||||
function(self)
|
||||
local target_item = math.ceil(self.items * (keydef.keycode-KEY_1) / 9)
|
||||
self.current, self.page, self.markerdirty, self.pagedirty =
|
||||
gotoTargetItem(target_item, self.items, self.current, self.page, self.perpage)
|
||||
end
|
||||
)
|
||||
self.commands:add({KEY_PGFWD, KEY_LPGFWD}, nil, ">",
|
||||
"next page",
|
||||
function(self)
|
||||
if self.page < (self.items / self.perpage) then
|
||||
if self.current + self.page*self.perpage > self.items then
|
||||
self.current = self.items - self.page*self.perpage
|
||||
end
|
||||
self.page = self.page + 1
|
||||
self.pagedirty = true
|
||||
else
|
||||
self.current = self.items - (self.page-1)*self.perpage
|
||||
self.markerdirty = true
|
||||
end
|
||||
end
|
||||
)
|
||||
self.commands:add({KEY_PGBCK, KEY_LPGBCK}, nil, "<",
|
||||
"previous page",
|
||||
function(self)
|
||||
if self.page > 1 then
|
||||
self.page = self.page - 1
|
||||
self.pagedirty = true
|
||||
else
|
||||
self.current = 1
|
||||
self.markerdirty = true
|
||||
end
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_G, nil, "G", -- NuPogodi, 01.10.12: goto page No.
|
||||
"goto page",
|
||||
function(self)
|
||||
local n = math.ceil(self.items / self.perpage)
|
||||
local page = NumInputBox:input(G_height-100, 100, "Page:", "current page "..self.page.." of "..n, true)
|
||||
if pcall(function () page = math.floor(page) end) -- convert string to number
|
||||
and page ~= self.page and page > 0 and page <= n then
|
||||
self.page = page
|
||||
if self.current + (page-1)*self.perpage > self.items then
|
||||
self.current = self.items - (page-1)*self.perpage
|
||||
end
|
||||
end
|
||||
self.pagedirty = true
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_FW_RIGHT, nil, "joypad right",
|
||||
"show document information",
|
||||
function(self)
|
||||
local folder = self.dirs[self.perpage*(self.page-1)+self.current]
|
||||
if folder then
|
||||
if folder == ".." then
|
||||
showInfoMsgWithDelay("<UP-DIR> ", 1000, 1)
|
||||
warningUnsupportedFunction()
|
||||
else
|
||||
folder = self.path.."/"..folder
|
||||
if FileInfo:show(folder) == "goto" then
|
||||
if FileInfo:show(folder) == "goto" then
|
||||
self:setPath(folder)
|
||||
end
|
||||
end
|
||||
@ -365,39 +395,29 @@ function FileChooser:addAllCommands()
|
||||
self.pagedirty = true
|
||||
end
|
||||
)
|
||||
-- NuPogodi, 23.05.12: modified to delete both files and empty folders
|
||||
-- modified to delete both files and empty folders
|
||||
self.commands:add(KEY_DEL, nil, "Del",
|
||||
"delete selected item",
|
||||
function(self)
|
||||
local pos = self.perpage*(self.page-1)+self.current
|
||||
local folder = self.dirs[pos]
|
||||
if folder == ".." then
|
||||
showInfoMsgWithDelay(".. cannot be deleted! ",1500,1)
|
||||
elseif folder then
|
||||
InfoMessage:show("Press \'Y\' to confirm",0)
|
||||
if self:ReturnKey() == KEY_Y then
|
||||
if lfs.rmdir(self.path.."/"..folder) then
|
||||
table.remove(self.dirs, offset)
|
||||
self:setPath(self.path)
|
||||
else
|
||||
showInfoMsgWithDelay("Cannot be deleted!",1500,1)
|
||||
end
|
||||
local confirm = "Please, press key Y to confirm deleting"
|
||||
if pos > #self.dirs then -- file
|
||||
if InfoMessage.InfoMethod[MSG_CONFIRM] == 0 then -- silent regime
|
||||
self:deleteFileAtPosition(pos)
|
||||
else
|
||||
InfoMessage:inform("Press 'Y' to confirm ", nil, 0, MSG_CONFIRM, confirm)
|
||||
if self:ReturnKey() == KEY_Y then self:deleteFileAtPosition(pos) end
|
||||
end
|
||||
else
|
||||
InfoMessage:show("Press \'Y\' to confirm",0)
|
||||
if self:ReturnKey() == KEY_Y then
|
||||
pos = pos - #self.dirs
|
||||
local fullpath = self.path.."/"..self.files[pos]
|
||||
-- delete the file itself
|
||||
os.remove(fullpath)
|
||||
-- and its history file, if any
|
||||
os.remove(DocToHistory(fullpath))
|
||||
-- to avoid showing just deleted file
|
||||
table.remove(self.files, pos)
|
||||
self.items = self.items - 1
|
||||
self.current = self.current - 1
|
||||
elseif self.dirs[pos] == ".." then
|
||||
warningUnsupportedFunction()
|
||||
else -- other folders
|
||||
if InfoMessage.InfoMethod[MSG_CONFIRM] == 0 then -- silent regime
|
||||
self:deleteFolderAtPosition(pos)
|
||||
else
|
||||
InfoMessage:inform("Press 'Y' to confirm ", nil, 0, MSG_CONFIRM, confirm)
|
||||
if self:ReturnKey() == KEY_Y then self:deleteFolderAtPosition(pos) end
|
||||
end
|
||||
end -- if folder == ".."
|
||||
end
|
||||
self.pagedirty = true
|
||||
end -- function
|
||||
)
|
||||
@ -427,14 +447,48 @@ function FileChooser:addAllCommands()
|
||||
end
|
||||
end
|
||||
)
|
||||
-- NuPogodi, 04.09.12: menu to switch the filechooser mode
|
||||
self.commands:add(KEY_M, MOD_ALT, "M",
|
||||
"set mode for filemanager",
|
||||
function(self)
|
||||
self:changeFileChooserMode()
|
||||
end
|
||||
)
|
||||
self.commands:add({KEY_F, KEY_AA}, nil, "F",
|
||||
-- NuPogodi, 25.09.12: new functions to tune the way how to inform user about the reader events
|
||||
local popup_text = "Unstable... For experts only! "
|
||||
local voice_text = "This function is still under development and available only for experts and beta testers."
|
||||
self.commands:add(KEY_I, nil, "I",
|
||||
"change the way to inform about events",
|
||||
function(self)
|
||||
if self.filemanager_expert_mode == self.ROOT_MODE then
|
||||
InfoMessage:chooseNotificatonMethods()
|
||||
self.pagedirty = true
|
||||
else
|
||||
InfoMessage:inform(popup_text, -1, 1, MSG_WARN, voice_text)
|
||||
end
|
||||
end
|
||||
)
|
||||
self.commands:addGroup("Vol-/+", {Keydef:new(KEY_VPLUS,nil), Keydef:new(KEY_VMINUS,nil)},
|
||||
"decrease/increase sound volume",
|
||||
function(self)
|
||||
if self.filemanager_expert_mode == self.ROOT_MODE then
|
||||
InfoMessage:incrSoundVolume(keydef.keycode == KEY_VPLUS and 1 or -1)
|
||||
else
|
||||
InfoMessage:inform(popup_text, -1, 1, MSG_WARN, voice_text)
|
||||
end
|
||||
end
|
||||
)
|
||||
self.commands:addGroup(MOD_SHIFT.."Vol-/+", {Keydef:new(KEY_VPLUS,MOD_SHIFT), Keydef:new(KEY_VMINUS,MOD_SHIFT)},
|
||||
"decrease/increase TTS-engine speed",
|
||||
function(self)
|
||||
if self.filemanager_expert_mode == self.ROOT_MODE then
|
||||
InfoMessage:incrTTSspeed(keydef.keycode == KEY_VPLUS and 1 or -1)
|
||||
else
|
||||
InfoMessage:inform(popup_text, -1, 1, MSG_WARN, voice_text)
|
||||
end
|
||||
end
|
||||
)
|
||||
------------ end of changes (NuPogodi, 25.09.12) ------------
|
||||
self.commands:add({KEY_F, KEY_AA}, nil, "F, Aa",
|
||||
"change font faces",
|
||||
function(self)
|
||||
Font:chooseFonts()
|
||||
@ -447,7 +501,7 @@ function FileChooser:addAllCommands()
|
||||
HelpPage:show(0, G_height, self.commands)
|
||||
self.pagedirty = true
|
||||
end
|
||||
)
|
||||
)
|
||||
self.commands:add(KEY_L, nil, "L",
|
||||
"show last documents",
|
||||
function(self)
|
||||
@ -462,16 +516,17 @@ function FileChooser:addAllCommands()
|
||||
function(self)
|
||||
local keywords = InputBox:input(0, 0, "Search:")
|
||||
if keywords then
|
||||
InfoMessage:show("Searching... ",0)
|
||||
InfoMessage:inform("Searching... ", nil, 1, MSG_AUX)
|
||||
FileSearcher:init( self.path )
|
||||
FileSearcher:choose(keywords)
|
||||
end
|
||||
self.pagedirty = true
|
||||
end -- function
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_C, MOD_SHIFT, "C",
|
||||
"copy file to \'clipboard\'",
|
||||
"copy file to 'clipboard'",
|
||||
function(self)
|
||||
-- TODO (NuPogodi, 27.09.12): overwrite?
|
||||
local file = self:FullFileName()
|
||||
if file then
|
||||
lfs.mkdir(self.clipboard)
|
||||
@ -479,29 +534,34 @@ function FileChooser:addAllCommands()
|
||||
local fn = self.files[self.perpage*(self.page-1)+self.current - #self.dirs]
|
||||
os.execute("cp "..self:InQuotes(DocToHistory(file)).." "
|
||||
..self:InQuotes(DocToHistory(self.clipboard.."/"..fn)) )
|
||||
showInfoMsgWithDelay("File copied to clipboard ", 1000, 1)
|
||||
InfoMessage:inform("File copied to clipboard ", 1000, 1, MSG_WARN,
|
||||
"The file has been copied to clipboard.")
|
||||
end
|
||||
end
|
||||
)
|
||||
)
|
||||
self.commands:add(KEY_X, MOD_SHIFT, "X",
|
||||
"move file to \'clipboard\'",
|
||||
"move file to 'clipboard'",
|
||||
function(self)
|
||||
-- TODO (NuPogodi, 27.09.12): overwrite?
|
||||
local file = self:FullFileName()
|
||||
if file then
|
||||
lfs.mkdir(self.clipboard)
|
||||
local fn = self.files[self.perpage*(self.page-1)+self.current - #self.dirs]
|
||||
os.rename(file, self.clipboard.."/"..fn)
|
||||
os.rename(DocToHistory(file), DocToHistory(self.clipboard.."/"..fn))
|
||||
InfoMessage:show("File moved to clipboard ", 0)
|
||||
InfoMessage:inform("File moved to clipboard ", nil, 0, MSG_WARN,
|
||||
"The file has been moved to clipboard.")
|
||||
self:setPath(self.path)
|
||||
self.pagedirty = true
|
||||
end
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_V, MOD_SHIFT, "V",
|
||||
"paste file(s) from \'clipboard\'",
|
||||
"paste file(s) from 'clipboard'",
|
||||
function(self)
|
||||
InfoMessage:show("moving file(s) from clipboard ", 0)
|
||||
-- TODO (NuPogodi, 27.09.12): first test whether the clipboard is empty & answer respectively
|
||||
-- TODO (NuPogodi, 27.09.12): overwrite?
|
||||
InfoMessage:inform("Moving files from clipboard...", nil, 0, MSG_AUX)
|
||||
for f in lfs.dir(self.clipboard) do
|
||||
if lfs.attributes(self.clipboard.."/"..f, "mode") == "file" then
|
||||
os.rename(self.clipboard.."/"..f, self.path.."/"..f)
|
||||
@ -513,11 +573,15 @@ function FileChooser:addAllCommands()
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_B, MOD_SHIFT, "B",
|
||||
"show content of \'clipboard\'",
|
||||
"show content of 'clipboard'",
|
||||
function(self)
|
||||
-- NuPogodi, 30.09.12: exit back from clipboard to last folder by '..'
|
||||
local current_path = self.path
|
||||
lfs.mkdir(self.clipboard)
|
||||
self:setPath(self.clipboard)
|
||||
-- TODO: exit back from clipboard to last folder - Redefine Exit on FW_Right?
|
||||
if self.clipboard ~= self.path then
|
||||
self:setPath(self.clipboard)
|
||||
self.before_clipboard = current_path
|
||||
end
|
||||
self.pagedirty = true
|
||||
end
|
||||
)
|
||||
@ -536,13 +600,12 @@ function FileChooser:addAllCommands()
|
||||
self.commands:add(KEY_K, MOD_SHIFT, "K",
|
||||
"run calculator",
|
||||
function(self)
|
||||
local CalcBox = InputBox:new{ calcmode = true }
|
||||
local CalcBox = InputBox:new{ inputmode = MODE_CALC }
|
||||
CalcBox:input(0, 0, "Calc ")
|
||||
self.pagedirty = true
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_HOME, nil, "Home",
|
||||
"exit",
|
||||
self.commands:addGroup("Home, Alt + Back", { Keydef:new(KEY_HOME, nil),Keydef:new(KEY_BACK, MOD_ALT)}, "exit",
|
||||
function(self)
|
||||
return "break"
|
||||
end
|
||||
@ -551,19 +614,14 @@ end
|
||||
|
||||
-- returns full filename or nil (if folder)
|
||||
function FileChooser:FullFileName()
|
||||
local file
|
||||
local folder = self.dirs[self.perpage*(self.page-1)+self.current]
|
||||
if folder == ".." then
|
||||
showInfoMsgWithDelay("<UP-DIR> ",1000,1)
|
||||
elseif folder then
|
||||
showInfoMsgWithDelay("<DIR> ",1000,1)
|
||||
else
|
||||
file=self.path.."/"..self.files[self.perpage*(self.page-1)+self.current - #self.dirs]
|
||||
if self.current > #self.dirs then
|
||||
return self.path.."/"..self.files[self.perpage*(self.page-1)+self.current - #self.dirs]
|
||||
end
|
||||
return file
|
||||
warningUnsupportedFunction()
|
||||
return nil
|
||||
end
|
||||
-- returns the keycode of released key and (if debug) shows the keycode on screen
|
||||
function FileChooser:ReturnKey(debug)
|
||||
-- returns the keycode of released key
|
||||
function FileChooser:ReturnKey()
|
||||
while true do
|
||||
ev = input.saveWaitForEvent()
|
||||
ev.code = adjustKeyEvents(ev)
|
||||
@ -571,7 +629,6 @@ function FileChooser:ReturnKey(debug)
|
||||
break
|
||||
end
|
||||
end
|
||||
if debug then showInfoMsgWithDelay("Keycode = "..ev.code,1000,1) end
|
||||
return ev.code
|
||||
end
|
||||
|
||||
@ -582,11 +639,11 @@ end
|
||||
--[[ NuPogodi, 04.09.2012: to make it more easy for users with various purposes and skills.
|
||||
ATM, one may leave only silent toggling between BEGINNERS_MODE <> ADVANCED_MODE
|
||||
-- But, in future, one more (the so called ROOT_MODE) might also be rather useful.
|
||||
Shitch this mode on should allow developers & beta-testers to use some unstable
|
||||
Switching this mode on should allow developers & beta-testers to use some unstable
|
||||
and/or dangerous functions able to crash the reader. ]]
|
||||
|
||||
function FileChooser:changeFileChooserMode()
|
||||
local face_list = { "safe mode for beginners", "advanced mode for experienced users", "expert mode for beta-testers & developers" }
|
||||
local face_list = { "Safe mode for beginners", "Advanced mode for experienced users", "Expert mode for beta-testers & developers" }
|
||||
local modes_menu = SelectMenu:new{
|
||||
menu_title = "Select proper mode to manage files",
|
||||
item_array = face_list,
|
||||
@ -594,30 +651,58 @@ function FileChooser:changeFileChooserMode()
|
||||
}
|
||||
local m = modes_menu:choose(0, G_height)
|
||||
if m and m ~= self.filemanager_expert_mode then
|
||||
--[[ TODO: to allow multiline-rendering for info messages & to include detailed description of the selected mode
|
||||
local msg = "Press 'Y' to accept new mode..."
|
||||
if m==self.BEGINNERS_MODE then
|
||||
msg = "You have selected safe mode for beginners: the filemanager shows only files with the reader-related extensions (*.pdf, *.djvu, etc.); "..
|
||||
"safe renaming (no extensions); unstable or dangerous functions are NOT included. "..msg
|
||||
elseif m==self.ADVANCED_MODE then
|
||||
msg = "You have selected advanced mode for experienced users: the filemanager shows all files; "..
|
||||
"you may rename not only their names, but also the extensions; the files with unknown extensions would be sent to CREReader "..
|
||||
"and could crash the reader. Please, use it in your own risk. "..msg
|
||||
else -- ROOT_MODE
|
||||
msg = "You have selected the most advanced and dangerous mode. I hope You know what you are doing. God bless You. "..msg
|
||||
end
|
||||
InfoMessage:show(msg, 1)
|
||||
if self:ReturnKey() == KEY_Y then ]]
|
||||
if (self.filemanager_expert_mode == self.BEGINNERS_MODE and m > self.BEGINNERS_MODE)
|
||||
or (m == self.BEGINNERS_MODE and self.filemanager_expert_mode > self.BEGINNERS_MODE) then
|
||||
self.filemanager_expert_mode = m -- make sure that new mode is set before...
|
||||
self:setPath(self.path) -- refreshing the folder content
|
||||
self:setPath(self.path) -- refreshing the folder content
|
||||
else
|
||||
self.filemanager_expert_mode = m
|
||||
end
|
||||
G_reader_settings:saveSetting("filemanager_expert_mode", self.filemanager_expert_mode)
|
||||
-- end
|
||||
end
|
||||
-- NuPogodi, 26.09.2012: temporary place; when properly tested, might be commented / deleted the following line
|
||||
InfoMessage:initInfoMessageSettings()
|
||||
self.pagedirty = true
|
||||
end
|
||||
|
||||
-- NuPogodi, 28.09.12: two following functions are extracted just to make the code more compact
|
||||
function FileChooser:deleteFolderAtPosition(pos)
|
||||
if lfs.rmdir(self.path.."/"..self.dirs[pos]) then
|
||||
table.remove(self.dirs, pos) -- to avoid showing just deleted file
|
||||
self.items = #self.dirs + #self.files
|
||||
self.current, self.page = gotoTargetItem(pos, self.items, pos, self.page, self.perpage)
|
||||
else
|
||||
InfoMessage:inform("Folder can't be deleted! ", 1500, 1, MSG_ERROR,
|
||||
"This folder can not be deleted! Please, make sure that it is empty.")
|
||||
end
|
||||
end
|
||||
|
||||
function FileChooser:deleteFileAtPosition(pos)
|
||||
local fullpath = self.path.."/"..self.files[pos-#self.dirs]
|
||||
os.remove(fullpath) -- delete the file itself
|
||||
os.remove(DocToHistory(fullpath)) -- and its history file, if any
|
||||
table.remove(self.files, pos-#self.dirs) -- to avoid showing just deleted file
|
||||
self.items = self.items - 1
|
||||
self.current, self.page = gotoTargetItem(pos, self.items, pos, self.page, self.perpage)
|
||||
end
|
||||
|
||||
-- NuPogodi, 01.10.12: jump to defined item in the itemlist
|
||||
function gotoTargetItem(target_item, all_items, current_item, current_page, perpage)
|
||||
target_item = math.max(math.min(target_item, all_items), 1)
|
||||
local target_page = math.ceil(target_item/perpage)
|
||||
local target_curr = (target_item -1) % perpage + 1
|
||||
local pagedirty, markerdirty = false, false
|
||||
if target_page ~= current_page then
|
||||
current_page = target_page
|
||||
pagedirty = true
|
||||
markerdirty = true
|
||||
elseif target_curr ~= current_item then
|
||||
markerdirty = true
|
||||
end
|
||||
return target_curr, current_page, markerdirty, pagedirty
|
||||
end
|
||||
|
||||
function warningUnsupportedFunction()
|
||||
InfoMessage:inform("Unsupported function! ", 2000, 1, MSG_WARN,
|
||||
"The requested function is not supported.")
|
||||
end
|
||||
|
202
filehistory.lua
202
filehistory.lua
@ -6,16 +6,13 @@ require "inputbox"
|
||||
require "dialog"
|
||||
require "filesearcher"
|
||||
require "settings"
|
||||
require "dialog"
|
||||
|
||||
FileHistory = {
|
||||
-- title height
|
||||
title_H = 40,
|
||||
-- spacing between lines
|
||||
spacing = 36,
|
||||
-- foot height
|
||||
foot_H = 28,
|
||||
-- horisontal margin
|
||||
margin_H = 10,
|
||||
title_H = 40, -- title height
|
||||
spacing = 36, -- spacing between lines
|
||||
foot_H = 28, -- foot height
|
||||
margin_H = 10, -- horisontal margin
|
||||
|
||||
-- state buffer
|
||||
history_files = {},
|
||||
@ -25,6 +22,7 @@ FileHistory = {
|
||||
page = 0,
|
||||
current = 1,
|
||||
oldcurrent = 1,
|
||||
commands = nil,
|
||||
}
|
||||
|
||||
function FileHistory:init(history_path)
|
||||
@ -33,14 +31,16 @@ function FileHistory:init(history_path)
|
||||
else
|
||||
self:setPath("./history")
|
||||
end
|
||||
self:addAllCommands()
|
||||
|
||||
-- to initialize only once
|
||||
if not self.commands then self:addAllCommands() end
|
||||
end
|
||||
|
||||
function FileHistory:setPath(newPath)
|
||||
self.path = newPath
|
||||
self:readDir("-c ")
|
||||
self.items = #self.files
|
||||
if self.items == 0 then
|
||||
if self.items == 1 then
|
||||
return nil
|
||||
end
|
||||
self.page = 1
|
||||
@ -49,24 +49,22 @@ function FileHistory:setPath(newPath)
|
||||
end
|
||||
|
||||
function FileHistory:readDir(order_criteria)
|
||||
self.history_files = {}
|
||||
self.files = {}
|
||||
self.history_files = { {dir=self.path, name=".."} }
|
||||
self.files = { {dir=self.path, name=".."} }
|
||||
local p = io.popen("ls "..order_criteria.."-1 "..self.path)
|
||||
for f in p:lines() do
|
||||
-- insert history files
|
||||
file_entry = {dir=self.path, name=f}
|
||||
table.insert(self.history_files, file_entry)
|
||||
table.insert(self.history_files, {dir=self.path, name=f})
|
||||
-- and corresponding path & file items
|
||||
file_entry = {dir=HistoryToPath(f), name=HistoryToName(f)}
|
||||
table.insert(self.files, file_entry)
|
||||
table.insert(self.files, {dir=HistoryToPath(f), name=HistoryToName(f)})
|
||||
end
|
||||
p:close()
|
||||
end
|
||||
|
||||
function FileHistory:setSearchResult(keywords)
|
||||
self.result = {}
|
||||
self.result = { {dir=self.path, name=".."} }
|
||||
if keywords == "" or keywords == " " then
|
||||
-- show all history
|
||||
-- show all history
|
||||
self.result = self.files
|
||||
else
|
||||
-- select history files with keywords in the filename
|
||||
@ -80,6 +78,7 @@ function FileHistory:setSearchResult(keywords)
|
||||
self.items = #self.result
|
||||
self.page = 1
|
||||
self.current = 1
|
||||
return self.items
|
||||
end
|
||||
|
||||
function FileHistory:prevItem()
|
||||
@ -113,28 +112,6 @@ end
|
||||
|
||||
function FileHistory:addAllCommands()
|
||||
self.commands = Commands:new{}
|
||||
-- search among last documents
|
||||
self.commands:add(KEY_S, nil, "S",
|
||||
"search among files",
|
||||
function(self)
|
||||
old_keywords = self.keywords
|
||||
self.keywords = InputBox:input(G_height - 100, 100,
|
||||
"Search:", old_keywords)
|
||||
if self.keywords then
|
||||
self:setSearchResult(self.keywords)
|
||||
else
|
||||
self.keywords = old_keywords
|
||||
end
|
||||
self.pagedirty = true
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_L, nil, "L",
|
||||
"last documents",
|
||||
function(self)
|
||||
self:setSearchResult("")
|
||||
self.pagedirty = true
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_H, nil, "H",
|
||||
"show help page",
|
||||
function(self)
|
||||
@ -142,26 +119,29 @@ function FileHistory:addAllCommands()
|
||||
self.pagedirty = true
|
||||
end
|
||||
)
|
||||
self.commands:add({KEY_FW_RIGHT, KEY_I}, nil, "joypad right",
|
||||
"document details",
|
||||
function(self)
|
||||
file_entry = self.result[self.perpage*(self.page-1)+self.current]
|
||||
FileInfo:show(file_entry.dir,file_entry.name)
|
||||
self.pagedirty = true
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_FW_UP, nil, "joypad up",
|
||||
"goto previous item",
|
||||
"previous item",
|
||||
function(self)
|
||||
self:prevItem()
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_FW_DOWN, nil, "joypad down",
|
||||
"goto next item",
|
||||
"next item",
|
||||
function(self)
|
||||
self:nextItem()
|
||||
end
|
||||
)
|
||||
-- NuPogodi, 01.10.12: fast jumps to items at positions 10, 20, .. 90, 0% within the list
|
||||
local numeric_keydefs, i = {}
|
||||
for i=1, 10 do numeric_keydefs[i]=Keydef:new(KEY_1+i-1, nil, tostring(i%10)) end
|
||||
self.commands:addGroup("[1, 2 .. 9, 0]", numeric_keydefs,
|
||||
"item at position 0%, 10% .. 90%, 100%",
|
||||
function(self)
|
||||
local target_item = math.ceil(self.items * (keydef.keycode-KEY_1) / 9)
|
||||
self.current, self.page, self.markerdirty, self.pagedirty =
|
||||
gotoTargetItem(target_item, self.items, self.current, self.page, self.perpage)
|
||||
end
|
||||
)
|
||||
self.commands:add({KEY_PGFWD, KEY_LPGFWD}, nil, ">",
|
||||
"next page",
|
||||
function(self)
|
||||
@ -189,7 +169,58 @@ function FileHistory:addAllCommands()
|
||||
end
|
||||
end
|
||||
)
|
||||
self.commands:add({KEY_F, KEY_AA}, nil, "F",
|
||||
self.commands:add(KEY_G, nil, "G", -- NuPogodi, 01.10.12: goto page No.
|
||||
"goto page",
|
||||
function(self)
|
||||
local n = math.ceil(self.items / self.perpage)
|
||||
local page = NumInputBox:input(G_height-100, 100, "Page:", "current page "..self.page.." of "..n, true)
|
||||
if pcall(function () page = math.floor(page) end) -- convert string to number
|
||||
and page ~= self.page and page > 0 and page <= n then
|
||||
self.page = page
|
||||
if self.current + (page-1)*self.perpage > self.items then
|
||||
self.current = self.items - (page-1)*self.perpage
|
||||
end
|
||||
end
|
||||
self.pagedirty = true
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_FW_RIGHT, nil, "joypad right",
|
||||
"document details",
|
||||
function(self)
|
||||
local file_entry = self.result[self.perpage*(self.page-1)+self.current]
|
||||
if file_entry.name == ".." then
|
||||
warningUnsupportedFunction()
|
||||
return
|
||||
end -- do not show details
|
||||
FileInfo:show(file_entry.dir,file_entry.name)
|
||||
self.pagedirty = true
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_S, nil, "S",
|
||||
"invoke search inputbox",
|
||||
function(self)
|
||||
-- NuPogodi, 30.09.12: be sure that something is found
|
||||
local old_keywords = self.keywords
|
||||
local old_data = self.result
|
||||
local old_page, old_current = self.page, self.current
|
||||
self.keywords = InputBox:input(G_height - 100, 100, "Search:", old_keywords)
|
||||
if self.keywords then
|
||||
self:setSearchResult(self.keywords)
|
||||
end
|
||||
if #self.result < 2 then
|
||||
InfoMessage:inform("No hits! Try another keyword. ", 2000, 1, MSG_WARN,
|
||||
"The search has given no results! Please, try another keyword.")
|
||||
-- restoring the original data
|
||||
self.result = old_data
|
||||
self.items = #self.result
|
||||
self.keywords = old_keywords
|
||||
self.page = old_page
|
||||
self.current = old_current
|
||||
end
|
||||
self.pagedirty = true
|
||||
end
|
||||
)
|
||||
self.commands:add({KEY_F, KEY_AA}, nil, "F, Aa",
|
||||
"change font faces",
|
||||
function(self)
|
||||
Font:chooseFonts()
|
||||
@ -197,35 +228,42 @@ function FileHistory:addAllCommands()
|
||||
end
|
||||
)
|
||||
self.commands:add({KEY_ENTER, KEY_FW_PRESS}, nil, "Enter",
|
||||
"open selected item",
|
||||
"open selected document",
|
||||
function(self)
|
||||
if #self.result == 0 then
|
||||
showInfoMsgWithDelay("No files to open", 1500, 1)
|
||||
return
|
||||
end
|
||||
file_entry = self.result[self.perpage*(self.page-1)+self.current]
|
||||
local file_entry = self.result[self.perpage*(self.page-1)+self.current]
|
||||
if file_entry.name == ".." then return "break" end -- quit
|
||||
file_full_path = file_entry.dir .. "/" .. file_entry.name
|
||||
|
||||
openFile(file_full_path)
|
||||
--reset height and item index if screen has been rotated
|
||||
local item_no = self.perpage * (self.page - 1) + self.current
|
||||
self.perpage = math.floor(G_height / self.spacing) - 2
|
||||
self.current = item_no % self.perpage
|
||||
self.page = math.floor(item_no / self.perpage) + 1
|
||||
|
||||
self.pagedirty = true
|
||||
end
|
||||
)
|
||||
self.commands:add({KEY_DEL}, nil, "Del",
|
||||
"delete history entry",
|
||||
function(self)
|
||||
file_entry = self.result[self.perpage*(self.page-1)+self.current]
|
||||
if not file_entry then return end
|
||||
local file_entry = self.result[self.perpage*(self.page-1)+self.current]
|
||||
if file_entry.name == ".." then
|
||||
warningUnsupportedFunction()
|
||||
return
|
||||
end -- do not delete
|
||||
local file_to_del = file_entry.dir .. "/" .. file_entry.name
|
||||
os.remove(DocToHistory(file_to_del))
|
||||
-- to avoid showing just deleted file
|
||||
self:init()
|
||||
self:setSearchResult(self.keywords)
|
||||
if InfoMessage.InfoMethod[MSG_CONFIRM] == 0 then -- silent regime
|
||||
os.remove(DocToHistory(file_to_del))
|
||||
self:init()
|
||||
self:setSearchResult(self.keywords)
|
||||
else
|
||||
InfoMessage:inform("Press 'Y' to confirm ", nil, 0, MSG_CONFIRM,
|
||||
"Please, press key Y to delete the book history")
|
||||
if FileChooser:ReturnKey() == KEY_Y then
|
||||
os.remove(DocToHistory(file_to_del))
|
||||
self:init()
|
||||
self:setSearchResult(self.keywords)
|
||||
end
|
||||
end
|
||||
self.pagedirty = true
|
||||
end
|
||||
)
|
||||
@ -235,7 +273,7 @@ function FileHistory:addAllCommands()
|
||||
self.pagedirty = true
|
||||
end
|
||||
)
|
||||
self.commands:add({KEY_BACK, KEY_HOME}, nil, "Back",
|
||||
self.commands:add({KEY_BACK, KEY_HOME}, nil, "Back, '..', Home",
|
||||
"back",
|
||||
function(self)
|
||||
return "break"
|
||||
@ -248,7 +286,11 @@ function FileHistory:choose(keywords)
|
||||
self.pagedirty = true
|
||||
self.markerdirty = false
|
||||
|
||||
self:setSearchResult(keywords)
|
||||
-- NuPogodi, 30.09.12: immediate quit (no redraw), if empty
|
||||
if self:setSearchResult(keywords) < 2 then -- only ".."
|
||||
InfoMessage:inform("No reading history! ", 2000, 1, MSG_WARN, "The reading history is empty!")
|
||||
return nil
|
||||
end
|
||||
|
||||
while true do
|
||||
local cface = Font:getFace("cfont", 22)
|
||||
@ -258,37 +300,25 @@ function FileHistory:choose(keywords)
|
||||
if self.pagedirty then
|
||||
self.markerdirty = true
|
||||
fb.bb:paintRect(0, 0, G_width, G_height, 0)
|
||||
|
||||
-- draw header
|
||||
local header = "Last Documents"
|
||||
if self.keywords ~= "" and self.keywords ~= " " then
|
||||
--header = header .. " (filter: \'" .. string.upper(self.keywords) .. "\')"
|
||||
header = "Search Results for \'"..string.upper(self.keywords).."\'"
|
||||
end
|
||||
DrawTitle(header,self.margin_H,0,self.title_H,4,tface)
|
||||
|
||||
DrawTitle(header,self.margin_H,0,self.title_H,3,tface)
|
||||
-- draw found results
|
||||
local c
|
||||
if self.items == 0 then -- nothing found
|
||||
y = self.title_H + self.spacing * 2
|
||||
renderUtf8Text(fb.bb, self.margin_H, y, cface,
|
||||
"Sorry, no files found.", true)
|
||||
self.markerdirty = false
|
||||
else -- found something, draw it
|
||||
for c = 1, self.perpage do
|
||||
local i = (self.page - 1) * self.perpage + c
|
||||
if i <= self.items then
|
||||
y = self.title_H + (self.spacing * c) + 4
|
||||
local ftype = string.lower(string.match(self.result[i].name, ".+%.([^.]+)") or "")
|
||||
DrawFileItem(self.result[i].name,self.margin_H,y,ftype)
|
||||
end
|
||||
for c = 1, self.perpage do
|
||||
local i = (self.page - 1) * self.perpage + c
|
||||
if i <= self.items then
|
||||
y = self.title_H + (self.spacing * c) + 4
|
||||
local ftype = string.lower(string.match(self.result[i].name, ".+%.([^.]+)") or "")
|
||||
DrawFileItem(self.result[i].name,self.margin_H,y,ftype)
|
||||
end
|
||||
end
|
||||
|
||||
-- draw footer
|
||||
all_page = math.ceil(self.items/self.perpage)
|
||||
DrawFooter("Page "..self.page.." of "..all_page,fface,self.foot_H)
|
||||
|
||||
end
|
||||
|
||||
if self.markerdirty then
|
||||
|
2
font.lua
2
font.lua
@ -9,8 +9,6 @@ Font = {
|
||||
hpkfont = "droid/DroidSansMono.ttf", -- help page: font for displaying keys
|
||||
hfont = "droid/DroidSans.ttf", -- help page: font for displaying help messages
|
||||
infont = "droid/DroidSansMono.ttf", -- inputbox: use mono for better distance controlling
|
||||
-- pgfont = "droid/DroidSans.ttf", -- was in use in heppage to render footer
|
||||
-- to be repalced by ffont
|
||||
},
|
||||
fontdir = os.getenv("FONTDIR") or "./fonts",
|
||||
-- face table
|
||||
|
32
inputbox.lua
32
inputbox.lua
@ -3,6 +3,9 @@ require "rendertext"
|
||||
require "keys"
|
||||
require "graphics"
|
||||
|
||||
MODE_CALC = 1
|
||||
MODE_TERM = 2
|
||||
|
||||
----------------------------------------------------
|
||||
-- General inputbox
|
||||
----------------------------------------------------
|
||||
@ -37,7 +40,7 @@ InputBox = {
|
||||
shiftmode = true, -- toggle chars <-> capitals, lowest bit in (layout-2)
|
||||
symbolmode = false, -- toggle chars <-> symbols, middle bit in (layout-2)
|
||||
utf8mode = false, -- toggle english <-> national, highest bit in (layout-2)
|
||||
calcmode = false, -- toggle calculator mode
|
||||
inputmode, -- define mode: input <> calculator <> terminal
|
||||
calcfunctions = nil, -- math functions for calculator helppage
|
||||
}
|
||||
|
||||
@ -128,7 +131,7 @@ function InputBox:input(ypos, height, title, d_text, is_hint)
|
||||
-- my own position, at the bottom screen edge
|
||||
ypos = fb.bb:getHeight() - 165
|
||||
-- some corrections for calculator mode
|
||||
if self.calcmode then
|
||||
if self.inputmode == MODE_CALC then
|
||||
self:setCalcMode()
|
||||
end
|
||||
|
||||
@ -366,7 +369,7 @@ function InputBox:CharlistToString()
|
||||
end
|
||||
|
||||
function InputBox:addAllCommands()
|
||||
-- if already initialized, we (re)define only calcmode-dependent commands
|
||||
-- if already initialized, we (re)define only inputmode-dependent commands
|
||||
if self.commands then
|
||||
self:ModeDependentCommands()
|
||||
self:DrawVirtualKeyboard()
|
||||
@ -378,7 +381,7 @@ function InputBox:addAllCommands()
|
||||
self:addCharCommands(self.layout)
|
||||
-- adding the rest commands (independent of the selected layout)
|
||||
self.commands:add(KEY_H, MOD_ALT, "H",
|
||||
"show helppage",
|
||||
"show help page",
|
||||
function(self)
|
||||
self:showHelpPage(self.commands)
|
||||
end
|
||||
@ -436,7 +439,7 @@ function InputBox:addAllCommands()
|
||||
end
|
||||
)
|
||||
self.commands:addGroup("up/down", { Keydef:new(KEY_FW_DOWN, nil), Keydef:new(KEY_FW_UP, nil) },
|
||||
"goto previous/next VK-layout",
|
||||
"previous/next VK-layout",
|
||||
function(self)
|
||||
if keydef.keycode == KEY_FW_DOWN then
|
||||
if self.layout == self.max_layout then self:addCharCommands(self.min_layout)
|
||||
@ -469,10 +472,10 @@ function InputBox:addAllCommands()
|
||||
self:addCharCommands()
|
||||
end
|
||||
)
|
||||
-- NuPogodi, 02.06.12: calcmode-dependent commands are collected
|
||||
-- NuPogodi, 02.06.12: inputmode-dependent commands are collected
|
||||
self:ModeDependentCommands() -- here
|
||||
|
||||
self.commands:add({KEY_BACK, KEY_HOME}, nil, "Back",
|
||||
self.commands:add({KEY_BACK, KEY_HOME}, nil, "Back, Home",
|
||||
"back",
|
||||
function(self)
|
||||
self.input_string = nil
|
||||
@ -552,9 +555,8 @@ function InputBox:showHelpPage(list, title)
|
||||
self.cursor:clear() -- hide cursor
|
||||
fb.bb:dimRect(self.input_start_x-5, self.input_start_y-19, self.input_slot_w, self.fheight, self.input_bg)
|
||||
fb:refresh(1, self.input_start_x-5, self.ypos, self.input_slot_w, self.h)
|
||||
-- now start the helppage with own list of commands and own title
|
||||
HelpPage:show(0, fb.bb:getHeight()-165, list, title)
|
||||
-- on the helppage-exit, making inactive helpage
|
||||
-- on the help page-exit, making inactive helpage
|
||||
fb.bb:dimRect(0, 40, fb.bb:getWidth(), fb.bb:getHeight()-205, self.input_bg)
|
||||
-- and active input slot
|
||||
self:refreshText()
|
||||
@ -595,13 +597,13 @@ end
|
||||
|
||||
-- define whether we need to calculate the result or to return 'self.input_string'
|
||||
function InputBox:ModeDependentCommands()
|
||||
if self.calcmode then
|
||||
if self.inputmode == MODE_CALC then
|
||||
-- define what to do with the input_string
|
||||
self.commands:add({KEY_FW_PRESS, KEY_ENTER}, nil, "joypad center",
|
||||
self.commands:add({KEY_FW_PRESS, KEY_ENTER}, nil, "Enter",
|
||||
"calculate the result",
|
||||
function(self)
|
||||
if #self.input_string == 0 then
|
||||
showInfoMsgWithDelay("No input ", 1000, 1)
|
||||
InfoMessage:inform("No input! ", 1000, 1, MSG_WARN, "There is nothing to calculate")
|
||||
else
|
||||
local s = self:PrepareStringToCalc()
|
||||
if pcall(function () f = assert(loadstring("r = tostring("..s..")")) end) and pcall(f) then
|
||||
@ -618,7 +620,7 @@ function InputBox:ModeDependentCommands()
|
||||
self.cursor:draw()
|
||||
fb:refresh(1, self.input_start_x-5, self.input_start_y-25, self.input_slot_w, self.h-25)
|
||||
else
|
||||
showInfoMsgWithDelay("Invalid input ", 1000, 1)
|
||||
InfoMessage:inform("Invalid input! ", 1000, 1, MSG_WARN)
|
||||
end -- if pcall
|
||||
end
|
||||
end -- function
|
||||
@ -633,7 +635,7 @@ function InputBox:ModeDependentCommands()
|
||||
end
|
||||
)
|
||||
else -- return input_string & close input box
|
||||
self.commands:add({KEY_FW_PRESS, KEY_ENTER}, nil, "joypad center",
|
||||
self.commands:add({KEY_FW_PRESS, KEY_ENTER}, nil, "Enter",
|
||||
"submit input content",
|
||||
function(self)
|
||||
if self.input_string == "" then
|
||||
@ -644,7 +646,7 @@ function InputBox:ModeDependentCommands()
|
||||
)
|
||||
-- delete calculator-specific help
|
||||
self.commands:del(KEY_M, MOD_ALT, "M")
|
||||
end -- if self.calcmode
|
||||
end -- if self.inputmode
|
||||
end
|
||||
|
||||
----------------------------------------------------
|
||||
|
@ -1,3 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
/mnt/us/launchpad/kpdf.sh
|
||||
/mnt/us/kindlepdfviewer/kpdf.sh
|
||||
|
@ -1,3 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
/mnt/us/launchpad/kpdf.sh /mnt/us/documents
|
||||
/mnt/us/kindlepdfviewer/kpdf.sh /mnt/us/documents
|
||||
|
37
kpdf.sh
Normal file
37
kpdf.sh
Normal file
@ -0,0 +1,37 @@
|
||||
#!/bin/sh
|
||||
export LC_ALL="en_US.UTF-8"
|
||||
|
||||
echo unlock > /proc/keypad
|
||||
echo unlock > /proc/fiveway
|
||||
|
||||
# we're always starting from our working directory
|
||||
cd /mnt/us/kindlepdfviewer/
|
||||
|
||||
# bind-mount system fonts
|
||||
if ! grep /mnt/us/kindlepdfviewer/fonts/host /proc/mounts; then
|
||||
mount -o bind /usr/java/lib/fonts /mnt/us/kindlepdfviewer/fonts/host
|
||||
fi
|
||||
|
||||
# check if we are supposed to shut down the Amazon framework
|
||||
if test "$1" == "--framework_stop"; then
|
||||
shift 1
|
||||
/etc/init.d/framework stop
|
||||
fi
|
||||
|
||||
# stop cvm
|
||||
killall -stop cvm
|
||||
|
||||
# finally call reader
|
||||
./reader.lua "$1" 2> /mnt/us/kindlepdfviewer/crash.log || cat /mnt/us/kindlepdfviewer/crash.log
|
||||
|
||||
# unmount system fonts
|
||||
if grep /mnt/us/kindlepdfviewer/fonts/host /proc/mounts; then
|
||||
umount /mnt/us/kindlepdfviewer/fonts/host
|
||||
fi
|
||||
|
||||
# always try to continue cvm
|
||||
killall -cont cvm || /etc/init.d/framework start
|
||||
|
||||
# cleanup hanging process
|
||||
killall lipc-wait-event
|
||||
|
@ -1,11 +1,11 @@
|
||||
[Actions]
|
||||
# start kindlepdfviewer with filebrowser in /mnt/us/documents
|
||||
P D = !/mnt/us/launchpad/kpdf.sh /mnt/us/documents
|
||||
P D = !/mnt/us/kindlepdfviewer/kpdf.sh /mnt/us/documents
|
||||
# start kindlepdfviewer with last document
|
||||
P P = !/mnt/us/launchpad/kpdf.sh
|
||||
P P = !/mnt/us/kindlepdfviewer/kpdf.sh
|
||||
# start kindlepdfviewer without framework in /mnt/us/documents
|
||||
P K = !/mnt/us/launchpad/kpdf.sh --framework_stop /mnt/us/documents
|
||||
P K = !/mnt/us/kindlepdfviewer/kpdf.sh --framework_stop /mnt/us/documents
|
||||
# start kindlepdfviewer without framework on last read document
|
||||
P L = !/mnt/us/launchpad/kpdf.sh --framework_stop
|
||||
P L = !/mnt/us/kindlepdfviewer/kpdf.sh --framework_stop
|
||||
# restart amazon framework - when it got irritated
|
||||
P R = !/etc/init.d/framework restart
|
||||
|
@ -42,7 +42,7 @@ function openFile(filename)
|
||||
|
||||
reader = ext:getReader(file_type)
|
||||
if reader then
|
||||
InfoMessage:show("Opening document... ", 0)
|
||||
InfoMessage:inform("Opening document... ", nil, 0, MSG_AUX)
|
||||
reader:preLoadSettings(filename)
|
||||
local ok, err = reader:open(filename)
|
||||
if ok then
|
||||
@ -54,9 +54,9 @@ function openFile(filename)
|
||||
else
|
||||
if err then
|
||||
Debug("openFile(): "..err)
|
||||
showInfoMsgWithDelay(err:sub(1,30), 2000, 1)
|
||||
InfoMessage:inform(err:sub(1,30), 2000, 1, MSG_ERROR)
|
||||
else
|
||||
showInfoMsgWithDelay("Error opening document ", 2000, 1)
|
||||
InfoMessage:inform("Error opening document! ", 2000, 1, MSG_ERROR)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -140,6 +140,8 @@ end
|
||||
|
||||
-- set up the mode to manage files
|
||||
FileChooser.filemanager_expert_mode = G_reader_settings:readSetting("filemanager_expert_mode") or 1
|
||||
InfoMessage:initInfoMessageSettings()
|
||||
|
||||
-- initialize global settings shared among all readers
|
||||
UniReader:initGlobalSettings(G_reader_settings)
|
||||
-- initialize specific readers
|
||||
@ -171,6 +173,7 @@ end
|
||||
|
||||
-- save reader settings
|
||||
G_reader_settings:saveSetting("fontmap", Font.fontmap)
|
||||
InfoMessage:saveInfoMessageSettings()
|
||||
G_reader_settings:close()
|
||||
|
||||
-- @TODO dirty workaround, find a way to force native system poll
|
||||
|
BIN
resources/info-aux.png
Normal file
BIN
resources/info-aux.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
BIN
resources/info-bug.png
Normal file
BIN
resources/info-bug.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
BIN
resources/info-confirm.png
Normal file
BIN
resources/info-confirm.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 858 B |
BIN
resources/info-error.png
Normal file
BIN
resources/info-error.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 950 B |
Binary file not shown.
Before Width: | Height: | Size: 538 B |
BIN
resources/info-warn.png
Normal file
BIN
resources/info-warn.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 844 B |
@ -38,7 +38,6 @@ Codes for rotation modes:
|
||||
0
|
||||
--]]
|
||||
|
||||
|
||||
Screen = {
|
||||
cur_rotation_mode = 0,
|
||||
-- these two variabls are used to help switching from framework to reader
|
||||
@ -118,7 +117,8 @@ function Screen:screenshot()
|
||||
local diff = nsecs - secs + (nusecs - usecs)/1000000
|
||||
--self:fb2bmp("/dev/fb0", lfs.currentdir().."/screenshots/"..os.date("%Y%m%d%H%M%S")..".bmp", true, "bzip2 ")
|
||||
--self:fb2pgm("/dev/fb0", lfs.currentdir().."/screenshots/"..os.date("%Y%m%d%H%M%S")..".pgm", "bzip2 ", 4)
|
||||
showInfoMsgWithDelay(string.format("Screenshot is ready in %.2fs ", diff), 2000, 1)
|
||||
local msg = "Screenshot is ready in "
|
||||
InfoMessage:inform(msg..string.format("%.2fs ", diff), 2000, 1, MSG_WARN, msg..math.ceil(diff*1000).." milliseconds")
|
||||
end
|
||||
|
||||
-- NuPogodi (02.07.2012): added the functions to save the fb-content in common graphic files - bmp & pgm.
|
||||
|
@ -5,22 +5,14 @@ require "font"
|
||||
require "commands"
|
||||
|
||||
SelectMenu = {
|
||||
-- font for displaying item names
|
||||
fsize = 22,
|
||||
-- font for page title
|
||||
tfsize = 25,
|
||||
-- font for paging display
|
||||
ffsize = 16,
|
||||
-- font for item shortcut
|
||||
fsize = 22, -- font for displaying item names
|
||||
tfsize = 25, -- font for page title
|
||||
ffsize = 16,-- font for paging display
|
||||
|
||||
-- title height
|
||||
title_H = 40,
|
||||
-- spacing between lines
|
||||
spacing = 36,
|
||||
-- foot height
|
||||
foot_H = 27,
|
||||
-- horisontal margin
|
||||
margin_H = 10,
|
||||
title_H = 40, -- title height
|
||||
spacing = 36, -- spacing between lines
|
||||
foot_H = 27, -- foot height
|
||||
margin_H = 10, -- horisontal margin
|
||||
current_entry = 0,
|
||||
|
||||
menu_title = "No Title",
|
||||
@ -114,7 +106,7 @@ function SelectMenu:addAllCommands()
|
||||
end
|
||||
end
|
||||
)
|
||||
self.commands:add({KEY_PGFWD, KEY_LPGFWD}, nil, "next",
|
||||
self.commands:add({KEY_PGFWD, KEY_LPGFWD}, nil, ">",
|
||||
"next page",
|
||||
function(sm)
|
||||
if sm.page < (sm.items / sm.perpage) then
|
||||
@ -129,7 +121,7 @@ function SelectMenu:addAllCommands()
|
||||
end
|
||||
end
|
||||
)
|
||||
self.commands:add({KEY_PGBCK, KEY_LPGBCK}, nil, "prev",
|
||||
self.commands:add({KEY_PGBCK, KEY_LPGBCK}, nil, "<",
|
||||
"previous page",
|
||||
function(sm)
|
||||
if sm.page > 1 then
|
||||
@ -188,7 +180,7 @@ function SelectMenu:addAllCommands()
|
||||
table.insert(KEY_Q_to_P, Keydef:new(i, nil, ""))
|
||||
end
|
||||
self.commands:addGroup("Q to P", KEY_Q_to_P,
|
||||
"Select item with Q to P key as shortcut",
|
||||
"select item with Q to P key as shortcut",
|
||||
function(sm, keydef)
|
||||
sm.selected_item = sm:getItemIndexByShortCut(
|
||||
sm.item_shortcuts[ keydef.keycode - KEY_Q + 1 ], sm.perpage)
|
||||
@ -199,7 +191,7 @@ function SelectMenu:addAllCommands()
|
||||
table.insert(KEY_A_to_L, Keydef:new(i, nil, ""))
|
||||
end
|
||||
self.commands:addGroup("A to L", KEY_A_to_L,
|
||||
"Select item with A to L key as shortcut",
|
||||
"select item with A to L key as shortcut",
|
||||
function(sm, keydef)
|
||||
sm.selected_item = sm:getItemIndexByShortCut(
|
||||
sm.item_shortcuts[ keydef.keycode - KEY_A + 11 ], sm.perpage)
|
||||
@ -210,55 +202,55 @@ function SelectMenu:addAllCommands()
|
||||
table.insert(KEY_Z_to_M, Keydef:new(i, nil, ""))
|
||||
end
|
||||
self.commands:addGroup("Z to M", KEY_Z_to_M,
|
||||
"Select item with Z to M key as shortcut",
|
||||
"select item with Z to M key as shortcut",
|
||||
function(sm, keydef)
|
||||
sm.selected_item = sm:getItemIndexByShortCut(
|
||||
sm.item_shortcuts[ keydef.keycode - KEY_Z + 21 ], sm.perpage)
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_SLASH, nil, "/",
|
||||
"Select item with / key as shortcut",
|
||||
"select item with / key as shortcut",
|
||||
function(sm)
|
||||
sm.selected_item = sm:getItemIndexByShortCut("/", sm.perpage)
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_DOT, nil, ".",
|
||||
"Select item with dot key as shortcut",
|
||||
"select item with dot key as shortcut",
|
||||
function(sm)
|
||||
sm.selected_item = sm:getItemIndexByShortCut(".", sm.perpage)
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_SYM, nil, "Sym",
|
||||
"Select item with Sym key as shortcut",
|
||||
"select item with Sym key as shortcut",
|
||||
function(sm)
|
||||
sm.selected_item = sm:getItemIndexByShortCut("Sym", sm.perpage)
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_ENTER, nil, "Enter",
|
||||
"Select item with Enter key as shortcut",
|
||||
"select item with Enter key as shortcut",
|
||||
function(sm)
|
||||
sm.selected_item = sm:getItemIndexByShortCut("Ent", sm.perpage)
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_BACK, nil, "Back",
|
||||
"Exit menu",
|
||||
function(sm)
|
||||
return "break"
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_H,MOD_ALT,"H",
|
||||
"show help page",
|
||||
function(sm)
|
||||
HelpPage:show(0, G_height, sm.commands)
|
||||
sm.pagedirty = true
|
||||
end)
|
||||
self.commands:add({KEY_BACK,KEY_HOME}, nil, "Back, Home",
|
||||
"exit menu",
|
||||
function(sm)
|
||||
return "break"
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
function SelectMenu:clearCommands()
|
||||
self.commands = Commands:new{}
|
||||
|
||||
self.commands:add(KEY_BACK, nil, "",
|
||||
"Exit menu",
|
||||
self.commands:add({KEY_BACK,KEY_HOME}, nil, "Back, Home",
|
||||
"exit menu",
|
||||
function(sm)
|
||||
return "break"
|
||||
end)
|
||||
@ -352,7 +344,7 @@ function SelectMenu:choose(ypos, height)
|
||||
end -- for c=1, self.perpage
|
||||
end -- if self.items == 0
|
||||
|
||||
local footer = "Page "..self.page.." of "..(math.ceil(self.items / self.perpage)).." Press Alt-H for help"
|
||||
local footer = "Page "..self.page.." of "..(math.ceil(self.items / self.perpage)).." - Press Alt-H for help"
|
||||
renderUtf8Text(fb.bb, self.margin_H, height-7, fface, footer, true)
|
||||
end
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user