[feat] Add dictionary download option (#3176)

You can now download pretty much all of the easily available freely licensed dictionaries I could find.
This commit is contained in:
Frans de Jonge
2018-12-13 06:27:49 +00:00
committed by GitHub
parent 8fec0f330f
commit b261a647c2
4 changed files with 330 additions and 4 deletions

View File

@@ -8,8 +8,10 @@ local InputContainer = require("ui/widget/container/inputcontainer")
local JSON = require("json")
local KeyValuePage = require("ui/widget/keyvaluepage")
local LuaData = require("luadata")
local NetworkMgr = require("ui/network/manager")
local Trapper = require("ui/trapper")
local UIManager = require("ui/uimanager")
local ffiUtil = require("ffi/util")
local logger = require("logger")
local util = require("util")
local _ = require("gettext")
@@ -238,6 +240,10 @@ function ReaderDictionary:addToMainMenu(menu_items)
})
end,
},
{
text = _("Download dictionaries"),
sub_item_table = self:_genDownloadDictionariesMenu()
},
{
text = _("Enable fuzzy search"),
checked_func = function()
@@ -370,6 +376,50 @@ function ReaderDictionary:getNumberOfDictionaries()
return nb_available, nb_enabled, nb_disabled
end
function ReaderDictionary:_genDownloadDictionariesMenu()
local downloadable_dicts = require("ui/data/dictionaries")
local languages = {}
for i = 1, #downloadable_dicts do
local dict = downloadable_dicts[i]
local dict_lang_in = dict.lang_in
local dict_lang_out = dict.lang_out
if not languages[dict_lang_in] then
languages[dict_lang_in] = {}
end
table.insert(languages[dict_lang_in], dict)
if not languages[dict_lang_out] then
languages[dict_lang_out] = {}
end
table.insert(languages[dict_lang_out], dict)
end
-- remove duplicates
for lang_key,lang in pairs(languages) do
local hash = {}
local res = {}
for k,v in ipairs(lang) do
if not hash[v.name] then
res[#res+1] = v
hash[v.name] = true
end
end
languages[lang_key] = res
end
local menu_items = {}
for lang_key, available_langs in ffiUtil.orderedPairs(languages) do
table.insert(menu_items, {
text = lang_key,
callback = function()
self:showDownload(available_langs)
end
})
end
return menu_items
end
function ReaderDictionary:genDictionariesMenu()
local items = {}
for _, ifo in pairs(available_ifos) do
@@ -677,6 +727,128 @@ function ReaderDictionary:showDict(word, results, box, link)
end
end
function ReaderDictionary:showDownload(downloadable_dicts)
local kv_pairs = {}
table.insert(kv_pairs, {_("Tap dictionary name to download"), ""})
table.insert(kv_pairs, "----------------------------")
for dummy, dict in ipairs(downloadable_dicts) do
table.insert(kv_pairs, {dict.name, "",
callback = function()
if not NetworkMgr:isOnline() then
NetworkMgr:promptWifiOn()
return
end
self:downloadDictionaryPrep(dict)
end})
local lang
if dict.lang_in == dict.lang_out then
lang = string.format(" %s", dict.lang_in)
else
lang = string.format(" %s%s", dict.lang_in, dict.lang_out)
end
table.insert(kv_pairs, {lang, ""})
table.insert(kv_pairs, {" ".._("License"), dict.license})
table.insert(kv_pairs, {" ".._("Entries"), dict.entries})
table.insert(kv_pairs, "----------------------------")
end
self.download_window = KeyValuePage:new{
title = _("Download dictionaries"),
kv_pairs = kv_pairs,
}
UIManager:show(self.download_window)
end
function ReaderDictionary:downloadDictionaryPrep(dict, size)
local dummy, filename = util.splitFilePathName(dict.url)
local download_location = string.format("%s/%s", self.data_dir, filename)
local lfs = require("libs/libkoreader-lfs")
if lfs.attributes(download_location) then
UIManager:show(ConfirmBox:new{
text = _("File already exists. Overwrite?"),
ok_text = _("Overwrite"),
ok_callback = function()
self:downloadDictionary(dict, download_location)
end,
})
else
self:downloadDictionary(dict, download_location)
end
end
function ReaderDictionary:downloadDictionary(dict, download_location, continue)
continue = continue or false
local socket = require("socket")
local http = socket.http
local https = require("ssl.https")
local ltn12 = require("ltn12")
local url = socket.url
local parsed = url.parse(dict.url)
local httpRequest = parsed.scheme == "http" and http.request or https.request
if not continue then
local file_size
--local r, c, h = httpRequest {
local dummy, headers, dummy = socket.skip(1, httpRequest{
method = "HEAD",
url = dict.url,
--redirect = true,
})
--logger.dbg(status)
--logger.dbg(headers)
--logger.dbg(code)
file_size = headers and headers["content-length"]
UIManager:show(ConfirmBox:new{
text = T(_("Dictionary filesize is %1 (%2 bytes). Continue with download?"), util.getFriendlySize(file_size), util.getFormattedSize(file_size)),
ok_text = _("Download"),
ok_callback = function()
-- call ourselves with continue = true
self:downloadDictionary(dict, download_location, true)
end,
})
return
else
UIManager:nextTick(function()
UIManager:show(InfoMessage:new{
text = _("Downloading…"),
timeout = 3,
})
end)
end
local dummy, c, dummy = httpRequest{
url = dict.url,
sink = ltn12.sink.file(io.open(download_location, "w")),
}
if c == 200 then
logger.dbg("file downloaded to", download_location)
else
UIManager:show(InfoMessage:new{
text = _("Could not save file to:\n") .. download_location,
--timeout = 3,
})
return false
end
local ok, error = util.unpackArchive(download_location, self.data_dir)
if ok then
available_ifos = false
self:init()
UIManager:show(InfoMessage:new{
text = _("Dictionary downloaded:\n") .. dict.name,
})
return true
else
UIManager:show(InfoMessage:new{
text = _("Dictionary failed to download:\n") .. string.format("%s\n%s", dict.name, error),
})
return false
end
end
function ReaderDictionary:onUpdateDefaultDict(dict)
logger.dbg("make default dictionary:", dict)
self.default_dictionary = dict