add fulltext search for EPUB documents

pull/1079/head
chrox 10 years ago
parent 8ddca4bf49
commit bd0975896d

@ -1 +1 @@
Subproject commit af763e714395a9bf1a2356f7fb99a020c0387684
Subproject commit 5a83d4aaded90420306380613ccdc4613a53a9ce

@ -111,19 +111,24 @@ function ReaderHighlight:onSetDimensions(dimen)
end
function ReaderHighlight:clear()
if self.ui.document.info.has_pages then
self.view.highlight.temp = {}
else
self.ui.document:clearSelection()
end
UIManager:setDirty(self.dialog, "partial")
if self.hold_pos then
if self.ui.document.info.has_pages then
self.view.highlight.temp[self.hold_pos.page] = nil
else
self.ui.document:clearSelection()
end
self.hold_pos = nil
self.selected_text = nil
UIManager:setDirty(self.dialog, "partial")
return true
end
end
function ReaderHighlight:onClearHighlight()
self:clear()
return true
end
function ReaderHighlight:onTap(arg, ges)
if not self:clear() then
if self.ui.document.info.has_pages then
@ -333,11 +338,10 @@ function ReaderHighlight:onHoldRelease()
},
{
{
text = _("Share"),
enabled = false,
text = _("Search"),
callback = function()
self:shareHighlight()
self:onClose()
self:onHighlightSearch()
UIManager:close(self.highlight_dialog)
end,
},
{
@ -357,16 +361,20 @@ function ReaderHighlight:onHoldRelease()
return true
end
function ReaderHighlight:onHighlight()
function ReaderHighlight:highlightFromHoldPos()
if self.hold_pos then
if not self.selected_text then
self.selected_text = self.ui.document:getTextFromPositions(self.hold_pos, self.hold_pos)
DEBUG("selected text:", self.selected_text)
end
self:saveHighlight()
end
end
function ReaderHighlight:onHighlight()
self:highlightFromHoldPos()
self:saveHighlight()
end
function ReaderHighlight:saveHighlight()
DEBUG("save highlight")
local page = self.hold_pos.page
@ -427,6 +435,14 @@ function ReaderHighlight:lookupWikipedia()
end
end
function ReaderHighlight:onHighlightSearch()
DEBUG("search highlight")
self:highlightFromHoldPos()
if self.selected_text then
self.ui:handleEvent(Event:new("ShowSearchDialog", self.selected_text.text))
end
end
function ReaderHighlight:shareHighlight()
DEBUG("share highlight")
end

@ -0,0 +1,100 @@
local InputContainer = require("ui/widget/container/inputcontainer")
local ButtonDialog = require("ui/widget/buttondialog")
local UIManager = require("ui/uimanager")
local Geom = require("ui/geometry")
local Screen = require("ui/screen")
local DEBUG = require("dbg")
local _ = require("gettext")
local ReaderSearch = InputContainer:new{
direction = 0, -- 0 for search forward, 1 for search backward
case_insensitive = 1, -- default to case insensitive
}
function ReaderSearch:init()
self.ui.menu:registerToMainMenu(self)
end
function ReaderSearch:addToMainMenu(tab_item_table)
table.insert(tab_item_table.plugins, {
text = _("Fulltext search"),
tap_input = {
title = _("Input text to search for"),
type = "text",
callback = function(input)
self:onShowSearchDialog(input)
end,
},
})
end
function ReaderSearch:onShowSearchDialog(text)
local do_search = function(search_func, text, param)
return function()
local res = search_func(self, text, param)
if res then
self.ui.link:onGotoLink(res[1].start)
end
end
end
self.search_dialog = ButtonDialog:new{
alpha = 0.5,
buttons = {
{
{
text = "|<",
callback = do_search(self.searchFromStart, text),
},
{
text = "<",
callback = do_search(self.searchNext, text, 1),
},
{
text = ">",
callback = do_search(self.searchNext, text, 0),
},
{
text = ">|",
callback = do_search(self.searchFromEnd, text),
},
}
},
tap_close_callback = function()
DEBUG("highlight clear")
self.ui.highlight:clear()
end,
}
local res = do_search(self.searchFromCurrent, text, 0)()
UIManager:show(self.search_dialog)
UIManager:setDirty(self.dialog, "partial")
return true
end
function ReaderSearch:search(pattern, origin)
local direction = self.direction
local case = self.case_insensitive
return self.ui.document:findText(pattern, origin, direction, case)
end
function ReaderSearch:searchFromStart(pattern)
self.direction = 0
return self:search(pattern, -1)
end
function ReaderSearch:searchFromEnd(pattern)
self.direction = 1
return self:search(pattern, -1)
end
function ReaderSearch:searchFromCurrent(pattern, direction)
self.direction = direction
return self:search(pattern, 0)
end
-- ignore current page and search next occurrence
function ReaderSearch:searchNext(pattern, direction)
self.direction = direction
return self:search(pattern, 1)
end
return ReaderSearch

@ -37,9 +37,10 @@ local ReaderDictionary = require("apps/reader/modules/readerdictionary")
local ReaderWikipedia = require("apps/reader/modules/readerwikipedia")
local ReaderHyphenation = require("apps/reader/modules/readerhyphenation")
local ReaderActivityIndicator = require("apps/reader/modules/readeractivityindicator")
local FileManagerHistory = require("apps/filemanager/filemanagerhistory")
local ReaderSearch = require("apps/reader/modules/readersearch")
local ReaderLink = require("apps/reader/modules/readerlink")
local PluginLoader = require("apps/reader/pluginloader")
local FileManagerHistory = require("apps/filemanager/filemanagerhistory")
--[[
This is an abstraction for a reader interface
@ -280,6 +281,12 @@ function ReaderUI:init()
ui = self
})
end
-- fulltext search
self:registerModule("search", ReaderSearch:new{
dialog = self.dialog,
view = self.view,
ui = self
})
-- koreader plugins
for _,module in ipairs(PluginLoader:loadPlugins()) do

@ -312,6 +312,7 @@ function CreDocument:setFontFace(new_font_face)
end
function CreDocument:clearSelection()
DEBUG("clear selection")
self._document:clearSelection()
end
@ -418,6 +419,11 @@ function CreDocument:setStatusLineProp(prop)
self._document:setStringProperty("window.status.line", prop)
end
function CreDocument:findText(pattern, origin, reverse, caseInsensitive)
DEBUG("CreDocument: find text", pattern, origin, reverse, caseInsensitive)
return self._document:findText(pattern, origin, reverse, caseInsensitive)
end
function CreDocument:register(registry)
registry:addProvider("txt", "application/txt", self)
registry:addProvider("epub", "application/epub", self)

@ -217,6 +217,10 @@ function Document:getCoverPageImage()
return nil
end
function Document:findText()
return nil
end
function Document:getFullPageHash(pageno, zoom, rotation, gamma, render_mode)
return "renderpg|"..self.file.."|"..self.mod_time.."|"..pageno.."|"
..zoom.."|"..rotation.."|"..gamma.."|"..render_mode

@ -187,10 +187,10 @@ function DictQuickLookup:update()
end,
},
{
text = _("More"),
enabled = false,
text = _("Search"),
callback = function()
self.ui:handleEvent(Event:new("HighlightMore"))
self.ui:handleEvent(Event:new("HighlightSearch"))
UIManager:close(self)
end,
},
},

@ -0,0 +1,94 @@
require("commonrequire")
local DocumentRegistry = require("document/documentregistry")
local ReaderUI = require("apps/reader/readerui")
local DEBUG = require("dbg")
local sample_epub = "spec/front/unit/data/juliet.epub"
describe("Readersearch module", function()
describe("search API for EPUB documents", function()
local doc, search, rolling
setup(function()
local readerui = ReaderUI:new{
document = DocumentRegistry:openDocument(sample_epub),
}
doc = readerui.document
search = readerui.search
rolling = readerui.rolling
end)
it("should search backward", function()
rolling:gotoPage(10)
assert.truthy(search:searchFromCurrent("Verona", 1))
for i = 1, 100, 10 do
rolling:gotoPage(i)
local words = search:searchFromCurrent("Verona", 1)
if words then
for _, word in ipairs(words) do
local pageno = doc:getPageFromXPointer(word.start)
--DEBUG("found at pageno", pageno)
assert.truthy(pageno <= i)
end
end
end
end)
it("should search forward", function()
rolling:gotoPage(10)
assert.truthy(search:searchFromCurrent("Verona", 0))
for i = 1, 100, 10 do
rolling:gotoPage(i)
local words = search:searchFromCurrent("Verona", 0)
if words then
for _, word in ipairs(words) do
local pageno = doc:getPageFromXPointer(word.start)
--DEBUG("found at pageno", pageno)
assert.truthy(pageno >= i)
end
end
end
end)
it("should find the first occurrence", function()
for i = 10, 100, 10 do
rolling:gotoPage(i)
local words = search:searchFromStart("Verona")
assert.truthy(words)
local pageno = doc:getPageFromXPointer(words[1].start)
assert.are.equal(8, pageno)
end
for i = 1, 5, 1 do
rolling:gotoPage(i)
local words = search:searchFromStart("Verona")
assert(words == nil)
end
end)
it("should find the last occurrence", function()
for i = 100, 200, 10 do
rolling:gotoPage(i)
local words = search:searchFromEnd("Verona")
assert.truthy(words)
local pageno = doc:getPageFromXPointer(words[1].start)
assert.are.equal(208, pageno)
end
for i = 230, 235, 1 do
rolling:gotoPage(i)
local words = search:searchFromEnd("Verona")
assert(words == nil)
end
end)
it("should find all occurrences", function()
local count = 0
rolling:gotoPage(1)
local words = search:searchFromCurrent("Verona", 0)
while words do
count = count + #words
for _, word in ipairs(words) do
--DEBUG("found word", word.start)
end
doc:gotoXPointer(words[1].start)
words = search:searchNext("Verona", 0)
end
assert.are.equal(13, count)
end)
end)
describe("search API for PDF documents", function()
end)
end)
Loading…
Cancel
Save