From f297699396f86beb533cebdfcc5a49d50027fc84 Mon Sep 17 00:00:00 2001 From: Jordan Ruthe Date: Wed, 20 Jan 2021 22:06:48 -0500 Subject: [PATCH] job_status/settings: Allow different file estimation methods --- docs/changelog.md | 5 +++++ ks_includes/KlipperScreen.conf | 6 ++++++ ks_includes/config.py | 10 ++++++++- panels/job_status.py | 38 +++++++++++++++++++++++---------- panels/settings.py | 39 ++++++++++++++++++++++++++++------ styles/style.css | 22 +++++++++++++++++++ 6 files changed, 101 insertions(+), 19 deletions(-) diff --git a/docs/changelog.md b/docs/changelog.md index 815cdd98..58165d3e 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,5 +1,10 @@ ## Changelog +#### 2021 01 20 +* Add different time estimation methods to settings panel +* Job status panel will use time estimation method selected from settings panel +* Bugfixes to state tracking + #### 2021 01 10 * Added system reboot/shutdown buttons to systems panel. diff --git a/ks_includes/KlipperScreen.conf b/ks_includes/KlipperScreen.conf index 5a98db2c..9eb50ea7 100644 --- a/ks_includes/KlipperScreen.conf +++ b/ks_includes/KlipperScreen.conf @@ -179,6 +179,12 @@ name: {{ gettext('System') }} icon: info panel: system +[menu __print settings] +name: {{ gettext('Settings') }} +icon: settings +panel: settings + + [menu __splashscreen] name: {{ gettext('Menu') }} diff --git a/ks_includes/config.py b/ks_includes/config.py index 7bf2ba2a..ee11a272 100644 --- a/ks_includes/config.py +++ b/ks_includes/config.py @@ -25,7 +25,15 @@ class KlipperScreenConfig: self.configurable_options = [ {"invert_x": {"section": "main", "name": _("Invert X"), "type": "binary", "value": "False"}}, {"invert_y": {"section": "main", "name": _("Invert Y"), "type": "binary", "value": "False"}}, - {"invert_z": {"section": "main", "name": _("Invert Z"), "type": "binary", "value": "False"}} + {"invert_z": {"section": "main", "name": _("Invert Z"), "type": "binary", "value": "False"}}, + {"print_estimate_method": {"section": "main", "name": _("Estimated Time Method"), "type": "dropdown", + "value": "file","options":[ + {"name": _("File Estimation (default)"), "value": "file"}, + {"name": _("Duration Only"), "value": "duration"}, + {"name": _("Filament Used"), "value": "filament"}, + {"name": _("Slicer"), "value": "slicer"} + ]}} + #{"": {"section": "main", "name": _(""), "type": ""}} ] self.default_config_path = "%s/ks_includes/%s" % (os.getcwd(), self.configfile_name) diff --git a/panels/job_status.py b/panels/job_status.py index 92b5940b..891b6f79 100644 --- a/panels/job_status.py +++ b/panels/job_status.py @@ -24,6 +24,7 @@ class JobStatusPanel(ScreenPanel): _ = self.lang.gettext self.layout = Gtk.Layout() self.layout.set_size(self._screen.width, self._screen.height) + self.timeleft_type = "file" self.create_buttons() @@ -322,7 +323,7 @@ class JobStatusPanel(ScreenPanel): self.disable_button("pause","resume","cancel") self._screen._ws.klippy.print_cancel(self._response_callback) - def _response_callback(self, response, method, params, func, *args): + def _response_callback(self, response, method, params, func=None, *args): if func == "enable_button": self.enable_button(*args) @@ -435,18 +436,33 @@ class JobStatusPanel(ScreenPanel): self.progress = progress self.labels['darea'].queue_draw() - if ps['print_duration'] == 0: - time_left = self.file_metadata['estimated_time'] if "estimated_time" in self.file_metadata else 0 - else: - est_time = self.file_metadata['estimated_time'] if "estimated_time" in self.file_metadata else 0 - time_left = max( - est_time - ps['print_duration'] , - 0 #ps['print_duration'] / (vsd['progress'] if vsd['progress'] != 0 else 1) - ) - self.update_text("duration", str(self._gtk.formatTimeString(ps['print_duration']))) + + timeleft_type = self._config.get_config()['main'].get('print_estimate_method','file') + + if timeleft_type != self.timeleft_type: + if self.timeleft_type == "duration": + self.labels['it_box'].add(self.labels['est_time']) + elif timeleft_type == "duration": + self.labels['it_box'].remove(self.labels['est_time']) + self.timeleft_type = timeleft_type + + if timeleft_type in ['filament','file','slicer']: + duration = ps['print_duration'] + if timeleft_type == "filament": + estimated_filament = (self.file_metadata['filament_total'] if "filament_total" in self.file_metadata + else 1) + total_duration = duration / (ps['filament_used'] / estimated_filament) + elif timeleft_type == "file": + total_duration = duration / max(self.progress, 0.0001) + elif timeleft_type == "slicer": + total_duration = (self.file_metadata['estimated_time'] if "estimated_time" in self.file_metadata + else duration) + + time_left = max(total_duration - duration, 0) self.update_text("time_left", str(self._gtk.formatTimeString(time_left))) - self.update_progress() + + self.update_progress() if "pause_resume" in data and self.state != "complete": if self.state == "paused" and data['pause_resume']['is_paused'] == False: diff --git a/panels/settings.py b/panels/settings.py index 3ccf37b1..6d3efcf9 100644 --- a/panels/settings.py +++ b/panels/settings.py @@ -23,17 +23,17 @@ class SettingsPanel(ScreenPanel): self.labels['main_box'] = self.create_box('main') self.labels['macros_box'] = self.create_box('macros') - options = self._config.get_configurable_options() + options = self._config.get_configurable_options().copy() + options.append({"macros": { + "name": _("Displayed Macros"), + "type": "menu", + "menu": "macros"} + }) + for option in options: name = list(option)[0] self.add_option('main', self.settings, name, option[name]) - self.add_option('main', self.settings, "macros", { - "name": _("Displayed Macros"), - "type": "menu", - "menu": "macros" - }) - for macro in self._printer.get_config_section_list("gcode_macro "): macro = macro[12:] self.macros[macro] = { @@ -120,6 +120,19 @@ class SettingsPanel(ScreenPanel): switch.set_property("height-request", round(self._gtk.get_image_height()*1.25)) box.add(switch) dev.add(box) + elif option['type'] == "dropdown": + dropdown = Gtk.ComboBoxText() + i = 0 + for opt in option['options']: + dropdown.append(opt['value'], opt['name']) + if opt['value'] == self._config.get_config()[option['section']].get(opt_name, option['value']): + dropdown.set_active(i) + i += 1 + dropdown.connect("changed", self.on_dropdown_change, option['section'], opt_name) + #dropdown.props.relief = Gtk.ReliefStyle.NONE + dropdown.set_entry_text_column(0) + dev.add(dropdown) + logger.debug("Children: %s" % dropdown.get_children()) elif option['type'] == "menu": open = self._gtk.ButtonImage("open",None,"color3") open.connect("clicked", self.load_menu, option['menu']) @@ -128,12 +141,15 @@ class SettingsPanel(ScreenPanel): dev.add(open) frame.add(dev) + frame.show_all() opt_array[opt_name] = { + "name": option['name'], "row": frame } opts = sorted(opt_array) + opts = sorted(list(opt_array), key=lambda x: opt_array[x]['name']) pos = opts.index(opt_name) self.labels[boxname].insert_row(pos) @@ -162,6 +178,15 @@ class SettingsPanel(ScreenPanel): self.content.add(self.labels[self.menu[-1]]) self.content.show_all() + def on_dropdown_change(self, combo, section, option): + tree_iter = combo.get_active_iter() + if tree_iter is not None: + model = combo.get_model() + value = model[tree_iter][1] + logger.debug("[%s] %s changed to %s" % (section, option, value)) + self._config.set(section, option, value) + self._config.save_user_config_options() + def switch_config_option(self, switch, gparam, section, option): logger.debug("[%s] %s toggled %s" % (section, option, switch.get_active())) if section not in self._config.get_config().sections(): diff --git a/styles/style.css b/styles/style.css index 8896e896..0773599c 100644 --- a/styles/style.css +++ b/styles/style.css @@ -1,6 +1,7 @@ * { color: #fff; font-size: KS_FONT_SIZEpx; + -GtkComboBox-appears-as-list: 0; } window { @@ -50,6 +51,11 @@ button.file-list { margin: 0; } +combobox box button { + border: .05em solid #cccccc; + padding: .5em 1em; +} + entry { font-size: 1em; background-color: #20292F; @@ -66,6 +72,18 @@ label { color: white; } +menu { + background-color: #13181C; + border: .1em solid #cccccc; +} + +menuitem { + background-color: #13181C; + border: .1em solid #cccccc; + border-bottom: 0; + border-top: 0; +} + progress, trough { min-height: 2em; background-color: #404E57; @@ -97,6 +115,10 @@ trough { margin: .5em 1em; } +.popup { + background-color: #0000ff; +} + .dialog { border: .1em solid black; padding: 2.5em;