CoverBrowser: adjustable mosaic grid (#11232)

reviewable/pr11341/r1
hius07 4 months ago committed by GitHub
parent cd903d66e5
commit ea9ef6781c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -4,9 +4,11 @@ local ConfirmBox = require("ui/widget/confirmbox")
local Device = require("device")
local FFIUtil = require("ffi/util")
local InputContainer = require("ui/widget/container/inputcontainer")
local KeyValuePage = require("ui/widget/keyvaluepage")
local PluginLoader = require("pluginloader")
local SetDefaults = require("apps/filemanager/filemanagersetdefaults")
local Size = require("ui/size")
local SpinWidget = require("ui/widget/spinwidget")
local UIManager = require("ui/uimanager")
local Screen = Device.screen
local filemanagerutil = require("apps/filemanager/filemanagerutil")
@ -168,49 +170,49 @@ function FileManagerMenu:setUpdateItemTable()
text = _("Classic mode settings"),
sub_item_table = {
{
text = _("Items per page"),
text_func = function()
return T(_("Items per page: %1"), FileChooser.perpage)
end,
help_text = _([[This sets the number of items per page in:
- File browser, history and favorites in 'classic' display mode
- Search results and folder shortcuts
- File and folder selection
- Calibre and OPDS browsers/search results]]),
callback = function()
local SpinWidget = require("ui/widget/spinwidget")
local Menu = require("ui/widget/menu")
local default_perpage = Menu.items_per_page_default
local curr_perpage = G_reader_settings:readSetting("items_per_page") or default_perpage
local items = SpinWidget:new{
value = curr_perpage,
value_min = 6,
value_max = 24,
default_value = default_perpage,
callback = function(touchmenu_instance)
local current_value = FileChooser.perpage
local default_value = FileChooser.items_per_page_default
local widget = SpinWidget:new{
title_text = _("Items per page"),
value = current_value,
value_min = 6,
value_max = 30,
default_value = default_value,
keep_shown_on_apply = true,
callback = function(spin)
G_reader_settings:saveSetting("items_per_page", spin.value)
self.ui:onRefresh()
end
FileChooser:refreshPath()
touchmenu_instance:updateItems()
end,
}
UIManager:show(items)
UIManager:show(widget)
end,
},
{
text = _("Item font size"),
callback = function()
local SpinWidget = require("ui/widget/spinwidget")
local Menu = require("ui/widget/menu")
local curr_perpage = G_reader_settings:readSetting("items_per_page") or Menu.items_per_page_default
local default_font_size = Menu.getItemFontSize(curr_perpage)
local curr_font_size = G_reader_settings:readSetting("items_font_size") or default_font_size
local items_font = SpinWidget:new{
value = curr_font_size,
text_func = function()
return T(_("Item font size: %1"), FileChooser.font_size)
end,
callback = function(touchmenu_instance)
local current_value = FileChooser.font_size
local default_value = FileChooser.getItemFontSize(FileChooser.perpage)
local widget = SpinWidget:new{
title_text = _("Item font size"),
value = current_value,
value_min = 10,
value_max = 72,
default_value = default_font_size,
default_value = default_value,
keep_shown_on_apply = true,
title_text = _("Item font size"),
callback = function(spin)
if spin.value == default_font_size then
if spin.value == default_value then
-- We can't know if the user has set a size or hit "Use default", but
-- assume that if it is the default font size, he will prefer to have
-- our default font size if he later updates per-page
@ -218,10 +220,11 @@ function FileManagerMenu:setUpdateItemTable()
else
G_reader_settings:saveSetting("items_font_size", spin.value)
end
self.ui:onRefresh()
end
FileChooser:refreshPath()
touchmenu_instance:updateItems()
end,
}
UIManager:show(items_font)
UIManager:show(widget)
end,
},
{
@ -373,26 +376,28 @@ To:
separator = true,
},
{
text = _("Info lists items per page"),
text_func = function()
local default_value = KeyValuePage.getDefaultItemsPerPage()
local current_value = G_reader_settings:readSetting("keyvalues_per_page") or default_value
return T(_("Info lists items per page: %1"), current_value)
end,
help_text = _([[This sets the number of items per page in:
- Book information
- Dictionary and Wikipedia lookup history
- Reading statistics details
- A few other plugins]]),
keep_menu_open = true,
callback = function()
local SpinWidget = require("ui/widget/spinwidget")
local KeyValuePage = require("ui/widget/keyvaluepage")
local default_perpage = KeyValuePage:getDefaultKeyValuesPerPage()
local curr_perpage = G_reader_settings:readSetting("keyvalues_per_page") or default_perpage
local items = SpinWidget:new{
value = curr_perpage,
callback = function(touchmenu_instance)
local default_value = KeyValuePage.getDefaultItemsPerPage()
local current_value = G_reader_settings:readSetting("keyvalues_per_page") or default_value
local widget = SpinWidget:new{
value = current_value,
value_min = 10,
value_max = 24,
default_value = default_perpage,
value_max = 30,
default_value = default_value,
title_text = _("Info lists items per page"),
callback = function(spin)
if spin.value == default_perpage then
if spin.value == default_value then
-- We can't know if the user has set a value or hit "Use default", but
-- assume that if it is the default, he will prefer to stay with our
-- default if he later changes screen DPI
@ -400,9 +405,10 @@ To:
else
G_reader_settings:saveSetting("keyvalues_per_page", spin.value)
end
touchmenu_instance:updateItems()
end
}
UIManager:show(items)
UIManager:show(widget)
end,
},
},

@ -467,14 +467,10 @@ function KeyValuePage:init()
- 2*Size.line.thick
-- account for possibly 2 separator lines added
local force_items_per_page
if self.single_page then
force_items_per_page = math.max(#self.kv_pairs,
G_reader_settings:readSetting("keyvalues_per_page") or self:getDefaultKeyValuesPerPage())
self.items_per_page = G_reader_settings:readSetting("keyvalues_per_page") or self.getDefaultItemsPerPage()
if self.single_page and self.items_per_page < #self.kv_pairs then
self.items_per_page = #self.kv_pairs
end
self.items_per_page = force_items_per_page or
G_reader_settings:readSetting("keyvalues_per_page") or self:getDefaultKeyValuesPerPage()
self.item_height = math.floor(available_height / self.items_per_page)
-- Put half of the pixels lost by floor'ing between title and content
local content_height = self.items_per_page * self.item_height
@ -522,7 +518,7 @@ function KeyValuePage:init()
}
end
function KeyValuePage:getDefaultKeyValuesPerPage()
function KeyValuePage.getDefaultItemsPerPage()
-- Get a default according to Screen DPI (roughly following
-- the former implementation building logic)
local default_item_height = Size.item.height_default * 1.5 -- we were adding 1/2 as margin
@ -685,7 +681,7 @@ function KeyValuePage:_populateItems()
background = Blitbuffer.COLOR_LIGHT_GRAY,
dimen = Geom:new{
w = self.item_width,
h = Size.line.thick
h = Size.line.thick,
},
style = "solid",
})
@ -699,7 +695,7 @@ function KeyValuePage:_populateItems()
background = Blitbuffer.COLOR_LIGHT_GRAY,
dimen = Geom:new{
w = self.item_width,
h = Size.line.thick
h = Size.line.thick,
},
style = "solid",
})

@ -1040,9 +1040,9 @@ function Menu:updateItems(select_number)
select_number = 1
end
local font_size = self.items_font_size or G_reader_settings:readSetting("items_font_size")
self.font_size = self.items_font_size or G_reader_settings:readSetting("items_font_size")
or Menu.getItemFontSize(self.perpage)
local infont_size = self.items_mandatory_font_size or (font_size - 4)
local infont_size = self.items_mandatory_font_size or (self.font_size - 4)
local multilines_show_more_text = self.multilines_show_more_text
if multilines_show_more_text == nil then
multilines_show_more_text = G_reader_settings:isTrue("items_multilines_show_more_text")
@ -1075,7 +1075,7 @@ function Menu:updateItems(select_number)
bold = self.item_table.current == i or self.item_table[i].bold == true,
dim = self.item_table[i].dim,
font = "smallinfofont",
font_size = font_size,
font_size = self.font_size,
infont = "infont",
infont_size = infont_size,
dimen = self.item_dimen:new(),

@ -39,7 +39,7 @@ local BOOKINFO_DB_SCHEMA = [[
cover_fetched TEXT, -- NULL / 'Y' = we tried to fetch a cover (but we may not have gotten one)
has_meta TEXT, -- NULL / 'Y' = has metadata (title, authors...)
has_cover TEXT, -- NULL / 'Y' = has cover image (cover_*)
cover_sizetag TEXT, -- 'M' (Medium, MosaicMenuItem) / 's' (small, ListMenuItem)
cover_sizetag TEXT, -- '1072x1448' (example, is the original cover image width and height)
-- Other properties that can be set and returned as is (not used here)
-- If user doesn't want to see these (wrong metadata, offending cover...)
@ -270,7 +270,7 @@ function BookInfoManager:loadSettings(db_conn)
local keys = res[1]
local values = res[2]
for i, key in ipairs(keys) do
self.settings[key] = values[i]
self.settings[key] = tonumber(values[i]) or values[i] -- TEXT db field
end
end
end
@ -506,23 +506,18 @@ function BookInfoManager:extractBookInfo(filepath, cover_specs)
dbrow[k] = v
end
if cover_specs then
local spec_sizetag = cover_specs.sizetag
local spec_max_cover_w = cover_specs.max_cover_w
local spec_max_cover_h = cover_specs.max_cover_h
dbrow.cover_fetched = 'Y' -- we had a try at getting a cover
local cover_bb = FileManagerBookInfo:getCoverImage(document)
if cover_bb then
dbrow.has_cover = 'Y'
dbrow.cover_sizetag = spec_sizetag
-- we should scale down the cover to our max size
local cbb_w, cbb_h = cover_bb:getWidth(), cover_bb:getHeight()
local scale_factor = 1
dbrow.cover_sizetag = cbb_w .. "x" .. cbb_h -- store original cover size
if cbb_w > spec_max_cover_w or cbb_h > spec_max_cover_h then
-- scale down if bigger than what we will display
scale_factor = math.min(spec_max_cover_w / cbb_w, spec_max_cover_h / cbb_h)
cbb_w = math.min(math.floor(cbb_w * scale_factor)+1, spec_max_cover_w)
cbb_h = math.min(math.floor(cbb_h * scale_factor)+1, spec_max_cover_h)
cbb_w, cbb_h = BookInfoManager.getCachedCoverSize(cbb_w, cbb_h, spec_max_cover_w, spec_max_cover_h)
cover_bb = RenderImage:scaleBlitBuffer(cover_bb, cbb_w, cbb_h, true)
end
dbrow.cover_w = cover_bb.w
@ -532,7 +527,8 @@ function BookInfoManager:extractBookInfo(filepath, cover_specs)
local cover_size = cover_bb.stride * cover_bb.h
local cover_zst_ptr, cover_zst_size = zstd.zstd_compress(cover_bb.data, cover_size)
dbrow.cover_bb_data = SQ3.blob(cover_zst_ptr, cover_zst_size) -- cast to blob for sqlite
logger.dbg("cover for", filename, "scaled by", scale_factor, "=>", cover_bb.w, "x", cover_bb.h, ", compressed from", tonumber(cover_size), "to", tonumber(cover_zst_size))
logger.dbg("cover for", filename, "scaled from", dbrow.cover_sizetag, "to", cover_bb.w, "x", cover_bb.h,
", compressed from", tonumber(cover_size), "to", tonumber(cover_zst_size))
-- We're done with the uncompressed bb now, and the compressed one has been managed by SQLite ;)
cover_bb:free()
end
@ -886,10 +882,8 @@ Do you want to prune the cache of removed books?]]
local to_extract = not bookinfo
if bookinfo and cover_specs and not bookinfo.ignore_cover then
if bookinfo.cover_fetched then
if bookinfo.has_cover and cover_specs.sizetag ~= bookinfo.cover_sizetag then
if bookinfo.cover_sizetag ~= "M" then -- keep the bigger "M"
to_extract = true
end
if bookinfo.has_cover and BookInfoManager.isCachedCoverInvalid(bookinfo, cover_specs) then
to_extract = true
end
else
to_extract = true
@ -985,6 +979,35 @@ Do you want to prune the cache of removed books?]]
UIManager:show(info)
end
function BookInfoManager.getCachedCoverSize(img_w, img_h, max_img_w, max_img_h)
local scale_factor
local width = math.floor(max_img_h * img_w / img_h + 0.5)
if max_img_w >= width then
max_img_w = width
scale_factor = max_img_w / img_w
else
max_img_h = math.floor(max_img_w * img_h / img_w + 0.5)
scale_factor = max_img_h / img_h
end
return max_img_w, max_img_h, scale_factor
end
function BookInfoManager.isCachedCoverInvalid(bookinfo, cover_specs)
local img_w, img_h = bookinfo.cover_sizetag:match("(%d+)x(%d+)") -- original image
if not img_w or not img_h then -- old or bad cover_sizetag
return true
end
img_w, img_h = tonumber(img_w), tonumber(img_h)
local max_img_w = cover_specs.max_cover_w
local max_img_h = cover_specs.max_cover_h
if img_w > max_img_w or img_h > max_img_h then -- original image bigger than placeholder
local new_cover_w, new_cover_h = BookInfoManager.getCachedCoverSize(img_w, img_h, max_img_w, max_img_h)
if new_cover_w > bookinfo.cover_w or new_cover_h > bookinfo.cover_h then -- bigger thumbnail needed
return true
end
end
end
BookInfoManager:init()
return BookInfoManager

@ -209,7 +209,6 @@ function ListMenuItem:update()
local max_img_w = dimen.h - 2*border_size -- width = height, squared
local max_img_h = dimen.h - 2*border_size
local cover_specs = {
sizetag = self.menu.cover_sizetag,
max_cover_w = max_img_w,
max_cover_h = max_img_h,
}
@ -267,24 +266,26 @@ function ListMenuItem:update()
-- File
local bookinfo = BookInfoManager:getBookInfo(self.filepath, self.do_cover_image)
if bookinfo and self.do_cover_image and not bookinfo.ignore_cover then
if bookinfo.cover_fetched then
-- trigger recalculation of thumbnail if size changed
if bookinfo.has_cover and bookinfo.cover_sizetag ~= "M" and bookinfo.cover_sizetag ~= cover_specs.sizetag then
if bookinfo.cover_bb then
bookinfo.cover_bb:free()
if bookinfo.has_cover and not self.menu.no_refresh_covers then
if BookInfoManager.isCachedCoverInvalid(bookinfo, cover_specs) then
-- there is a thumbnail, but it's smaller than is needed for new grid dimensions,
-- and it would be ugly if scaled up to the required size:
-- do as if not found to force a new extraction with our size
if bookinfo.cover_bb then
bookinfo.cover_bb:free()
end
bookinfo = nil
end
bookinfo = nil
end
-- if not has_cover, book has no cover, no need to try again
else
-- cover was not fetched previously, do as if not found
-- to force a new extraction
bookinfo = nil
end
-- If there's already a cover and it's a "M" size (MosaicMenuItem),
-- we'll use it and scale it down (it may slow a bit rendering,
-- but "M" size may be useful in another view (FileBrowser/History),
-- so we don't replace it).
end
if bookinfo then -- This book is known
@ -301,7 +302,7 @@ function ListMenuItem:update()
if bookinfo.has_cover and not bookinfo.ignore_cover then
cover_bb_used = true
-- Let ImageWidget do the scaling and give us the final size
local scale_factor = math.min(max_img_w / bookinfo.cover_w, max_img_h / bookinfo.cover_h)
local _, _, scale_factor = BookInfoManager.getCachedCoverSize(bookinfo.cover_w, bookinfo.cover_h, max_img_w, max_img_h)
local wimage = ImageWidget:new{
image = bookinfo.cover_bb,
scale_factor = scale_factor,
@ -901,6 +902,7 @@ end
local ListMenu = {}
function ListMenu:_recalculateDimen()
self.portrait_mode = Screen:getWidth() <= Screen:getHeight()
-- Find out available height from other UI elements made in Menu
self.others_height = 0
if self.title_bar then -- Menu:init() has been done
@ -927,25 +929,16 @@ function ListMenu:_recalculateDimen()
end
local available_height = self.inner_dimen.h - self.others_height - Size.line.thin
-- (Note: we can't assign directly to self.perpage and expect it to
-- be 'nil' if it was not defined, as we'll find instead the value
-- defined in the Menu class (14) because of inheritance.)
local files_per_page = BookInfoManager:getSetting("files_per_page")
if files_per_page then
self.perpage = tonumber(files_per_page)
else
-- perpage used to be static and computed from a base of 64px per ListMenuItem,
-- which gave 10 items both in filemanager and history on kobo glo hd.
-- Now that we can change the nb of items, let's start with a similar default
-- and save it so it's known as the initial value by the menu selection widget.
self.perpage = math.floor(available_height / scale_by_size / 64)
BookInfoManager:saveSetting("files_per_page", tostring(self.perpage))
if self.files_per_page == nil then -- first drawing
-- Default perpage is computed from a base of 64px per ListMenuItem,
-- which gives 10 items on kobo glo hd.
self.files_per_page = math.floor(available_height / scale_by_size / 64)
BookInfoManager:saveSetting("files_per_page", self.files_per_page)
end
self.cover_sizetag = "s" .. self.perpage
if Screen:getWidth() > Screen:getHeight() then -- landscape mode
-- When in landscape mode (only possible with History), adjust
-- perpage so items get a chance to have about the same height
-- as when in portrait mode.
self.perpage = self.files_per_page
if not self.portrait_mode then
-- When in landscape mode, adjust perpage so items get a chance
-- to have about the same height as when in portrait mode.
-- This computation is not strictly correct, as "others_height" would
-- have a different value in portrait mode. But let's go with that.
local portrait_available_height = Screen:getWidth() - self.others_height - Size.line.thin

@ -2,6 +2,7 @@ local UIManager = require("ui/uimanager")
local WidgetContainer = require("ui/widget/container/widgetcontainer")
local logger = require("logger")
local _ = require("gettext")
local T = require("ffi/util").template
local BookInfoManager = require("bookinfomanager")
--[[
@ -50,7 +51,9 @@ local CoverBrowser = WidgetContainer:extend{
}
function CoverBrowser:init()
self.ui.menu:registerToMainMenu(self)
if self.ui.file_chooser then -- FileManager menu only
self.ui.menu:registerToMainMenu(self)
end
if init_done then -- things already patched according to current modes
return
@ -64,6 +67,7 @@ function CoverBrowser:init()
logger.info("CoverBrowser: setting default display modes")
BookInfoManager:saveSetting("filemanager_display_mode", "list_image_meta")
BookInfoManager:saveSetting("history_display_mode", "mosaic_image")
BookInfoManager:saveSetting("collection_display_mode", "mosaic_image")
end
G_reader_settings:makeTrue("coverbrowser_initial_default_setup_done")
end
@ -72,17 +76,11 @@ function CoverBrowser:init()
self:setupHistoryDisplayMode(BookInfoManager:getSetting("history_display_mode"))
self:setupCollectionDisplayMode(BookInfoManager:getSetting("collection_display_mode"))
series_mode = BookInfoManager:getSetting("series_mode")
init_done = true
BookInfoManager:closeDbConnection() -- will be re-opened if needed
end
function CoverBrowser:addToMainMenu(menu_items)
-- We add it only to FileManager menu
if self.ui.view then -- Reader
return
end
local modes = {
{ _("Classic (filename only)") },
{ _("Mosaic with cover images"), "mosaic_image" },
@ -94,7 +92,7 @@ function CoverBrowser:addToMainMenu(menu_items)
local sub_item_table, history_sub_item_table, collection_sub_item_table = {}, {}, {}
for i, v in ipairs(modes) do
local text, mode = unpack(v)
table.insert(sub_item_table, {
sub_item_table[i] = {
text = text,
checked_func = function()
return mode == filemanager_display_mode
@ -106,8 +104,8 @@ function CoverBrowser:addToMainMenu(menu_items)
self:setupCollectionDisplayMode(mode)
end
end,
})
table.insert(history_sub_item_table, {
}
history_sub_item_table[i] = {
text = text,
checked_func = function()
return mode == history_display_mode
@ -115,8 +113,8 @@ function CoverBrowser:addToMainMenu(menu_items)
callback = function()
self:setupHistoryDisplayMode(mode)
end,
})
table.insert(collection_sub_item_table, {
}
collection_sub_item_table[i] = {
text = text,
checked_func = function()
return mode == collection_display_mode
@ -124,7 +122,7 @@ function CoverBrowser:addToMainMenu(menu_items)
callback = function()
self:setupCollectionDisplayMode(mode)
end,
})
}
end
sub_item_table[#modes].separator = true
table.insert(sub_item_table, {
@ -161,58 +159,174 @@ function CoverBrowser:addToMainMenu(menu_items)
-- add Mosaic / Detailed list mode settings to File browser Settings submenu
-- next to Classic mode settings
if menu_items.filebrowser_settings == nil then return end
table.insert (menu_items.filebrowser_settings.sub_item_table, 4, {
table.insert (menu_items.filebrowser_settings.sub_item_table, 5, {
text = _("Mosaic and detailed list settings"),
separator = true,
sub_item_table = {
{
text = _("Items per page"),
help_text = _([[This sets the number of files and folders per page in display modes other than classic.]]),
text_func = function()
local fc = self.ui.file_chooser
return T(_("Items per page in portrait mosaic mode: %1 × %2"), fc.nb_cols_portrait, fc.nb_rows_portrait)
end,
-- Best to not "keep_menu_open = true", to see how this apply on the full view
callback = function()
local fc = self.ui.file_chooser
local nb_cols = fc.nb_cols_portrait
local nb_rows = fc.nb_rows_portrait
local DoubleSpinWidget = require("/ui/widget/doublespinwidget")
local widget = DoubleSpinWidget:new{
title_text = _("Portrait mosaic mode"),
width_factor = 0.6,
left_text = _("Columns"),
left_value = nb_cols,
left_min = 2,
left_max = 8,
left_default = 3,
left_precision = "%01d",
right_text = _("Rows"),
right_value = nb_rows,
right_min = 2,
right_max = 8,
right_default = 3,
right_precision = "%01d",
keep_shown_on_apply = true,
callback = function(left_value, right_value)
fc.nb_cols_portrait = left_value
fc.nb_rows_portrait = right_value
if fc.display_mode_type == "mosaic" and fc.portrait_mode then
fc.no_refresh_covers = true
fc:updateItems()
end
end,
close_callback = function()
if fc.nb_cols_portrait ~= nb_cols or fc.nb_rows_portrait ~= nb_rows then
BookInfoManager:saveSetting("nb_cols_portrait", fc.nb_cols_portrait)
BookInfoManager:saveSetting("nb_rows_portrait", fc.nb_rows_portrait)
FileChooser.nb_cols_portrait = fc.nb_cols_portrait
FileChooser.nb_rows_portrait = fc.nb_rows_portrait
if fc.display_mode_type == "mosaic" and fc.portrait_mode then
fc.no_refresh_covers = nil
fc:updateItems()
end
end
end,
}
UIManager:show(widget)
end,
},
{
text_func = function()
local fc = self.ui.file_chooser
return T(_("Items per page in landscape mosaic mode: %1 × %2"), fc.nb_cols_landscape, fc.nb_rows_landscape)
end,
callback = function()
local fc = self.ui.file_chooser
local nb_cols = fc.nb_cols_landscape
local nb_rows = fc.nb_rows_landscape
local DoubleSpinWidget = require("/ui/widget/doublespinwidget")
local widget = DoubleSpinWidget:new{
title_text = _("Landscape mosaic mode"),
width_factor = 0.6,
left_text = _("Columns"),
left_value = nb_cols,
left_min = 2,
left_max = 8,
left_default = 4,
left_precision = "%01d",
right_text = _("Rows"),
right_value = nb_rows,
right_min = 2,
right_max = 8,
right_default = 2,
right_precision = "%01d",
keep_shown_on_apply = true,
callback = function(left_value, right_value)
fc.nb_cols_landscape = left_value
fc.nb_rows_landscape = right_value
if fc.display_mode_type == "mosaic" and not fc.portrait_mode then
fc.no_refresh_covers = true
fc:updateItems()
end
end,
close_callback = function()
if fc.nb_cols_landscape ~= nb_cols or fc.nb_rows_landscape ~= nb_rows then
BookInfoManager:saveSetting("nb_cols_landscape", fc.nb_cols_landscape)
BookInfoManager:saveSetting("nb_rows_landscape", fc.nb_rows_landscape)
FileChooser.nb_cols_landscape = fc.nb_cols_landscape
FileChooser.nb_rows_landscape = fc.nb_rows_landscape
if fc.display_mode_type == "mosaic" and not fc.portrait_mode then
fc.no_refresh_covers = nil
fc:updateItems()
end
end
end,
}
UIManager:show(widget)
end,
},
{
text_func = function()
local fc = self.ui.file_chooser
-- default files_per_page should be calculated by ListMenu on the first drawing,
-- use 10 if ListMenu has not been drawn yet
return T(_("Items per page in portrait list mode: %1"), fc.files_per_page or 10)
end,
callback = function()
local fc = self.ui.file_chooser
local files_per_page = fc.files_per_page or 10
local SpinWidget = require("ui/widget/spinwidget")
-- "files_per_page" should have been saved with an adequate value
-- the first time Detailed list was shown. Fallback to a start
-- value of 10 if it hasn't.
local curr_items = BookInfoManager:getSetting("files_per_page") or 10
local items = SpinWidget:new{
value = curr_items,
local widget = SpinWidget:new{
title_text = _("Portrait list mode"),
value = files_per_page,
value_min = 4,
value_max = 20,
default_value = 10,
keep_shown_on_apply = true,
title_text = _("Items per page"),
callback = function(spin)
BookInfoManager:saveSetting("files_per_page", spin.value)
self.ui:onRefresh()
end
fc.files_per_page = spin.value
if fc.display_mode_type == "list" then
fc.no_refresh_covers = true
fc:updateItems()
end
end,
close_callback = function()
if fc.files_per_page ~= files_per_page then
BookInfoManager:saveSetting("files_per_page", fc.files_per_page)
FileChooser.files_per_page = fc.files_per_page
if fc.display_mode_type == "list" then
fc.no_refresh_covers = nil
fc:updateItems()
end
end
end,
}
UIManager:show(items)
UIManager:show(widget)
end,
separator = true,
},
{
text = _("Progress"),
sub_item_table = {
{
text = _("Show progress"),
checked_func = function() return
not BookInfoManager:getSetting("hide_page_info")
end,
text = _("Show progress in mosaic mode"),
checked_func = function() return BookInfoManager:getSetting("show_progress_in_mosaic") end,
callback = function()
BookInfoManager:toggleSetting("hide_page_info")
BookInfoManager:toggleSetting("show_progress_in_mosaic")
self:refreshFileManagerInstance()
end,
separator = true,
},
{
text = _("Show progress % in mosaic mode"),
checked_func = function() return BookInfoManager:getSetting("show_progress_in_mosaic") end,
text = _("Show progress in detailed list mode"),
checked_func = function() return not BookInfoManager:getSetting("hide_page_info") end,
callback = function()
BookInfoManager:toggleSetting("show_progress_in_mosaic")
BookInfoManager:toggleSetting("hide_page_info")
self:refreshFileManagerInstance()
end,
},
{
text = _("Show number of pages read instead of progress %"),
enabled_func = function() return not BookInfoManager:getSetting("hide_page_info") end,
checked_func = function() return BookInfoManager:getSetting("show_pages_read_as_progress") end,
callback = function()
BookInfoManager:toggleSetting("show_pages_read_as_progress")
@ -221,12 +335,12 @@ function CoverBrowser:addToMainMenu(menu_items)
},
{
text = _("Show number of pages left to read"),
enabled_func = function() return not BookInfoManager:getSetting("hide_page_info") end,
checked_func = function() return BookInfoManager:getSetting("show_pages_left_in_progress") end,
callback = function()
BookInfoManager:toggleSetting("show_pages_left_in_progress")
self:refreshFileManagerInstance()
end,
separator = true,
},
},
},
@ -302,7 +416,6 @@ function CoverBrowser:addToMainMenu(menu_items)
end,
},
},
separator = true
},
{
text = _("Show file properties"),
@ -313,6 +426,7 @@ function CoverBrowser:addToMainMenu(menu_items)
BookInfoManager:toggleSetting("hide_file_info")
self:refreshFileManagerInstance()
end,
separator = true,
},
{
text = _("Book info cache management"),
@ -391,6 +505,19 @@ function CoverBrowser:addToMainMenu(menu_items)
})
end
function CoverBrowser.initGrid(menu, display_mode)
if menu == nil then return end
if menu.nb_cols_portrait == nil then
menu.nb_cols_portrait = BookInfoManager:getSetting("nb_cols_portrait") or 3
menu.nb_rows_portrait = BookInfoManager:getSetting("nb_rows_portrait") or 3
menu.nb_cols_landscape = BookInfoManager:getSetting("nb_cols_landscape") or 4
menu.nb_rows_landscape = BookInfoManager:getSetting("nb_rows_landscape") or 2
-- initial List mode files_per_page will be calculated and saved by ListMenu on the first drawing
menu.files_per_page = BookInfoManager:getSetting("files_per_page")
end
menu.display_mode_type = display_mode and display_mode:gsub("_.*", "") -- "mosaic" or "list"
end
function CoverBrowser:refreshFileManagerInstance(cleanup, post_init)
local fm = FileManager.instance
if fm then
@ -433,6 +560,9 @@ function CoverBrowser:setupFileManagerDisplayMode(display_mode)
filemanager_display_mode = display_mode
logger.dbg("CoverBrowser: setting FileManager display mode to:", display_mode or "classic")
-- init Mosaic and List grid dimensions (in Classic mode used in the settings menu)
CoverBrowser.initGrid(FileChooser, display_mode)
if not init_done and not display_mode then
return -- starting in classic mode, nothing to patch
end
@ -459,8 +589,7 @@ function CoverBrowser:setupFileManagerDisplayMode(display_mode)
FileChooser.updateCache = CoverMenu.updateCache
FileChooser.updateItems = CoverMenu.updateItems
FileChooser.onCloseWidget = CoverMenu.onCloseWidget
if display_mode == "mosaic_image" or display_mode == "mosaic_text" then -- mosaic mode
if FileChooser.display_mode_type == "mosaic" then
-- Replace some other original methods with those from our MosaicMenu
local MosaicMenu = require("mosaicmenu")
FileChooser._recalculateDimen = MosaicMenu._recalculateDimen
@ -470,14 +599,7 @@ function CoverBrowser:setupFileManagerDisplayMode(display_mode)
FileChooser._do_hint_opened = true -- dogear at bottom
-- Don't have "../" centered in empty directories
FileChooser._do_center_partial_rows = false
-- One could override default 3x3 grid here (put that as settings ?)
-- FileChooser.nb_cols_portrait = 4
-- FileChooser.nb_rows_portrait = 4
-- FileChooser.nb_cols_landscape = 6
-- FileChooser.nb_rows_landscape = 3
elseif display_mode == "list_image_meta" or display_mode == "list_only_meta" or
display_mode == "list_image_filename" then -- list modes
elseif FileChooser.display_mode_type == "list" then
-- Replace some other original methods with those from our ListMenu
local ListMenu = require("listmenu")
FileChooser._recalculateDimen = ListMenu._recalculateDimen
@ -488,7 +610,6 @@ function CoverBrowser:setupFileManagerDisplayMode(display_mode)
FileChooser._do_hint_opened = true -- dogear at bottom
end
-- Replace this FileManager method with the one from CoverMenu
-- (but first, make the original method saved here as local available
-- to CoverMenu)
@ -505,7 +626,6 @@ function CoverBrowser:setupFileManagerDisplayMode(display_mode)
self:refreshFileManagerInstance(false, true)
end)
end
end
local function _FileManagerHistory_updateItemTable(self)
@ -529,7 +649,8 @@ local function _FileManagerHistory_updateItemTable(self)
hist_menu.onMenuHold_orig = hist_menu.onMenuHold
hist_menu.onMenuHold = CoverMenu.onHistoryMenuHold
if display_mode == "mosaic_image" or display_mode == "mosaic_text" then -- mosaic mode
CoverBrowser.initGrid(hist_menu, display_mode)
if hist_menu.display_mode_type == "mosaic" then
-- Replace some other original methods with those from our MosaicMenu
local MosaicMenu = require("mosaicmenu")
hist_menu._recalculateDimen = MosaicMenu._recalculateDimen
@ -538,8 +659,7 @@ local function _FileManagerHistory_updateItemTable(self)
hist_menu._do_cover_images = display_mode ~= "mosaic_text"
hist_menu._do_center_partial_rows = true -- nicer looking when few elements
elseif display_mode == "list_image_meta" or display_mode == "list_only_meta" or
display_mode == "list_image_filename" then -- list modes
elseif hist_menu.display_mode_type == "list" then
-- Replace some other original methods with those from our ListMenu
local ListMenu = require("listmenu")
hist_menu._recalculateDimen = ListMenu._recalculateDimen
@ -608,7 +728,8 @@ local function _FileManagerCollections_updateItemTable(self)
coll_menu.onMenuHold_orig = coll_menu.onMenuHold
coll_menu.onMenuHold = CoverMenu.onCollectionsMenuHold
if display_mode == "mosaic_image" or display_mode == "mosaic_text" then -- mosaic mode
CoverBrowser.initGrid(coll_menu, display_mode)
if coll_menu.display_mode_type == "mosaic" then
-- Replace some other original methods with those from our MosaicMenu
local MosaicMenu = require("mosaicmenu")
coll_menu._recalculateDimen = MosaicMenu._recalculateDimen
@ -617,8 +738,7 @@ local function _FileManagerCollections_updateItemTable(self)
coll_menu._do_cover_images = display_mode ~= "mosaic_text"
coll_menu._do_center_partial_rows = true -- nicer looking when few elements
elseif display_mode == "list_image_meta" or display_mode == "list_only_meta" or
display_mode == "list_image_filename" then -- list modes
elseif coll_menu.display_mode_type == "list" then
-- Replace some other original methods with those from our ListMenu
local ListMenu = require("listmenu")
coll_menu._recalculateDimen = ListMenu._recalculateDimen

@ -447,7 +447,6 @@ function MosaicMenuItem:update()
local max_img_w = dimen.w - 2*border_size
local max_img_h = dimen.h - 2*border_size
local cover_specs = {
sizetag = "M",
max_cover_w = max_img_w,
max_cover_h = max_img_h,
}
@ -538,22 +537,19 @@ function MosaicMenuItem:update()
end
local bookinfo = BookInfoManager:getBookInfo(self.filepath, self.do_cover_image)
if bookinfo and self.do_cover_image and not bookinfo.ignore_cover then
if bookinfo.cover_fetched then
if bookinfo.has_cover and bookinfo.cover_sizetag ~= "M" then
-- there is a cover, but it's a small one (made by ListMenuItem),
-- and it would be ugly if scaled up to MosaicMenuItem size:
-- do as if not found to force a new extraction with our size
if bookinfo.cover_bb then
bookinfo.cover_bb:free()
if bookinfo.has_cover and not self.menu.no_refresh_covers then
if BookInfoManager.isCachedCoverInvalid(bookinfo, cover_specs) then
-- there is a thumbnail, but it's smaller than is needed for new grid dimensions,
-- and it would be ugly if scaled up to the required size:
-- do as if not found to force a new extraction with our size
if bookinfo.cover_bb then
bookinfo.cover_bb:free()
end
bookinfo = nil
end
bookinfo = nil
-- Note: with the current size differences between FileManager
-- and the History windows, we'll get lower max_img_* in History.
-- So, when one get Items first generated by the other, it will
-- have to do some scaling. Hopefully, people most probably
-- browse a lot more files than have them in history, so
-- it's most probably History that will have to do some scaling.
end
-- if not has_cover, book has no cover, no need to try again
else
@ -595,7 +591,7 @@ function MosaicMenuItem:update()
if self.do_cover_image and bookinfo.has_cover and not bookinfo.ignore_cover then
cover_bb_used = true
-- Let ImageWidget do the scaling and give us a bb that fit
local scale_factor = math.min(max_img_w / bookinfo.cover_w, max_img_h / bookinfo.cover_h)
local _, _, scale_factor = BookInfoManager.getCachedCoverSize(bookinfo.cover_w, bookinfo.cover_h, max_img_w, max_img_h)
local image= ImageWidget:new{
image = bookinfo.cover_bb,
scale_factor = scale_factor,
@ -858,14 +854,13 @@ end
local MosaicMenu = {}
function MosaicMenu:_recalculateDimen()
local portrait_mode = Screen:getWidth() <= Screen:getHeight()
-- 3 x 3 grid by default if not initially provided (4 x 2 in landscape mode)
if portrait_mode then
self.nb_cols = self.nb_cols_portrait or 3
self.nb_rows = self.nb_rows_portrait or 3
self.portrait_mode = Screen:getWidth() <= Screen:getHeight()
if self.portrait_mode then
self.nb_cols = self.nb_cols_portrait
self.nb_rows = self.nb_rows_portrait
else
self.nb_cols = self.nb_cols_landscape or 4
self.nb_rows = self.nb_rows_landscape or 2
self.nb_cols = self.nb_cols_landscape
self.nb_rows = self.nb_rows_landscape
end
self.perpage = self.nb_rows * self.nb_cols
self.page_num = math.ceil(#self.item_table / self.perpage)

Loading…
Cancel
Save