From c3a5e952e2dced4c6b63794cdb7472aa758483f2 Mon Sep 17 00:00:00 2001 From: Dragos GALALAE Date: Fri, 29 Nov 2024 00:04:13 +0200 Subject: [PATCH] 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 --- docs/Config_Reference.md | 15 +++++++++++++++ klippy/extras/display/menu.py | 18 ++++++++++++++++-- klippy/extras/virtual_sdcard.py | 33 ++++++++++++++++++++++++++++++++- 3 files changed, 63 insertions(+), 3 deletions(-) diff --git a/docs/Config_Reference.md b/docs/Config_Reference.md index 6a5a7582397d..9e3f71685726 100644 --- a/docs/Config_Reference.md +++ b/docs/Config_Reference.md @@ -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: diff --git a/klippy/extras/display/menu.py b/klippy/extras/display/menu.py index e7723a7e36b0..a1c2810ca7b2 100644 --- a/klippy/extras/display/menu.py +++ b/klippy/extras/display/menu.py @@ -661,18 +661,32 @@ def draw_container(self, nrows, eventtime): 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, diff --git a/klippy/extras/virtual_sdcard.py b/klippy/extras/virtual_sdcard.py index 6dc49e2f5c39..f2972700d6a7 100644 --- a/klippy/extras/virtual_sdcard.py +++ b/klippy/extras/virtual_sdcard.py @@ -64,7 +64,8 @@ def stats(self, eventtime): 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 @@ def get_file_list(self, check_subdirs=False): 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('.')