Refactor FileManager collation for easier patching

reviewable/pr11211/r1
Wim de With 5 months ago committed by Frans de Jonge
parent 3c63a5d8a8
commit 98d92d37ab

@ -124,7 +124,7 @@ function FileSearcher:getList()
["/proc"] = true,
["/sys"] = true,
}
local collate = G_reader_settings:readSetting("collate")
local collate = FileChooser:getCollate()
local search_string = self.search_string
if search_string ~= "*" then -- one * to show all files
if not self.case_sensitive then

@ -443,12 +443,12 @@ To:
self.menu_items.sort_mixed = {
text = _("Folders and files mixed"),
enabled_func = function()
local collate = G_reader_settings:readSetting("collate")
return not FileChooser.isCollateNotForMixed(collate)
local collate = FileChooser:getCollate()
return collate.can_collate_mixed
end,
checked_func = function()
local collate = G_reader_settings:readSetting("collate")
return not FileChooser.isCollateNotForMixed(collate) and G_reader_settings:isTrue("collate_mixed")
local collate = FileChooser:getCollate()
return collate.can_collate_mixed and G_reader_settings:isTrue("collate_mixed")
end,
callback = function()
G_reader_settings:flipNilOrFalse("collate_mixed")
@ -851,37 +851,27 @@ dbg:guard(FileManagerMenu, 'setUpdateItemTable',
end)
function FileManagerMenu:getSortingMenuTable()
local collates = {
{ _("name"), "strcoll" },
{ _("name (natural sorting)"), "natural" },
{ _("last read date"), "access" },
{ _("date modified"), "date" },
{ _("size"), "size" },
{ _("type"), "type" },
{ _("percent unopened first"), "percent_unopened_first" },
{ _("percent unopened last"), "percent_unopened_last" },
}
local sub_item_table = {}
for i, v in ipairs(collates) do
for k, v in pairs(self.ui.file_chooser.collates) do
table.insert(sub_item_table, {
text = v[1],
text = v.text,
menu_order = v.menu_order,
checked_func = function()
return v[2] == G_reader_settings:readSetting("collate", "strcoll")
local _, id = self.ui.file_chooser:getCollate()
return k == id
end,
callback = function()
G_reader_settings:saveSetting("collate", v[2])
G_reader_settings:saveSetting("collate", k)
self.ui.file_chooser:clearSortingCache()
self.ui.file_chooser:refreshPath()
end,
})
end
table.sort(sub_item_table, function(a, b) return a.menu_order < b.menu_order end)
return {
text_func = function()
local collate = G_reader_settings:readSetting("collate")
for i, v in ipairs(collates) do
if v[2] == collate then
return T(_("Sort by: %1"), v[1])
end
end
local collate = self.ui.file_chooser:getCollate()
return T(_("Sort by: %1"), collate.text)
end,
sub_item_table = sub_item_table,
}

@ -75,6 +75,141 @@ local FileChooser = Menu:extend{
},
path_items = nil, -- hash, store last browsed location (item index) for each path
goto_letter = true,
collates = {
strcoll = {
text = _("name"),
menu_order = 10,
can_collate_mixed = true,
init_sort_func = function(cache)
return function(a, b)
return ffiUtil.strcoll(a.text, b.text)
end, cache
end,
},
natural = {
text = _("name (natural sorting)"),
menu_order = 20,
can_collate_mixed = true,
init_sort_func = function(cache)
local natsort
natsort, cache = sort.natsort_cmp(cache)
return function(a, b)
return natsort(a.text, b.text)
end, cache
end
},
access = {
text = _("last read date"),
menu_order = 30,
can_collate_mixed = true,
init_sort_func = function(cache)
return function(a, b)
return a.attr.access > b.attr.access
end, cache
end,
mandatory_func = function(item)
return datetime.secondsToDateTime(item.attr.access)
end,
},
date = {
text = _("date modified"),
menu_order = 40,
can_collate_mixed = true,
init_sort_func = function(cache)
return function(a, b)
return a.attr.modification > b.attr.modification
end, cache
end,
mandatory_func = function(item)
return datetime.secondsToDateTime(item.attr.modification)
end,
},
size = {
text = _("size"),
menu_order = 50,
can_collate_mixed = false,
init_sort_func = function(cache)
return function(a, b)
return a.attr.size < b.attr.size
end, cache
end,
},
type = {
text = _("type"),
menu_order = 60,
can_collate_mixed = false,
init_sort_func = function(cache)
return function(a, b)
if (a.suffix or b.suffix) and a.suffix ~= b.suffix then
return ffiUtil.strcoll(a.suffix, b.suffix)
end
return ffiUtil.strcoll(a.text, b.text)
end, cache
end,
item_func = function(item)
item.suffix = util.getFileNameSuffix(item.text)
return item
end,
},
percent_unopened_first = {
text = _("percent - unopened first"),
menu_order = 70,
can_collate_mixed = false,
init_sort_func = function(cache)
return function(a, b)
if a.opened == b.opened then
if a.opened then
return a.percent_finished < b.percent_finished
end
return ffiUtil.strcoll(a.text, b.text)
end
return b.opened
end, cache
end,
item_func = function(item)
local percent_finished
item.opened = DocSettings:hasSidecarFile(item.fullpath)
if item.opened then
local doc_settings = DocSettings:open(item.fullpath)
percent_finished = doc_settings:readSetting("percent_finished")
end
item.percent_finished = percent_finished or 0
return item
end,
mandatory_func = function(item)
return item.opened and string.format("%d %%", 100 * item.percent_finished) or ""
end,
},
percent_unopened_last = {
text = _("percent - unopened last"),
menu_order = 80,
can_collate_mixed = false,
init_sort_func = function(cache)
return function(a, b)
if a.opened == b.opened then
if a.opened then
return a.percent_finished < b.percent_finished
end
return ffiUtil.strcoll(a.text, b.text)
end
return a.opened
end, cache
end,
item_func = function(item)
local percent_finished
item.opened = DocSettings:hasSidecarFile(item.fullpath)
if item.opened then
local doc_settings = DocSettings:open(item.fullpath)
percent_finished = doc_settings:readSetting("percent_finished")
end
item.percent_finished = percent_finished or 0
return item
end,
mandatory_func = function(item)
return item.opened and string.format("%d %%", 100 * item.percent_finished) or ""
end,
},
},
}
-- Cache of content we knew of for directories that are not readable
@ -163,70 +298,31 @@ function FileChooser.getListItem(f, filename, attributes, collate)
if G_reader_settings:readSetting("show_file_in_bold") ~= false then
item.opened = DocSettings:hasSidecarFile(filename)
end
if collate == "type" then
item.suffix = util.getFileNameSuffix(f)
elseif collate == "percent_unopened_first" or collate == "percent_unopened_last" then
local percent_finished
item.opened = DocSettings:hasSidecarFile(filename)
if item.opened then
local doc_settings = DocSettings:open(filename)
percent_finished = doc_settings:readSetting("percent_finished")
end
item.percent_finished = percent_finished or 0
if collate.item_func ~= nil then
item = collate.item_func(item)
end
end
return item
end
function FileChooser:getCollate()
local collate_id = G_reader_settings:readSetting("collate", "strcoll")
local collate = self.collates[collate_id]
if collate ~= nil then
return collate, collate_id
else
G_reader_settings:saveSetting("collate", "strcoll")
return self.collates.strcoll, "strcoll"
end
end
function FileChooser:getSortingFunction(collate, reverse_collate)
local sorting
if collate == "strcoll" then
sorting = function(a, b)
return ffiUtil.strcoll(a.text, b.text)
end
elseif collate == "natural" then
local natsort
-- Only keep the cache if we're an *instance* of FileChooser
if self ~= FileChooser then
natsort, self.natsort_cache = sort.natsort_cmp(self.natsort_cache)
else
natsort = sort.natsort_cmp()
end
sorting = function(a, b)
return natsort(a.text, b.text)
end
elseif collate == "access" then
sorting = function(a, b)
return a.attr.access > b.attr.access
end
elseif collate == "date" then
sorting = function(a, b)
return a.attr.modification > b.attr.modification
end
elseif collate == "size" then
sorting = function(a, b)
return a.attr.size < b.attr.size
end
elseif collate == "type" then
sorting = function(a, b)
if (a.suffix or b.suffix) and a.suffix ~= b.suffix then
return ffiUtil.strcoll(a.suffix, b.suffix)
end
return ffiUtil.strcoll(a.text, b.text)
end
else -- collate == "percent_unopened_first" or collate == "percent_unopened_last"
sorting = function(a, b)
if a.opened == b.opened then
if a.opened then
return a.percent_finished < b.percent_finished
end
return ffiUtil.strcoll(a.text, b.text)
end
if collate == "percent_unopened_first" then
return b.opened
end
return a.opened
end
-- Only keep the cache if we're an *instance* of FileChooser
if self ~= FileChooser then
sorting, self.sort_cache = collate.init_sort_func(self.sort_cache)
else
sorting = collate.init_sort_func()
end
if reverse_collate then
@ -237,27 +333,25 @@ function FileChooser:getSortingFunction(collate, reverse_collate)
return sorting
end
function FileChooser:clearSortingCache()
self.sort_cache = nil
end
function FileChooser:genItemTableFromPath(path)
local collate = G_reader_settings:readSetting("collate", "strcoll")
local collate = self:getCollate()
local dirs, files = self:getList(path, collate)
return self:genItemTable(dirs, files, path)
end
function FileChooser.isCollateNotForMixed(collate)
return collate == "size" or collate == "type"
or collate == "percent_unopened_first" or collate == "percent_unopened_last"
end
function FileChooser:genItemTable(dirs, files, path)
local collate = G_reader_settings:readSetting("collate")
local collate = self:getCollate()
local collate_mixed = G_reader_settings:isTrue("collate_mixed")
local reverse_collate = G_reader_settings:isTrue("reverse_collate")
local sorting = self:getSortingFunction(collate, reverse_collate)
local collate_not_for_mixed = self.isCollateNotForMixed(collate)
if collate_not_for_mixed or not collate_mixed then
if not collate.can_collate_mixed or not collate_mixed then
table.sort(files, sorting)
if collate_not_for_mixed then -- keep folders sorted by name not reversed
sorting = self:getSortingFunction("strcoll")
if not collate.can_collate_mixed then -- keep folders sorted by name not reversed
sorting = self:getSortingFunction(self.collates.strcoll)
end
table.sort(dirs, sorting)
end
@ -310,7 +404,7 @@ function FileChooser:genItemTable(dirs, files, path)
table.insert(item_table, file_item)
end
if not collate_not_for_mixed and collate_mixed then
if collate.can_collate_mixed and collate_mixed then
table.sort(item_table, sorting)
end
@ -347,13 +441,8 @@ end
function FileChooser:getMenuItemMandatory(item, collate)
local text
if collate then -- file
-- display the sorting parameter in mandatory
if collate == "access" then
text = datetime.secondsToDateTime(item.attr.access)
elseif collate == "date" then
text = datetime.secondsToDateTime(item.attr.modification)
elseif collate == "percent_unopened_first" or collate == "percent_unopened_last" then
text = item.opened and string.format("%d %%", 100 * item.percent_finished) or ""
if collate.mandatory_func ~= nil then
text = collate.mandatory_func(item)
else
text = util.getFriendlySize(item.attr.size or 0)
end

Loading…
Cancel
Save