mirror of
https://github.com/koreader/koreader.git
synced 2025-08-10 00:52:38 +00:00
[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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user