From cea0df8658fce5c4072e520a46e67e79e56ee89e Mon Sep 17 00:00:00 2001 From: Jordan Ruthe Date: Thu, 18 Feb 2021 23:56:25 -0500 Subject: [PATCH] print: Add support for directories --- docs/changelog.md | 6 + panels/print.py | 368 ++++++++++++++++++++++++++++++++-------------- 2 files changed, 260 insertions(+), 114 deletions(-) diff --git a/docs/changelog.md b/docs/changelog.md index 7382d0d8..54a2cb30 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,5 +1,11 @@ ## Changelog +#### 2021 02 18 +* Add directory support to print panel + +#### 2021 02 17 +* Fix issues with word wrapping in different languages + #### 2021 02 15 * Added action bar to left side (moves the Back, E-stop, and Home buttons) * Added wifi manager. Will show current wifi details in network panel. Will allow switching networks in the future. diff --git a/panels/print.py b/panels/print.py index 71524478..e6d8d791 100644 --- a/panels/print.py +++ b/panels/print.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- import gi +import json import humanize import logging @@ -16,8 +17,12 @@ def create_panel(*args): return PrintPanel(*args) class PrintPanel(ScreenPanel): + cur_directory = "gcodes" + dir_panels = {} + def initialize(self, panel_name): _ = self.lang.gettext + self.labels['directories'] = {} self.labels['files'] = {} self.sort_items = { "name": _("Name"), @@ -53,94 +58,211 @@ class PrintPanel(ScreenPanel): sbox.set_hexpand(True) sbox.set_vexpand(False) + pbox = Gtk.Box(spacing=0) + pbox.set_hexpand(True) + pbox.set_vexpand(False) + self.labels['path'] = Gtk.Label(" /") + pbox.add(self.labels['path']) + self.labels['path_box'] = pbox + box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0) box.set_vexpand(True) box.pack_start(sbox, False, False, 0) + box.pack_start(pbox, False, False, 0) box.pack_start(scroll, True, True, 0) - self.labels['filelist'] = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) - self.labels['filelist'].set_vexpand(True) - - self.labels['filelist'] = Gtk.Grid() + self.dir_panels['gcodes'] = Gtk.Grid() self.files = {} + self.directories = {} GLib.idle_add(self.reload_files) - scroll.add(self.labels['filelist']) + scroll.add(self.dir_panels['gcodes']) + self.scroll = scroll + self.control['back'].disconnect_by_func(self._screen._menu_go_back) + self.control['back'].connect("clicked", self.back) self.content.add(box) self._screen.files.add_file_callback(self._callback) return - def add_file(self, filename, show=True): - fileinfo = self._screen.files.get_file_info(filename) - if fileinfo == None: - return + def activate(self): + if self.cur_directory != "gcodes": + self.change_dir(None, "gcodes") - frame = Gtk.Frame() - frame.set_property("shadow-type",Gtk.ShadowType.NONE) - frame.get_style_context().add_class("frame-item") + def add_directory(self, directory, show=True): + parent_dir = '/'.join(directory.split('/')[:-1]) + if directory not in self.filelist: + self.filelist[directory] = {'directories':[],'files':[],'modified': 0} + self.filelist[parent_dir]['directories'].append(directory) + if directory not in self.labels['directories']: + frame = Gtk.Frame() + frame.set_property("shadow-type",Gtk.ShadowType.NONE) + frame.get_style_context().add_class("frame-item") - name = Gtk.Label() - #n = 50 - #name.set_markup("%s" % ("\n".join([filename[i:i+n] for i in range(0, len(filename), n)]))) - name.set_markup("%s" % (filename)) - name.set_hexpand(True) - name.set_halign(Gtk.Align.START) - name.set_line_wrap(True) - name.set_line_wrap_mode(Pango.WrapMode.WORD_CHAR) + name = Gtk.Label() + name.set_markup("%s" % (directory.split("/")[-1])) + name.set_hexpand(True) + name.set_halign(Gtk.Align.START) + name.set_line_wrap(True) + name.set_line_wrap_mode(Pango.WrapMode.WORD_CHAR) - info = Gtk.Label("Uploaded: blah - Size: blah") - info.set_halign(Gtk.Align.START) - info.set_markup(self.get_file_info_str(filename)) - labels = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) - labels.add(name) - labels.add(info) - labels.set_vexpand(True) - labels.set_valign(Gtk.Align.CENTER) - labels.set_halign(Gtk.Align.START) + info = Gtk.Label() + info.set_halign(Gtk.Align.START) - actions = self._gtk.ButtonImage("print",None,"color3") - actions.connect("clicked", self.confirm_print, filename) - actions.set_hexpand(False) - actions.set_halign(Gtk.Align.END) + labels = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) + labels.add(name) + labels.add(info) + labels.set_vexpand(True) + labels.set_valign(Gtk.Align.CENTER) + labels.set_halign(Gtk.Align.START) - file = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=5) - file.set_hexpand(True) - file.set_vexpand(False) + actions = self._gtk.ButtonImage("open",None,"color3") + actions.connect("clicked", self.change_dir, directory) + actions.set_hexpand(False) + actions.set_halign(Gtk.Align.END) - icon = self._gtk.Image("file.svg", False, 1.6, 1.6) - pixbuf = self.get_file_image(filename) - if pixbuf != None: - icon.set_from_pixbuf(pixbuf) + file = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=5) + file.set_hexpand(True) + file.set_vexpand(False) - file.add(icon) - file.add(labels) - file.add(actions) - frame.add(file) + icon = self._gtk.Image("folder.svg", False, 1, 1) - self.files[filename] = frame + file.add(icon) + file.add(labels) + file.add(actions) + frame.add(file) + + self.directories[directory] = frame + + self.labels['directories'][directory] = { + "icon": icon, + "info": info, + "name": name + } + + self.dir_panels[directory] = Gtk.Grid() reverse = False if self.sort_current[1] == 0 else True if self.sort_current[0] == "date": - files = sorted(self.files, reverse=reverse, - key=lambda item: self._screen.files.get_file_info(item)['modified']) + dirs = sorted(self.filelist[parent_dir]['directories'], reverse=reverse, + key=lambda item: self.filelist[item]['modified']) else: - files = sorted(self.files, reverse=reverse) - pos = files.index(filename) + dirs = sorted(self.filelist[parent_dir]['directories'], reverse=reverse) + pos = dirs.index(directory) - self.labels['files'][filename] = { - "icon": icon, - "info": info, - "name": name - } - - self.labels['filelist'].insert_row(pos) - self.labels['filelist'].attach(self.files[filename], 0, pos, 1, 1) + self.dir_panels[parent_dir].insert_row(pos) + self.dir_panels[parent_dir].attach(self.directories[directory], 0, pos, 1, 1) if show == True: - self.labels['filelist'].show_all() + self.dir_panels[parent_dir].show_all() + + def add_file(self, filepath, show=True): + _ = self.lang.gettext + + fileinfo = self._screen.files.get_file_info(filepath) + if fileinfo == None: + return + + dir = ("gcodes/%s" % filepath).split('/')[:-1] + directory = '/'.join(dir) + filename = filepath.split('/')[-1] + for i in range(1, len(dir)): + curdir = "/".join(dir[0:i]) + newdir = "/".join(dir[0:i+1]) + if newdir not in self.filelist[curdir]['directories']: + self.add_directory(newdir) + + if filename not in self.filelist[directory]['files']: + for i in range(1, len(dir)): + curdir = "/".join(dir[0:i+1]) + if curdir != "gcodes" and fileinfo['modified'] > self.filelist[curdir]['modified']: + self.filelist[curdir]['modified'] = fileinfo['modified'] + self.labels['directories'][curdir]['info'].set_markup("%s: %s" % + (_("Modified"), datetime.fromtimestamp(fileinfo['modified']).strftime("%Y-%m-%d %H:%M"))) + self.filelist[directory]['files'].append(filename) + + if filepath not in self.files: + frame = Gtk.Frame() + frame.set_property("shadow-type",Gtk.ShadowType.NONE) + frame.get_style_context().add_class("frame-item") + + name = Gtk.Label() + name.set_markup("%s" % (filename)) + name.set_hexpand(True) + name.set_halign(Gtk.Align.START) + name.set_line_wrap(True) + name.set_line_wrap_mode(Pango.WrapMode.WORD_CHAR) + + info = Gtk.Label() + info.set_halign(Gtk.Align.START) + info.set_markup(self.get_file_info_str(filepath)) + labels = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) + labels.add(name) + labels.add(info) + labels.set_vexpand(True) + labels.set_valign(Gtk.Align.CENTER) + labels.set_halign(Gtk.Align.START) + + actions = self._gtk.ButtonImage("print",None,"color3") + actions.connect("clicked", self.confirm_print, filepath) + actions.set_hexpand(False) + actions.set_halign(Gtk.Align.END) + + file = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=5) + file.set_hexpand(True) + file.set_vexpand(False) + + icon = self._gtk.Image("file.svg", False, 1.6, 1.6) + pixbuf = self.get_file_image(filepath) + if pixbuf != None: + icon.set_from_pixbuf(pixbuf) + + file.add(icon) + file.add(labels) + file.add(actions) + frame.add(file) + + self.files[filepath] = frame + self.labels['files'][filepath] = { + "icon": icon, + "info": info, + "name": name + } + + reverse = False if self.sort_current[1] == 0 else True + if self.sort_current[0] == "date": + files = sorted(self.filelist[directory]['files'], reverse=reverse, + key=lambda item: self._screen.files.get_file_info(("%s/%s" %(directory,item))[7:])['modified']) + else: + files = sorted(self.filelist[directory]['files'], reverse=reverse) + pos = files.index(filename) + pos += len(self.filelist[directory]['directories']) + + self.dir_panels[directory].insert_row(pos) + self.dir_panels[directory].attach(self.files[filepath], 0, pos, 1, 1) + if show == True: + self.dir_panels[directory].show_all() + + def back(self, widget): + if len(self.cur_directory.split('/')) > 1: + self.change_dir(None, '/'.join(self.cur_directory.split('/')[:-1])) + else: + self._screen._menu_go_back() + + def change_dir(self, widget, directory): + if directory not in self.dir_panels: + return + logger.debug("Changing dir to %s" % directory) + + for child in self.scroll.get_children(): + self.scroll.remove(child) + self.cur_directory = directory + self.labels['path'].set_text(" /%s" % self.cur_directory[7:]) + + self.scroll.add(self.dir_panels[directory]) + self.content.show_all() def change_sort(self, widget, key): if self.sort_current[0] == key: @@ -156,6 +278,71 @@ class PrintPanel(ScreenPanel): GLib.idle_add(self.reload_files) + def confirm_print(self, widget, filename): + _ = self.lang.gettext + buttons = [ + {"name":_("Print"), "response": Gtk.ResponseType.OK}, + {"name":_("Cancel"),"response": Gtk.ResponseType.CANCEL} + ] + + label = Gtk.Label() + label.set_markup("%s %s%s" % (_("Are you sure you want to print"), filename, _("?"))) + label.set_hexpand(True) + label.set_halign(Gtk.Align.CENTER) + label.set_line_wrap(True) + label.set_line_wrap_mode(Pango.WrapMode.WORD_CHAR) + + grid = Gtk.Grid() + grid.add(label) + grid.set_size_request(self._screen.width - 60, -1) + + pixbuf = self.get_file_image(filename, 8, 3.2) + if pixbuf != None: + image = Gtk.Image.new_from_pixbuf(pixbuf) + grid.attach_next_to(image, label, Gtk.PositionType.BOTTOM, 1, 3) + + #table.attach(label, 0, 1, 0, 1, Gtk.AttachOptions.SHRINK | Gtk.AttachOptions.FILL) + grid.set_vexpand(True) + grid.set_halign(Gtk.Align.CENTER) + grid.set_valign(Gtk.Align.CENTER) + + dialog = self._gtk.Dialog(self._screen, buttons, grid, self.confirm_print_response, filename) + + def confirm_print_response(self, widget, response_id, filename): + widget.destroy() + + if response_id == Gtk.ResponseType.CANCEL: + return + + logging.info("Starting print: %s" % (filename)) + self._screen._ws.klippy.print_start(filename) + + def delete_file(self, filename): + dir_parts = ("gcodes/%s" % filename).split('/')[:-1] + directory = '/'.join(dir_parts) + self.filelist[directory]["files"].pop(self.filelist[directory]["files"].index(filename.split('/')[-1])) + i = len(dir_parts) + while i > 1: + cur_dir = '/'.join(dir_parts[0:i]) + if len(self.filelist[cur_dir]['directories']) > 0 or len(self.filelist[cur_dir]['files']) > 0: + break + par_dir = '/'.join(cur_dir.split('/')[:-1]) + + if self.cur_directory == cur_dir: + self.change_dir(None, par_dir) + + del self.filelist[cur_dir] + self.filelist[par_dir]['directories'].pop(self.filelist[par_dir]['directories'].index(cur_dir)) + self.dir_panels[par_dir].remove(self.directories[cur_dir]) + del self.directories[cur_dir] + del self.labels['directories'][cur_dir] + self.dir_panels[par_dir].show_all() + i -= 1 + + self.dir_panels[directory].remove(self.files[filename]) + self.dir_panels[directory].show_all() + self.files.pop(filename) + def get_file_info_str(self, filename): _ = self.lang.gettext @@ -196,6 +383,15 @@ class PrintPanel(ScreenPanel): return print_str return "Unavailable" + def reload_files(self, widget=None): + self.filelist = {'gcodes':{'directories':[],'files':[]}} + for dirpan in self.dir_panels: + for child in self.dir_panels[dirpan].get_children(): + self.dir_panels[dirpan].remove(child) + + for file in self._screen.files.get_file_list(): + self.add_file(file) + def update_file(self, filename): if filename not in self.labels['files']: return @@ -208,23 +404,6 @@ class PrintPanel(ScreenPanel): if pixbuf != None: self.labels['files'][filename]['icon'].set_from_pixbuf(pixbuf) - def delete_file(self, filename): - files = sorted(self.files) - pos = files.index(filename) - self.labels['filelist'].remove_row(pos) - self.labels['filelist'].show_all() - self.files.pop(filename) - - def reload_files(self, widget=None): - for child in self.labels['filelist'].get_children(): - self.labels['filelist'].remove(child) - self.labels['filelist'].show_all() - - for file in self._screen.files.get_file_list(): - self.add_file(file, False) - - self.labels['filelist'].show_all() - def _callback(self, newfiles, deletedfiles, updatedfiles=[]): logger.debug("newfiles: %s", newfiles) for file in newfiles: @@ -235,42 +414,3 @@ class PrintPanel(ScreenPanel): logger.debug("updatefiles: %s", updatedfiles) for file in updatedfiles: self.update_file(file) - - def confirm_print(self, widget, filename): - _ = self.lang.gettext - buttons = [ - {"name":_("Print"), "response": Gtk.ResponseType.OK}, - {"name":_("Cancel"),"response": Gtk.ResponseType.CANCEL} - ] - - label = Gtk.Label() - label.set_markup("%s %s%s" % (_("Are you sure you want to print"), filename, _("?"))) - label.set_hexpand(True) - label.set_halign(Gtk.Align.CENTER) - label.set_line_wrap(True) - label.set_line_wrap_mode(Pango.WrapMode.WORD_CHAR) - - grid = Gtk.Grid() - grid.add(label) - grid.set_size_request(self._screen.width - 60, -1) - - pixbuf = self.get_file_image(filename, 8, 3.2) - if pixbuf != None: - image = Gtk.Image.new_from_pixbuf(pixbuf) - grid.attach_next_to(image, label, Gtk.PositionType.BOTTOM, 1, 3) - - #table.attach(label, 0, 1, 0, 1, Gtk.AttachOptions.SHRINK | Gtk.AttachOptions.FILL) - grid.set_vexpand(True) - grid.set_halign(Gtk.Align.CENTER) - grid.set_valign(Gtk.Align.CENTER) - - dialog = self._gtk.Dialog(self._screen, buttons, grid, self.confirm_print_response, filename) - - def confirm_print_response(self, widget, response_id, filename): - widget.destroy() - - if response_id == Gtk.ResponseType.CANCEL: - return - - logging.info("Starting print: %s" % (filename)) - self._screen._ws.klippy.print_start(filename)