display: Sort by date and/or reverse order for vsdlist menu.

This adds two config directives for sorting vsdlist (sd card file list)
on a LCD connected to the printer (dumb character display).

Add "sort_by_date: True" to a vsdlist menu config to have the files
sorted by date chronologically. If not present or "False" then files will
be sorted alphabetically just as before.

Add "sort_reverse: True" to a vsdlist menu config to have the files
sorted in reverse order (descending). If not present or "False" then the
files will be sorted in ascending order just as before.

By setting both "sort_by_date" and "sort_reverse" to "True" files will be
sorted in reverse chronological order (newest first).

Please note the file timestamp (date) is taken from the filesystem and some
filesystems may have broken timestamps on subsequent writes.

Signed-off-by: Dragos Galalae <gala 'underline' dragos 'at' yahoo 'dot' com>
This commit is contained in:
Dragos GALALAE 2024-11-29 00:04:13 +02:00 committed by Dragos GALALAE
parent 7f89668d6c
commit c3a5e952e2
3 changed files with 63 additions and 3 deletions

View file

@ -4549,6 +4549,21 @@ information on menu attributes available during template rendering.
# Position where an item needs to be inserted in list. By default
# the item is added at the end.
#[menu some_vsdlist]
#type: vsdlist
#name:
#enable:
# See above for a description of these parameters.
#sort_by_date: False
# Sort files using thier creation date from the filesystem.
# Default: (False) sort files using their names.
#sort_reverse: False
# Reverse order of sorting.
# When sort_by_date is True, files will be sorted from new to old.
# When sort_by_date is False, files will be sorted in alphabetical
# descending order, else they will be sorted in alphabetical
# ascending order.
#[menu some_list]
#type: list
#name:

View file

@ -661,18 +661,32 @@ class MenuList(MenuContainer):
class MenuVSDList(MenuList):
def __init__(self, manager, config, **kwargs):
self._sort_reverse = kwargs.get('sort_reverse', False)
self._sort_by_date = kwargs.get('sort_by_date', False)
super(MenuVSDList, self).__init__(manager, config, **kwargs)
try:
self._sort_reverse = config.getboolean('sort_reverse',
self._sort_reverse)
except config.error:
logging.debug("Failed to get sort_reverse from config file")
pass
try:
self._sort_by_date = config.getboolean('sort_by_date',
self._sort_by_date)
except config.error:
logging.debug("Failed to get sort_by_date from config file")
pass
def _populate(self):
super(MenuVSDList, self)._populate()
sdcard = self.manager.printer.lookup_object('virtual_sdcard', None)
if sdcard is not None:
files = sdcard.get_file_list()
files = sdcard.get_file_list(sortByDate=self._sort_by_date,
sortReverse=self._sort_reverse)
for fname, fsize in files:
self.insert_item(self.manager.menuitem_from(
'command', name=repr(fname), gcode='M23 /%s' % str(fname)))
menu_items = {
'disabled': MenuDisabled,
'command': MenuCommand,

View file

@ -64,7 +64,8 @@ class VirtualSD:
if self.work_timer is None:
return False, ""
return True, "sd_pos=%d" % (self.file_position,)
def get_file_list(self, check_subdirs=False):
def get_file_list(self, check_subdirs=False,
sortByDate=False, sortReverse=False):
if check_subdirs:
flist = []
for root, dirs, files in os.walk(
@ -77,11 +78,41 @@ class VirtualSD:
r_path = full_path[len(self.sdcard_dirname) + 1:]
size = os.path.getsize(full_path)
flist.append((r_path, size))
if sortByDate:
if sortReverse:
return sorted(flist,
key=lambda f: os.path.getmtime(f[0],
reverse=True))
return sorted(flist, key=lambda f: os.path.getmtime(f[0]))
if sortReverse:
return sorted(flist, key=lambda f: f[0].lower(), reverse=True)
return sorted(flist, key=lambda f: f[0].lower())
else:
dname = self.sdcard_dirname
try:
filenames = os.listdir(self.sdcard_dirname)
if sortByDate:
if sortReverse:
return [(fname,
os.path.getsize(os.path.join(dname, fname)))
for fname in sorted(filenames,
key=lambda f: os.path.getmtime(
os.path.join(dname, f)),
reverse=True)
if not fname.startswith('.')
and os.path.isfile((os.path.join(dname, fname)))]
return [(fname, os.path.getsize(os.path.join(dname, fname)))
for fname in sorted(filenames,
key=lambda f: os.path.getmtime(
os.path.join(dname, f)))
if not fname.startswith('.')
and os.path.isfile((os.path.join(dname, fname)))]
if sortReverse:
return [(fname, os.path.getsize(os.path.join(dname, fname)))
for fname in sorted(filenames, key=str.lower,
reverse=True)
if not fname.startswith('.')
and os.path.isfile((os.path.join(dname, fname)))]
return [(fname, os.path.getsize(os.path.join(dname, fname)))
for fname in sorted(filenames, key=str.lower)
if not fname.startswith('.')