Merge branch 'searcher'

pull/2/merge
Qingping Hou 12 years ago
commit 29a3b123c1

@ -2,6 +2,8 @@ require "rendertext"
require "keys"
require "graphics"
require "fontchooser"
require "filesearcher"
require "inputbox"
FileChooser = {
-- Class vars:
@ -35,6 +37,7 @@ function FileChooser:readdir()
table.insert(self.files, f)
end
end
--@TODO make sure .. is sortted to the first item 16.02 2012
table.sort(self.dirs)
table.sort(self.files)
end
@ -151,6 +154,7 @@ function FileChooser:choose(ypos, height)
end
local ev = input.waitForEvent()
if ev.type == EV_KEY and ev.value == EVENT_VALUE_KEY_PRESS then
print("key code:"..ev.code)
if ev.code == KEY_FW_UP then
if self:rotationMode() == 0 then
prevItem()
@ -183,6 +187,24 @@ function FileChooser:choose(ypos, height)
clearglyphcache()
end
pagedirty = true
elseif ev.code == KEY_S then
-- invoke search input
keywords = InputBox:input(height-100, 100, "Search:")
if keywords then -- display search result according to keywords
--[[
----------------------------------------------------------------
|| uncomment following line and set the correct path if you want
|| to test search feature in EMU mode
----------------------------------------------------------------
--]]
--FileSearcher:init("/home/dave/documents/kindle/backup/documents")
FileSearcher:init()
file = FileSearcher:choose(ypos, height, keywords)
if file then
return file
end
end
pagedirty = true
elseif ev.code == KEY_PGFWD then
if self.page < (self.items / perpage) then
if self.current + self.page*perpage > self.items then

@ -0,0 +1,232 @@
require "rendertext"
require "keys"
require "graphics"
FileSearcher = {
-- font for displaying file/dir names
face = freetype.newBuiltinFace("sans", 25),
fhash = "s25",
-- font for page title
tface = freetype.newBuiltinFace("Helvetica-BoldOblique", 32),
tfhash = "hbo32",
-- font for paging display
sface = freetype.newBuiltinFace("sans", 16),
sfhash = "s16",
-- title height
title_H = 45,
-- spacing between lines
spacing = 40,
-- foot height
foot_H = 27,
-- state buffer
dirs = {},
files = {},
result = {},
items = 0,
page = 0,
current = 1,
oldcurrent = 1,
}
function FileSearcher:readdir()
self.dirs = {self.path}
self.files = {}
while #self.dirs ~= 0 do
new_dirs = {}
-- handle each dir
for __, d in pairs(self.dirs) do
-- handle files in d
for f in lfs.dir(d) do
if lfs.attributes(self.path.."/"..f, "mode") == "directory"
and f ~= "." and f~= ".." and not string.match(f, "^%.[^.]") then
table.insert(new_dirs, d.."/"..f)
elseif string.match(f, ".+%.[pP][dD][fF]$") then
file_entry = {dir=d, name=f,}
table.insert(self.files, file_entry)
--print("file:"..d.."/"..f)
end
end
end
self.dirs = new_dirs
end
end
function FileSearcher:setPath(newPath)
self.path = newPath
self:readdir()
self.items = #self.files
--@TODO check none found 19.02 2012
if self.items == 0 then
return nil
end
self.page = 1
self.current = 1
return true
end
function FileSearcher:setSearchResult(keywords)
self.result = {}
if keywords == " " then -- one space to show all files
self.result = self.files
else
for __,f in pairs(self.files) do
if string.find(string.lower(f.name), keywords) then
table.insert(self.result, f)
end
end
end
self.items = #self.result
self.page = 1
self.current = 1
end
function FileSearcher:init(search_path)
if search_path then
self:setPath(search_path)
else
self:setPath("/mnt/us/documents")
end
end
function FileSearcher:choose(ypos, height, keywords)
local perpage = math.floor(height / self.spacing) - 2
local pagedirty = true
local markerdirty = false
local prevItem = function ()
if self.current == 1 then
if self.page > 1 then
self.current = perpage
self.page = self.page - 1
pagedirty = true
end
else
self.current = self.current - 1
markerdirty = true
end
end
local nextItem = function ()
if self.current == perpage then
if self.page < (self.items / perpage) then
self.current = 1
self.page = self.page + 1
pagedirty = true
end
else
if self.page ~= math.floor(self.items / perpage) + 1
or self.current + (self.page-1)*perpage < self.items then
self.current = self.current + 1
markerdirty = true
end
end
end
self:setSearchResult(keywords)
while true do
if pagedirty then
markerdirty = true
fb.bb:paintRect(0, ypos, fb.bb:getWidth(), height, 0)
-- draw menu title
renderUtf8Text(fb.bb, 30, ypos + self.title_H, self.tface, self.tfhash,
"Search Result for: "..keywords, true)
-- draw results
local c
if self.items == 0 then -- nothing found
y = ypos + self.title_H + self.spacing * 2
renderUtf8Text(fb.bb, 20, y, self.face, self.fhash,
"Sorry, your keyword did not match any documents.", true)
renderUtf8Text(fb.bb, 20, y + self.spacing, self.face, self.fhash,
"Please try a different keyword.", true)
markerdirty = false
else -- found something, draw it
for c = 1, perpage do
local i = (self.page - 1) * perpage + c
if i <= self.items then
y = ypos + self.title_H + (self.spacing * c)
renderUtf8Text(fb.bb, 50, y, self.face, self.fhash,
self.result[i].name, true)
end
end
end
-- draw footer
y = ypos + self.title_H + (self.spacing * perpage) + self.foot_H
x = (fb.bb:getWidth() / 2) - 50
all_page = (math.floor(self.items / perpage)+1)
renderUtf8Text(fb.bb, x, y, self.sface, self.sfhash,
"Page "..self.page.." of "..all_page, true)
end
if markerdirty then
if not pagedirty then
if self.oldcurrent > 0 then
y = ypos + self.title_H + (self.spacing * self.oldcurrent) + 10
fb.bb:paintRect(30, y, fb.bb:getWidth() - 60, 3, 0)
fb:refresh(1, 30, y, fb.bb:getWidth() - 60, 3)
end
end
-- draw new marker line
y = ypos + self.title_H + (self.spacing * self.current) + 10
fb.bb:paintRect(30, y, fb.bb:getWidth() - 60, 3, 15)
if not pagedirty then
fb:refresh(1, 30, y, fb.bb:getWidth() - 60, 3)
end
self.oldcurrent = self.current
markerdirty = false
end
if pagedirty then
fb:refresh(0, 0, ypos, fb.bb:getWidth(), height)
pagedirty = false
end
local ev = input.waitForEvent()
if ev.type == EV_KEY and ev.value == EVENT_VALUE_KEY_PRESS then
if ev.code == KEY_FW_UP then
prevItem()
elseif ev.code == KEY_FW_DOWN then
nextItem()
elseif ev.code == KEY_PGFWD then
if self.page < (self.items / perpage) then
if self.current + self.page*perpage > self.items then
self.current = self.items - self.page*perpage
end
self.page = self.page + 1
pagedirty = true
else
self.current = self.items - (self.page-1)*perpage
markerdirty = true
end
elseif ev.code == KEY_PGBCK then
if self.page > 1 then
self.page = self.page - 1
pagedirty = true
else
self.current = 1
markerdirty = true
end
elseif ev.code == KEY_S then
old_keywords = keywords
keywords = InputBox:input(height-100, 100, "Search:", old_keywords)
if keywords then
self:setSearchResult(keywords)
else
keywords = old_keywords
end
pagedirty = true
elseif ev.code == KEY_ENTER or ev.code == KEY_FW_PRESS then
-- return full file path
file_entry = self.files[perpage*(self.page-1)+self.current]
return file_entry.dir .. "/" .. file_entry.name
elseif ev.code == KEY_BACK then
return nil
end
end
end
end

@ -0,0 +1,172 @@
require "rendertext"
require "keys"
require "graphics"
InputBox = {
-- Class vars:
input_start_x = 145,
input_start_y = nil,
input_cur_x = nil, -- points to the start of next input pos
input_bg = 1,
input_string = "",
-- font for displaying input content
face = freetype.newBuiltinFace("mono", 25),
fhash = "m25",
fheight = 25,
fwidth = 16,
}
function InputBox:setDefaultInput(text)
self.input_string = ""
self:addString(text)
--renderUtf8Text(fb.bb, self.input_start_x, self.input_start_y,
--self.face, self.fhash, text, true)
--self.input_cur_x = self.input_start_x + (string.len(text) * self.fwidth)
--self.input_string = text
end
function InputBox:addString(str)
for i = 1, #str do
self:addChar(str:sub(i,i))
end
end
function InputBox:addChar(char)
renderUtf8Text(fb.bb, self.input_cur_x, self.input_start_y, self.face, self.fhash,
char, true)
fb:refresh(1, self.input_cur_x, self.input_start_y-19, self.fwidth, self.fheight)
self.input_cur_x = self.input_cur_x + self.fwidth
self.input_string = self.input_string .. char
end
function InputBox:delChar()
if self.input_start_x == self.input_cur_x then
return
end
self.input_cur_x = self.input_cur_x - self.fwidth
--fill last character with blank rectangle
fb.bb:paintRect(self.input_cur_x, self.input_start_y-19,
self.fwidth, self.fheight, self.input_bg)
fb:refresh(1, self.input_cur_x, self.input_start_y-19, self.fwidth, self.fheight)
self.input_string = self.input_string:sub(0,-2)
end
function InputBox:drawBox(ypos, w, h, title)
-- draw input border
fb.bb:paintRect(20, ypos, w, h, 5)
-- draw input slot
fb.bb:paintRect(140, ypos + 10, w - 130, h - 20, self.input_bg)
-- draw input title
renderUtf8Text(fb.bb, 35, self.input_start_y, self.face, self.fhash,
title, true)
end
--[[
|| d_text default to nil (used to set default text in input slot)
--]]
function InputBox:input(ypos, height, title, d_text)
local pagedirty = true
-- do some initilization
self.input_start_y = ypos + 35
self.input_cur_x = self.input_start_x
if d_text then -- if specified default text, draw it
w = fb.bb:getWidth() - 40
h = height - 45
self:drawBox(ypos, w, h, title)
self:setDefaultInput(d_text)
fb:refresh(1, 20, ypos, w, h)
pagedirty = false
else -- otherwise, leave the draw task to the main loop
self.input_string = ""
end
while true do
if pagedirty then
w = fb.bb:getWidth() - 40
h = height - 45
self:drawBox(ypos, w, h, title)
fb:refresh(1, 20, ypos, w, h)
pagedirty = false
end
local ev = input.waitForEvent()
if ev.type == EV_KEY and ev.value == EVENT_VALUE_KEY_PRESS then
print("key code:"..ev.code)
--ev.code = adjustFWKey(ev.code)
if ev.code == KEY_FW_UP then
elseif ev.code == KEY_FW_DOWN then
elseif ev.code == KEY_A then
self:addChar("a")
elseif ev.code == KEY_B then
self:addChar("b")
elseif ev.code == KEY_C then
self:addChar("c")
elseif ev.code == KEY_D then
self:addChar("d")
elseif ev.code == KEY_E then
self:addChar("e")
elseif ev.code == KEY_F then
self:addChar("f")
elseif ev.code == KEY_G then
self:addChar("g")
elseif ev.code == KEY_H then
self:addChar("h")
elseif ev.code == KEY_I then
self:addChar("i")
elseif ev.code == KEY_J then
self:addChar("j")
elseif ev.code == KEY_K then
self:addChar("k")
elseif ev.code == KEY_L then
self:addChar("l")
elseif ev.code == KEY_M then
self:addChar("m")
elseif ev.code == KEY_N then
self:addChar("n")
elseif ev.code == KEY_O then
self:addChar("o")
elseif ev.code == KEY_P then
self:addChar("p")
elseif ev.code == KEY_Q then
self:addChar("q")
elseif ev.code == KEY_R then
self:addChar("r")
elseif ev.code == KEY_S then
self:addChar("s")
elseif ev.code == KEY_T then
self:addChar("t")
elseif ev.code == KEY_U then
self:addChar("u")
elseif ev.code == KEY_V then
self:addChar("v")
elseif ev.code == KEY_W then
self:addChar("w")
elseif ev.code == KEY_X then
self:addChar("x")
elseif ev.code == KEY_Y then
self:addChar("y")
elseif ev.code == KEY_Z then
self:addChar("z")
elseif ev.code == KEY_SPACE then
self:addChar(" ")
elseif ev.code == KEY_PGFWD then
elseif ev.code == KEY_PGBCK then
elseif ev.code == KEY_ENTER or ev.code == KEY_FW_PRESS then
if self.input_string == "" then
return nil
else
return self.input_string
end
elseif ev.code == KEY_DEL then
self:delChar()
elseif ev.code == KEY_BACK then
return nil
end
end
end
end

@ -109,22 +109,45 @@ function set_emu_keycodes()
KEY_PGFWD = 117
KEY_PGBCK = 112
KEY_BACK = 22 -- backspace
KEY_DEL = 119 -- Delete
KEY_MENU = 67 -- F1
KEY_FW_UP = 111
KEY_FW_DOWN = 116
KEY_FW_LEFT = 113
KEY_FW_RIGHT = 114
KEY_FW_PRESS = 36 -- enter for now
KEY_SPACE = 65
KEY_ENTER = 36
KEY_Q = 24
KEY_W = 25
KEY_E = 26
KEY_R = 27
KEY_T = 28
KEY_Y = 29
KEY_U = 30
KEY_I = 31
KEY_O = 32
KEY_P = 33
KEY_A = 38
KEY_S = 39
KEY_D = 40
KEY_F = 41
KEY_G = 42
KEY_H = 43
KEY_J = 44
KEY_K = 45
KEY_L = 46
KEY_Z = 52
KEY_X = 53
KEY_C = 54
KEY_V = 55
KEY_B = 56
KEY_N = 57
KEY_M = 58
KEY_SHIFT = 50 -- left shift
KEY_ALT = 64 -- left alt

Loading…
Cancel
Save