Squashed commit of the following: commit 02c7556cdadf8de1ef3c54d2831920927cadbe30 Merge: 6bfa42e0 991003e6 Author: zkk <1007518571@qq.com> Date: Tue Dec 31 15:07:54 2024 +0800 Merge commit '991003e6cbea335eca73d3783aa1837059614724' into release commit 991003e6cbea335eca73d3783aa1837059614724 Author: zkk <1007518571@qq.com> Date: Tue Dec 31 15:03:34 2024 +0800 优化完整 简体中文和繁体中文的翻译 commit 1a177e90d09b9b9949bff2a1e3c6b12173420620 Author: zkk <1007518571@qq.com> Date: Tue Dec 31 14:10:03 2024 +0800 优化排除对象的英文语法错误 commit e8d509cb6c2883b1fadb5ab9f9ca658e61849055 Author: zkk <1007518571@qq.com> Date: Fri Dec 27 16:40:52 2024 +0800 优化耗材检测显示内容 commit 1b7670485a918cb334119175777525f768e670be Author: zkk <1007518571@qq.com> Date: Fri Dec 27 14:56:25 2024 +0800 完善断料自动切头功能描述 commit ecc0c3dd16442497e56f5f8ab3a0c6be00bd180e Author: zkk <1007518571@qq.com> Date: Fri Dec 27 13:40:01 2024 +0800 实现弹窗翻译功能 commit bc6d60fa183af50b7b16fea685139ca9d5df90ea Author: zkk <1007518571@qq.com> Date: Fri Dec 27 09:53:16 2024 +0800 优化不合理名称和不合理大小写 commit 2e650926bdba1c65baa506be1b1dd09621e8d8ea Author: zkk <1007518571@qq.com> Date: Thu Dec 26 15:06:11 2024 +0800 修复10寸屏幕偏移值微调页面出界问题 commit c481b551f777a3a6cadf7be3bfcab38448b51694 Author: zkk <1007518571@qq.com> Date: Wed Dec 25 15:28:26 2024 +0800 优化移轴设置页面没有返回按钮的问题 commit 2b3c9936bd693c8fc265d6352799f382680f4920 Author: zkk <1007518571@qq.com> Date: Wed Dec 25 10:05:04 2024 +0800 删除移动设置页面中轴反转的选项 commit 5e37d59497c54086d3f1e215cbabc03254857a58 Author: zkk <1007518571@qq.com> Date: Wed Dec 25 09:05:03 2024 +0800 优化选择语言标题 commit 5214c3697baac78bd0a465e33d6f4f3c1e30862e Author: zkk <1007518571@qq.com> Date: Tue Dec 24 10:57:41 2024 +0800 增加设置hostname功能 commit 3709a7465cc2e0d677ecc9979fb18144f7e0ec33 Author: zkk <1007518571@qq.com> Date: Tue Dec 24 10:43:46 2024 +0800 增加工厂设置中打包模式 commit 0c2a2618beb68d50601e433beef06122fb0ffd40 Author: zkk <1007518571@qq.com> Date: Mon Dec 23 16:25:37 2024 +0800 实现恢复出厂设置功能 commit e3a38f85613d53a4a063e835c34c701196010c6e Author: zkk <1007518571@qq.com> Date: Mon Dec 23 15:48:17 2024 +0800 一点格式化 commit 4e9e452e8bed4b53eaaae8f0a69142de8aa50611 Author: zkk <1007518571@qq.com> Date: Sat Dec 21 14:20:22 2024 +0800 优化探针偏移值校准时如果当前激活为第一个喷头时不会重复激活喷头 commit 3b85e8e8d59b0d4eae75f80d9e637fe9dc272cbe Merge: 882850db 10ec2029 Author: zkk <1007518571@qq.com> Date: Wed Dec 18 17:26:08 2024 +0800 Merge branch 'develop' of https://server.creatbot.com/Gitea/CreatBot/CreatBotKlipperScreen into develop commit 882850dbde648598e5f91281101d0ea01fd56d56 Author: zkk <1007518571@qq.com> Date: Wed Dec 18 17:21:16 2024 +0800 补充双喷头偏移校准页面二维码图片 commit 10ec2029eb73e66874d5a0ec492c016480641110 Author: ruipeng <1041589370@qq.com> Date: Wed Dec 18 17:17:18 2024 +0800 增加自动切换喷头开关选项 commit 3d6eed9d9526b77472ba7df29014b5768c594026 Author: zkk <1007518571@qq.com> Date: Mon Dec 16 16:33:34 2024 +0800 喷头偏移值校准功能的实现 commit 40ecbb3ea4827c9bac1aa271cccc958c94c1114a Author: zkk <1007518571@qq.com> Date: Fri Dec 13 09:20:00 2024 +0800 z探针校准时指定默认激活工具头为第一个头 commit bce3caa409618ef5bc2067865940d14a1441c0f8 Author: zkk <1007518571@qq.com> Date: Fri Dec 13 09:19:19 2024 +0800 优化z探针校准时候移动过慢问题 commit 6bfa42e036a521c8ff7db1bf8ccb65500eabb6ea Merge: 1a87ced3 4f3aa9aa Author: zkk <1007518571@qq.com> Date: Thu Dec 12 10:33:58 2024 +0800 Merge commit '4f3aa9aa4c581ae9e7a740bd37f9e80ba064c27f' into release commit 4f3aa9aa4c581ae9e7a740bd37f9e80ba064c27f Merge: e3fd413d 1a69b518 Author: zkk <1007518571@qq.com> Date: Thu Dec 12 10:30:00 2024 +0800 Merge branch 'develop' of https://server.creatbot.com/Gitea/CreatBot/CreatBotKlipperScreen into develop commit 1a69b5180de733f15550a1294a7221d6070306a0 Author: ruipeng <1041589370@qq.com> Date: Wed Dec 11 11:44:36 2024 +0800 新增D600pro2、D1000的V0版机型 commit e3fd413d6256414441e9fe653c1132b1799a5cb2 Author: zkk <1007518571@qq.com> Date: Tue Dec 10 14:34:13 2024 +0800 修复打印时没有修改z偏移值 仍提示保存z偏移的按钮的bug commit 594fb668fe94fe907c028bf65ecced43ea8660cb Author: zkk <1007518571@qq.com> Date: Tue Dec 10 14:25:04 2024 +0800 设置自适应调平选项默认为关闭状态 commit 1a87ced3f5725569a6b9a7ee5f5250044d01d852 Merge: 629416d1 6064a6e1 Author: zkk <1007518571@qq.com> Date: Fri Nov 29 10:18:32 2024 +0800 Merge branch 'develop' into release # Conflicts: # panels/advanced.py # panels/nozzle_offset.py # panels/offset_fine_tune.py # panels/zcalibrate.py
847 lines
42 KiB
Python
847 lines
42 KiB
Python
# -*- coding: utf-8 -*-
|
|
import logging
|
|
import os
|
|
import gi
|
|
|
|
gi.require_version("Gtk", "3.0")
|
|
from gi.repository import GLib, Gtk, Pango
|
|
from math import pi, sqrt, trunc
|
|
from statistics import median
|
|
from time import time
|
|
from ks_includes.screen_panel import ScreenPanel
|
|
from ks_includes.KlippyGtk import find_widget
|
|
|
|
|
|
class Panel(ScreenPanel):
|
|
def __init__(self, screen, title):
|
|
title = title or _("Job Status")
|
|
super().__init__(screen, title)
|
|
self.thumb_dialog = None
|
|
self.grid = Gtk.Grid(column_homogeneous=True)
|
|
self.pos_z = 0.0
|
|
self.extrusion = 100
|
|
self.speed_factor = 1.0
|
|
self.speed = 100
|
|
self.req_speed = 0
|
|
self.oheight = 0.0
|
|
self.current_extruder = None
|
|
self.fila_section = pi * ((1.75 / 2) ** 2)
|
|
self.filename_label = None
|
|
self.filename = None
|
|
self.prev_pos = None
|
|
self.prev_gpos = None
|
|
self.can_close = False
|
|
self.flow_timeout = None
|
|
self.animation_timeout = None
|
|
self.file_metadata = self.fans = {}
|
|
self.state = "standby"
|
|
self.timeleft_type = "auto"
|
|
self.progress = 0.0
|
|
self.zoffset = 0.0
|
|
self.flowrate = 0.0
|
|
self.vel = 0.0
|
|
self.flowstore = []
|
|
self.mm = _("mm")
|
|
self.mms = _("mm/s")
|
|
self.mms2 = _("mm/s²")
|
|
self.mms3 = _("mm³/s")
|
|
self.status_grid = None
|
|
self.move_grid = None
|
|
self.time_grid = None
|
|
self.extrusion_grid = None
|
|
|
|
data = ['pos_x', 'pos_y', 'pos_z', 'time_left', 'duration', 'slicer_time', 'file_time',
|
|
'filament_time', 'est_time', 'speed_factor', 'req_speed', 'max_accel', 'extrude_factor', 'zoffset',
|
|
'zoffset', 'filament_used', 'filament_total', 'advance', 'layer', 'total_layers', 'height',
|
|
'flowrate']
|
|
|
|
for item in data:
|
|
self.labels[item] = Gtk.Label(label="-", hexpand=True, vexpand=True)
|
|
|
|
self.labels['left'] = Gtk.Label(_("Left:"))
|
|
self.labels['elapsed'] = Gtk.Label(_("Elapsed:"))
|
|
self.labels['total'] = Gtk.Label(_("Total:"))
|
|
self.labels['slicer'] = Gtk.Label(_("Slicer:"))
|
|
self.labels['file_tlbl'] = Gtk.Label(_("File:"))
|
|
self.labels['fila_tlbl'] = Gtk.Label(_("Filament:"))
|
|
self.labels['speed_lbl'] = Gtk.Label(_("Speed:"))
|
|
self.labels['accel_lbl'] = Gtk.Label(_("Acceleration:"))
|
|
self.labels['flow'] = Gtk.Label(_("Flow:"))
|
|
self.labels['zoffset_lbl'] = Gtk.Label(_("Z offset:"))
|
|
self.labels['fila_used_lbl'] = Gtk.Label(_("Filament used:"))
|
|
self.labels['fila_total_lbl'] = Gtk.Label(_("Filament total:"))
|
|
self.labels['pa_lbl'] = Gtk.Label(_("Pressure Advance:"))
|
|
self.labels['flowrate_lbl'] = Gtk.Label(_("Flowrate:"))
|
|
self.labels['height_lbl'] = Gtk.Label(_("Height:"))
|
|
self.labels['layer_lbl'] = Gtk.Label(_("Layer:"))
|
|
|
|
for fan in self._printer.get_fans():
|
|
# fan_types = ["controller_fan", "fan_generic", "heater_fan"]
|
|
if fan == "fan":
|
|
name = " "
|
|
elif fan.startswith("fan_generic"):
|
|
name = " ".join(fan.split(" ")[1:])[:1].upper() + ":"
|
|
if name.startswith("_"):
|
|
continue
|
|
else:
|
|
continue
|
|
self.fans[fan] = {
|
|
"name": name,
|
|
"speed": "-"
|
|
}
|
|
|
|
self.labels['file'] = Gtk.Label(label="Filename", hexpand=True)
|
|
self.labels['file'].get_style_context().add_class("printing-filename")
|
|
self.labels['lcdmessage'] = Gtk.Label(no_show_all=True)
|
|
self.labels['lcdmessage'].get_style_context().add_class("printing-status")
|
|
|
|
for label in self.labels:
|
|
self.labels[label].set_halign(Gtk.Align.START)
|
|
self.labels[label].set_ellipsize(Pango.EllipsizeMode.END)
|
|
|
|
fi_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10, valign=Gtk.Align.CENTER)
|
|
fi_box.add(self.labels['file'])
|
|
fi_box.add(self.labels['lcdmessage'])
|
|
self.grid.attach(fi_box, 1, 0, 3, 1)
|
|
|
|
self.labels['darea'] = Gtk.DrawingArea()
|
|
self.labels['darea'].connect("draw", self.on_draw)
|
|
|
|
box = Gtk.Box(halign=Gtk.Align.CENTER)
|
|
self.labels['progress_text'] = Gtk.Label(label="0%")
|
|
self.labels['progress_text'].get_style_context().add_class("printing-progress-text")
|
|
box.add(self.labels['progress_text'])
|
|
|
|
overlay = Gtk.Overlay(hexpand=True)
|
|
overlay.set_size_request(*(self._gtk.font_size * 5,) * 2)
|
|
overlay.add(self.labels['darea'])
|
|
overlay.add_overlay(box)
|
|
self.grid.attach(overlay, 0, 0, 1, 1)
|
|
|
|
self.labels['thumbnail'] = self._gtk.Button("file")
|
|
self.labels['thumbnail'].get_style_context().add_class("custom-icon-button")
|
|
self.labels['thumbnail'].connect("clicked", self.show_fullscreen_thumbnail)
|
|
self.labels['info_grid'] = Gtk.Grid()
|
|
self.labels['info_grid'].attach(self.labels['thumbnail'], 0, 0, 1, 1)
|
|
self.current_extruder = self._printer.get_stat("toolhead", "extruder")
|
|
if self.current_extruder:
|
|
diameter = float(self._printer.get_config_section(self.current_extruder)['filament_diameter'])
|
|
self.fila_section = pi * ((diameter / 2) ** 2)
|
|
|
|
self.buttons = {}
|
|
self.create_buttons()
|
|
self.buttons['button_grid'] = Gtk.Grid(row_homogeneous=True, column_homogeneous=True, vexpand=False)
|
|
self.grid.attach(self.buttons['button_grid'], 0, 3, 4, 1)
|
|
|
|
self.create_status_grid()
|
|
self.create_extrusion_grid()
|
|
self.create_time_grid()
|
|
self.create_move_grid()
|
|
self.grid.attach(self.labels['info_grid'], 0, 1, 4, 2)
|
|
self.switch_info(info=self.status_grid)
|
|
self.content.add(self.grid)
|
|
|
|
def create_status_grid(self, widget=None):
|
|
buttons = {
|
|
'speed': self._gtk.Button("speed+", "-", None, self.bts, Gtk.PositionType.LEFT, 1),
|
|
'z': self._gtk.Button("height", "-", None, self.bts, Gtk.PositionType.LEFT, 1),
|
|
'extrusion': self._gtk.Button("extrude", "-", None, self.bts, Gtk.PositionType.LEFT, 1),
|
|
'fan': self._gtk.Button("fan", "-", None, self.bts, Gtk.PositionType.LEFT, 1),
|
|
'elapsed': self._gtk.Button("clock", "-", None, self.bts, Gtk.PositionType.LEFT, 1),
|
|
'left': self._gtk.Button("hourglass", "-", None, self.bts, Gtk.PositionType.LEFT, 1),
|
|
}
|
|
for button in buttons:
|
|
buttons[button].set_halign(Gtk.Align.START)
|
|
buttons['fan'].connect("clicked", self.menu_item_clicked, {"panel": "fan"})
|
|
self.buttons.update(buttons)
|
|
|
|
self.buttons['extruder'] = {}
|
|
for i, extruder in enumerate(self._printer.get_tools()):
|
|
self.labels[extruder] = Gtk.Label(label="-")
|
|
self.buttons['extruder'][extruder] = self._gtk.Button(f"extruder-{i}", "", None, self.bts,
|
|
Gtk.PositionType.LEFT, 1)
|
|
self.buttons['extruder'][extruder].set_label(self.labels[extruder].get_text())
|
|
self.buttons['extruder'][extruder].connect("clicked", self.menu_item_clicked,
|
|
{"panel": "numpad",
|
|
'extra': extruder})
|
|
self.buttons['extruder'][extruder].set_halign(Gtk.Align.START)
|
|
|
|
self.labels['temp_grid'] = Gtk.Grid(column_homogeneous=True)
|
|
nlimit = 3 if self._screen.width <= 500 else 4
|
|
n = 0
|
|
if nlimit > 2 and len(self._printer.get_tools()) == 2:
|
|
for extruder in self.buttons['extruder']:
|
|
self.labels['temp_grid'].attach(self.buttons['extruder'][extruder], n, 0, 1, 1)
|
|
n += 1
|
|
else:
|
|
self.current_extruder = self._printer.get_stat("toolhead", "extruder")
|
|
if self.current_extruder:
|
|
self.labels['temp_grid'].attach(self.buttons['extruder'][self.current_extruder], n, 0, 1, 1)
|
|
n += 1
|
|
self.buttons['heater'] = {}
|
|
n = 0
|
|
for dev in self._printer.get_heaters():
|
|
if n >= nlimit:
|
|
break
|
|
if dev == "heater_bed":
|
|
self.buttons['heater'][dev] = self._gtk.Button("bed", "", None, self.bts, Gtk.PositionType.LEFT, 1)
|
|
elif dev == "heater_generic chamber":
|
|
self.buttons['heater'][dev] = self._gtk.Button("chamber", "", None, self.bts, Gtk.PositionType.LEFT, 1)
|
|
else:
|
|
self.buttons['heater'][dev] = self._gtk.Button("heater", "", None, self.bts, Gtk.PositionType.LEFT, 1)
|
|
self.labels[dev] = Gtk.Label(label="-")
|
|
|
|
self.buttons['heater'][dev].set_label(self.labels[dev].get_text())
|
|
self.buttons['heater'][dev].connect("clicked", self.menu_item_clicked,
|
|
{"panel": "numpad", "extra": dev})
|
|
self.buttons['heater'][dev].set_halign(Gtk.Align.START)
|
|
self.labels['temp_grid'].attach(self.buttons['heater'][dev], n, 1, 1, 1)
|
|
n += 1
|
|
extra_item = not self._show_heater_power
|
|
if self.ks_printer_cfg is not None:
|
|
titlebar_items = self.ks_printer_cfg.get("titlebar_items", "")
|
|
if titlebar_items is not None:
|
|
titlebar_items = [str(i.strip()) for i in titlebar_items.split(',')]
|
|
logging.info(f"Titlebar items: {titlebar_items}")
|
|
for device in self._printer.get_temp_sensors():
|
|
name = " ".join(device.split(" ")[1:])
|
|
for item in titlebar_items:
|
|
if name == item:
|
|
if extra_item:
|
|
extra_item = False
|
|
nlimit += 1
|
|
if n >= nlimit:
|
|
break
|
|
self.buttons['heater'][device] = self._gtk.Button("heat-up", "", None, self.bts,
|
|
Gtk.PositionType.LEFT, 1)
|
|
self.labels[device] = Gtk.Label(label="-")
|
|
self.buttons['heater'][device].set_label(self.labels[device].get_text())
|
|
self.buttons['heater'][device].connect("clicked", self.menu_item_clicked,
|
|
{"panel": "numpad"})
|
|
self.buttons['heater'][device].set_halign(Gtk.Align.START)
|
|
self.labels['temp_grid'].attach(self.buttons['heater'][device], n, 1, 1, 1)
|
|
n += 1
|
|
break
|
|
|
|
szfe = Gtk.Grid(column_homogeneous=True)
|
|
szfe.attach(self.buttons['speed'], 0, 0, 3, 1)
|
|
szfe.attach(self.buttons['z'], 2, 0, 2, 1)
|
|
if self._printer.get_tools():
|
|
szfe.attach(self.buttons['extrusion'], 0, 1, 3, 1)
|
|
if self._printer.get_fans():
|
|
szfe.attach(self.buttons['fan'], 2, 1, 2, 1)
|
|
|
|
info = Gtk.Grid(row_homogeneous=True)
|
|
info.get_style_context().add_class("printing-info")
|
|
info.attach(self.labels['temp_grid'], 0, 0, 1, 2)
|
|
info.attach(szfe, 0, 2, 1, 2)
|
|
info.attach(self.buttons['elapsed'], 0, 4, 1, 1)
|
|
info.attach(self.buttons['left'], 0, 5, 1, 1)
|
|
self.status_grid = info
|
|
|
|
def create_extrusion_grid(self, widget=None):
|
|
goback = self._gtk.Button("back", None, "custom-icon-button", self.bts, Gtk.PositionType.TOP, False)
|
|
goback.connect("clicked", self.switch_info, self.status_grid)
|
|
goback.set_hexpand(False)
|
|
goback.get_style_context().add_class("printing-info")
|
|
|
|
info = Gtk.Grid(hexpand=True, vexpand=True, halign=Gtk.Align.START)
|
|
info.get_style_context().add_class("printing-info-secondary")
|
|
info.attach(goback, 0, 0, 1, 6)
|
|
info.attach(self.labels['flow'], 1, 0, 1, 1)
|
|
info.attach(self.labels['extrude_factor'], 2, 0, 1, 1)
|
|
info.attach(self.labels['flowrate_lbl'], 1, 1, 1, 1)
|
|
info.attach(self.labels['flowrate'], 2, 1, 1, 1)
|
|
info.attach(self.labels['pa_lbl'], 1, 2, 1, 1)
|
|
info.attach(self.labels['advance'], 2, 2, 1, 1)
|
|
info.attach(self.labels['fila_used_lbl'], 1, 3, 1, 1)
|
|
info.attach(self.labels['filament_used'], 2, 3, 1, 1)
|
|
info.attach(self.labels['fila_total_lbl'], 1, 4, 1, 1)
|
|
info.attach(self.labels['filament_total'], 2, 4, 1, 1)
|
|
self.extrusion_grid = info
|
|
self.buttons['extrusion'].connect("clicked", self.switch_info, self.extrusion_grid)
|
|
|
|
def create_move_grid(self, widget=None):
|
|
goback = self._gtk.Button("back", None, "custom-icon-button", self.bts, Gtk.PositionType.TOP, False)
|
|
goback.connect("clicked", self.switch_info, self.status_grid)
|
|
goback.set_hexpand(False)
|
|
goback.get_style_context().add_class("printing-info")
|
|
|
|
pos_box = Gtk.Box(spacing=5)
|
|
pos_box.add(self.labels['pos_x'])
|
|
pos_box.add(self.labels['pos_y'])
|
|
pos_box.add(self.labels['pos_z'])
|
|
|
|
info = Gtk.Grid(hexpand=True, vexpand=True, halign=Gtk.Align.START)
|
|
info.get_style_context().add_class("printing-info-secondary")
|
|
info.attach(goback, 0, 0, 1, 6)
|
|
info.attach(self.labels['speed_lbl'], 1, 0, 1, 1)
|
|
info.attach(self.labels['req_speed'], 2, 0, 1, 1)
|
|
info.attach(self.labels['accel_lbl'], 1, 1, 1, 1)
|
|
info.attach(self.labels['max_accel'], 2, 1, 1, 1)
|
|
info.attach(pos_box, 1, 2, 2, 1)
|
|
info.attach(self.labels['zoffset_lbl'], 1, 3, 1, 1)
|
|
info.attach(self.labels['zoffset'], 2, 3, 1, 1)
|
|
info.attach(self.labels['height_lbl'], 1, 4, 1, 1)
|
|
info.attach(self.labels['height'], 2, 4, 1, 1)
|
|
info.attach(self.labels['layer_lbl'], 1, 5, 1, 1)
|
|
info.attach(self.labels['layer'], 2, 5, 1, 1)
|
|
self.move_grid = info
|
|
self.buttons['z'].connect("clicked", self.switch_info, self.move_grid)
|
|
self.buttons['speed'].connect("clicked", self.switch_info, self.move_grid)
|
|
|
|
def create_time_grid(self, widget=None):
|
|
goback = self._gtk.Button("back", None, "custom-icon-button", self.bts, Gtk.PositionType.TOP, False)
|
|
goback.connect("clicked", self.switch_info, self.status_grid)
|
|
goback.set_hexpand(False)
|
|
|
|
info = Gtk.Grid()
|
|
info.get_style_context().add_class("printing-info-secondary")
|
|
info.attach(goback, 0, 0, 1, 6)
|
|
info.attach(self.labels['elapsed'], 1, 0, 1, 1)
|
|
info.attach(self.labels['duration'], 2, 0, 1, 1)
|
|
info.attach(self.labels['left'], 1, 1, 1, 1)
|
|
info.attach(self.labels['time_left'], 2, 1, 1, 1)
|
|
info.attach(self.labels['total'], 1, 2, 1, 1)
|
|
info.attach(self.labels['est_time'], 2, 2, 1, 1)
|
|
info.attach(self.labels['slicer'], 1, 3, 1, 1)
|
|
info.attach(self.labels['slicer_time'], 2, 3, 1, 1)
|
|
info.attach(self.labels['file_tlbl'], 1, 4, 1, 1)
|
|
info.attach(self.labels['file_time'], 2, 4, 1, 1)
|
|
info.attach(self.labels['fila_tlbl'], 1, 5, 1, 1)
|
|
info.attach(self.labels['filament_time'], 2, 5, 1, 1)
|
|
self.time_grid = info
|
|
self.buttons['elapsed'].connect("clicked", self.switch_info, self.time_grid)
|
|
self.buttons['left'].connect("clicked", self.switch_info, self.time_grid)
|
|
|
|
def switch_info(self, widget=None, info=None):
|
|
if not info:
|
|
logging.debug("No info to attach")
|
|
return
|
|
if self._screen.vertical_mode:
|
|
self.labels['info_grid'].remove_row(1)
|
|
self.labels['info_grid'].attach(info, 0, 1, 1, 1)
|
|
else:
|
|
self.labels['info_grid'].remove_column(1)
|
|
self.labels['info_grid'].attach(info, 1, 0, 1, 1)
|
|
self.labels['info_grid'].show_all()
|
|
|
|
def on_draw(self, da, ctx):
|
|
w = da.get_allocated_width()
|
|
h = da.get_allocated_height()
|
|
r = min(w, h) * .42
|
|
|
|
ctx.set_source_rgb(0.13, 0.13, 0.13)
|
|
ctx.set_line_width(self._gtk.font_size * .75)
|
|
ctx.translate(w / 2, h / 2)
|
|
ctx.arc(0, 0, r, 0, 2 * pi)
|
|
ctx.stroke()
|
|
ctx.set_source_rgb(0.114, 0.550, 0.777)
|
|
ctx.arc(0, 0, r, 3 / 2 * pi, 3 / 2 * pi + (self.progress * 2 * pi))
|
|
ctx.stroke()
|
|
|
|
def activate(self):
|
|
if self.flow_timeout is None:
|
|
self.flow_timeout = GLib.timeout_add_seconds(2, self.update_flow)
|
|
if self.animation_timeout is None:
|
|
self.animation_timeout = GLib.timeout_add(500, self.animate_label)
|
|
|
|
def deactivate(self):
|
|
if self.flow_timeout is not None:
|
|
GLib.source_remove(self.flow_timeout)
|
|
self.flow_timeout = None
|
|
if self.animation_timeout is not None:
|
|
GLib.source_remove(self.animation_timeout)
|
|
self.animation_timeout = None
|
|
|
|
def create_buttons(self):
|
|
|
|
self.buttons = {
|
|
'cancel': self._gtk.Button("stop", _("Cancel"), "color2"),
|
|
'control': self._gtk.Button("more-settings", _("Settings"), "color3"),
|
|
'fine_tune': self._gtk.Button("fine-tune", _("Fine Tuning"), "color4"),
|
|
'menu': self._gtk.Button("main-menu", _("Main Menu"), "color4"),
|
|
'pause': self._gtk.Button("pause", _("Pause"), "color1"),
|
|
'restart': self._gtk.Button("refresh", _("Reprint"), "color3"),
|
|
'resume': self._gtk.Button("resume", _("Resume"), "color1"),
|
|
'save_offset_probe': self._gtk.Button("home-z", _("Save Z") + "\n" + "Probe", "color1"),
|
|
'save_offset_endstop': self._gtk.Button("home-z", _("Save Z") + "\n" + "Endstop", "color2"),
|
|
}
|
|
self.buttons['cancel'].connect("clicked", self.cancel)
|
|
self.buttons['control'].connect("clicked", self._screen._go_to_submenu, "")
|
|
self.buttons['fine_tune'].connect("clicked", self.menu_item_clicked, {
|
|
"panel": "fine_tune"})
|
|
self.buttons['menu'].connect("clicked", self.close_panel)
|
|
self.buttons['pause'].connect("clicked", self.pause)
|
|
self.buttons['restart'].connect("clicked", self.restart)
|
|
self.buttons['resume'].connect("clicked", self.resume)
|
|
self.buttons['save_offset_probe'].connect("clicked", self.save_offset, "probe")
|
|
self.buttons['save_offset_endstop'].connect("clicked", self.save_offset, "endstop")
|
|
|
|
def save_offset(self, widget, device):
|
|
sign = "+" if self.zoffset > 0 else "-"
|
|
label = Gtk.Label(hexpand=True, vexpand=True, wrap=True)
|
|
saved_z_offset = None
|
|
msg = f"Apply {sign}{abs(self.zoffset)} offset to {device}?"
|
|
if device == "probe":
|
|
msg = _("Apply %s%.3f offset to Probe?") % (sign, abs(self.zoffset))
|
|
if probe := self._printer.get_probe():
|
|
saved_z_offset = probe['z_offset']
|
|
elif device == "endstop":
|
|
msg = _("Apply %s%.3f offset to Endstop?") % (sign, abs(self.zoffset))
|
|
if 'stepper_z' in self._printer.get_config_section_list():
|
|
saved_z_offset = self._printer.get_config_section('stepper_z')['position_endstop']
|
|
elif 'stepper_a' in self._printer.get_config_section_list():
|
|
saved_z_offset = self._printer.get_config_section('stepper_a')['position_endstop']
|
|
if saved_z_offset:
|
|
msg += "\n\n" + _("Saved offset: %s") % saved_z_offset
|
|
label.set_label(msg)
|
|
buttons = [
|
|
{"name": _("Apply"), "response": Gtk.ResponseType.APPLY, "style": 'dialog-default'},
|
|
{"name": _("Cancel"), "response": Gtk.ResponseType.CANCEL, "style": 'dialog-error'}
|
|
]
|
|
self._gtk.Dialog(_("Save Z"), buttons, label, self.save_confirm, device)
|
|
|
|
def save_confirm(self, dialog, response_id, device):
|
|
self._gtk.remove_dialog(dialog)
|
|
if response_id == Gtk.ResponseType.APPLY:
|
|
if device == "probe":
|
|
self._screen._ws.klippy.gcode_script("Z_OFFSET_APPLY_PROBE")
|
|
if device == "endstop":
|
|
self._screen._ws.klippy.gcode_script("Z_OFFSET_APPLY_ENDSTOP")
|
|
self._screen._ws.klippy.gcode_script("SAVE_CONFIG")
|
|
|
|
def restart(self, widget):
|
|
if self.filename:
|
|
self.disable_button("restart")
|
|
if self.state == "error":
|
|
self._screen._ws.klippy.gcode_script("SDCARD_RESET_FILE")
|
|
self._screen._ws.klippy.print_start(self.filename)
|
|
logging.info(f"Starting print: {self.filename}")
|
|
self.new_print()
|
|
else:
|
|
logging.info(f"Could not restart {self.filename}")
|
|
|
|
def resume(self, widget):
|
|
self._screen._ws.klippy.print_resume()
|
|
self._screen.show_all()
|
|
|
|
def pause(self, widget):
|
|
self.disable_button("pause", "resume")
|
|
self._screen._ws.klippy.print_pause()
|
|
self._screen.show_all()
|
|
|
|
def cancel(self, widget):
|
|
buttons = [
|
|
{"name": _("Cancel Print"), "response": Gtk.ResponseType.OK, "style": 'dialog-error'},
|
|
{"name": _("Go Back"), "response": Gtk.ResponseType.CANCEL, "style": 'dialog-info'}
|
|
]
|
|
if len(self._printer.get_stat("exclude_object", "objects")) > 1:
|
|
buttons.insert(0, {"name": _("Exclude Object"), "response": Gtk.ResponseType.APPLY})
|
|
label = Gtk.Label(hexpand=True, vexpand=True, wrap=True)
|
|
label.set_markup(_("Are you sure you wish to cancel this print?"))
|
|
self._gtk.Dialog(_("Cancel"), buttons, label, self.cancel_confirm)
|
|
|
|
def cancel_confirm(self, dialog, response_id):
|
|
self._gtk.remove_dialog(dialog)
|
|
if response_id == Gtk.ResponseType.APPLY:
|
|
self.menu_item_clicked(None, {"panel": "exclude"})
|
|
return
|
|
if response_id == Gtk.ResponseType.CANCEL:
|
|
self.enable_button("pause", "cancel")
|
|
return
|
|
logging.debug("Canceling print")
|
|
self.set_state("cancelling")
|
|
self.disable_button("pause", "resume", "cancel")
|
|
self._screen._ws.klippy.print_cancel()
|
|
|
|
def close_panel(self, widget=None):
|
|
if self.can_close:
|
|
logging.debug("Closing job_status panel")
|
|
self._screen.state_ready(wait=False)
|
|
|
|
def enable_button(self, *args):
|
|
for arg in args:
|
|
self.buttons[arg].set_sensitive(True)
|
|
|
|
def disable_button(self, *args):
|
|
for arg in args:
|
|
self.buttons[arg].set_sensitive(False)
|
|
|
|
def new_print(self):
|
|
self._screen.close_screensaver()
|
|
if "virtual_sdcard" in self._printer.data:
|
|
logging.info("reseting progress")
|
|
self._printer.data["virtual_sdcard"]["progress"] = 0
|
|
self.update_progress(0.0)
|
|
self.set_state("printing")
|
|
|
|
def process_update(self, action, data):
|
|
if action == "notify_gcode_response":
|
|
if "action:cancel" in data:
|
|
self.set_state("cancelled")
|
|
elif "action:paused" in data:
|
|
self.set_state("paused")
|
|
elif "action:resumed" in data:
|
|
self.set_state("printing")
|
|
return
|
|
elif action == "notify_metadata_update" and data['filename'] == self.filename:
|
|
self.get_file_metadata(response=True)
|
|
elif action != "notify_status_update":
|
|
return
|
|
|
|
for x in self._printer.get_temp_devices():
|
|
if x in data:
|
|
temp = round(self._printer.get_stat(x, "temperature"))
|
|
temp_target = round(self._printer.get_stat(x, "target"))
|
|
power = round(self._printer.get_stat(x, "power") * 100)
|
|
temp_state = f"{temp}°/{temp_target}° {'{:3.0f}%'.format(power) if self._show_heater_power else ''}".strip()
|
|
if x in self.buttons['extruder']:
|
|
self.buttons['extruder'][x].set_label(temp_state)
|
|
elif x in self.buttons['heater']:
|
|
self.buttons['heater'][x].set_label(temp_state)
|
|
|
|
if "display_status" in data and "message" in data["display_status"]:
|
|
if data['display_status']['message']:
|
|
self.labels['lcdmessage'].set_label(f"{data['display_status']['message']}")
|
|
self.labels['lcdmessage'].show()
|
|
else:
|
|
self.labels['lcdmessage'].hide()
|
|
|
|
if 'toolhead' in data:
|
|
if "max_accel" in data["toolhead"]:
|
|
self.labels['max_accel'].set_label(f"{data['toolhead']['max_accel']:.0f} {self.mms2}")
|
|
if 'extruder' in data and 'pressure_advance' in data['extruder']:
|
|
self.labels['advance'].set_label(f"{data['extruder']['pressure_advance']:.2f}")
|
|
|
|
if 'gcode_move' in data:
|
|
if 'gcode_position' in data['gcode_move']:
|
|
self.pos_z = round(float(data['gcode_move']['gcode_position'][2]), 2)
|
|
self.buttons['z'].set_label(
|
|
f"Z: {self.pos_z:6.2f}{f'/{self.oheight}' if self.oheight > 0 else ''} "
|
|
f"{f'{self.mm}' if self._screen.width > 500 else ''}"
|
|
)
|
|
if 'extrude_factor' in data['gcode_move']:
|
|
self.extrusion = round(float(data['gcode_move']['extrude_factor']) * 100)
|
|
self.labels['extrude_factor'].set_label(f"{self.extrusion:3}%")
|
|
if 'speed_factor' in data['gcode_move']:
|
|
self.speed = round(float(data['gcode_move']['speed_factor']) * 100)
|
|
self.speed_factor = float(data['gcode_move']['speed_factor'])
|
|
self.labels['speed_factor'].set_label(f"{self.speed:3}%")
|
|
if 'speed' in data['gcode_move']:
|
|
self.req_speed = round(float(data["gcode_move"]["speed"]) / 60 * self.speed_factor)
|
|
self.labels['req_speed'].set_label(
|
|
f"{self.speed}% {self.vel:3.0f}/{self.req_speed:3.0f} "
|
|
f"{f'{self.mms}' if self.vel < 1000 and self.req_speed < 1000 and self._screen.width > 500 else ''}"
|
|
)
|
|
self.buttons['speed'].set_label(self.labels['req_speed'].get_label())
|
|
if 'homing_origin' in data['gcode_move']:
|
|
self.zoffset = float(data['gcode_move']['homing_origin'][2])
|
|
self.labels['zoffset'].set_label(f"{self.zoffset:.3f} {self.mm}")
|
|
if 'motion_report' in data:
|
|
if 'live_position' in data['motion_report']:
|
|
self.labels['pos_x'].set_label(f"X: {data['motion_report']['live_position'][0]:6.2f}")
|
|
self.labels['pos_y'].set_label(f"Y: {data['motion_report']['live_position'][1]:6.2f}")
|
|
self.labels['pos_z'].set_label(f"Z: {data['motion_report']['live_position'][2]:6.2f}")
|
|
pos = data["motion_report"]["live_position"]
|
|
now = time()
|
|
if self.prev_pos is not None:
|
|
interval = (now - self.prev_pos[1])
|
|
# Calculate Flowrate
|
|
evelocity = (pos[3] - self.prev_pos[0][3]) / interval
|
|
self.flowstore.append(self.fila_section * evelocity)
|
|
self.prev_pos = [pos, now]
|
|
if 'live_velocity' in data['motion_report']:
|
|
self.vel = float(data["motion_report"]["live_velocity"])
|
|
self.labels['req_speed'].set_label(
|
|
f"{self.speed}% {self.vel:3.0f}/{self.req_speed:3.0f} "
|
|
f"{f'{self.mms}' if self.vel < 1000 and self.req_speed < 1000 and self._screen.width > 500 else ''}"
|
|
)
|
|
self.buttons['speed'].set_label(self.labels['req_speed'].get_label())
|
|
if 'live_extruder_velocity' in data['motion_report']:
|
|
self.flowstore.append(self.fila_section * float(data["motion_report"]["live_extruder_velocity"]))
|
|
fan_label = ""
|
|
for fan in self.fans:
|
|
self.fans[fan]['speed'] = f"{self._printer.get_fan_speed(fan) * 100:3.0f}%"
|
|
fan_label += f"C:{self.fans[fan]['speed']}" if fan == "fan" else f" {self.fans[fan]['name']}{self.fans[fan]['speed']}"
|
|
if fan_label:
|
|
self.buttons['fan'].set_label(fan_label[:13])
|
|
if "print_stats" in data:
|
|
if 'state' in data['print_stats']:
|
|
self.set_state(
|
|
data["print_stats"]["state"],
|
|
msg=f'{data["print_stats"]["message"] if "message" in data["print_stats"] else ""}'
|
|
)
|
|
if 'filename' in data['print_stats']:
|
|
self.update_filename(data['print_stats']["filename"])
|
|
if 'filament_used' in data['print_stats']:
|
|
self.labels['filament_used'].set_label(
|
|
f"{float(data['print_stats']['filament_used']) / 1000:.1f} m"
|
|
)
|
|
if 'info' in data["print_stats"]:
|
|
if ('total_layer' in data['print_stats']['info']
|
|
and data["print_stats"]['info']['total_layer'] is not None):
|
|
self.labels['total_layers'].set_label(f"{data['print_stats']['info']['total_layer']}")
|
|
if ('current_layer' in data['print_stats']['info']
|
|
and data['print_stats']['info']['current_layer'] is not None):
|
|
self.labels['layer'].set_label(
|
|
f"{data['print_stats']['info']['current_layer']} / "
|
|
f"{self.labels['total_layers'].get_text()}"
|
|
)
|
|
if 'total_duration' in data["print_stats"]:
|
|
self.labels["duration"].set_label(self.format_time(data["print_stats"]["total_duration"]))
|
|
if self.state in ["printing", "paused"]:
|
|
self.update_time_left()
|
|
|
|
def update_flow(self):
|
|
if not self.flowstore:
|
|
self.flowstore.append(0)
|
|
self.flowrate = median(self.flowstore)
|
|
self.flowstore = []
|
|
self.labels['flowrate'].set_label(f"{self.flowrate:.1f} {self.mms3}")
|
|
self.buttons['extrusion'].set_label(f"{self.extrusion:3}% {self.flowrate:5.1f} {self.mms3}")
|
|
return True
|
|
|
|
def update_time_left(self):
|
|
progress = (
|
|
max(self._printer.get_stat('virtual_sdcard', 'file_position') - self.file_metadata['gcode_start_byte'], 0)
|
|
/ (self.file_metadata['gcode_end_byte'] - self.file_metadata['gcode_start_byte'])
|
|
) if "gcode_start_byte" in self.file_metadata else self._printer.get_stat('virtual_sdcard', 'progress')
|
|
|
|
elapsed_label = f"{self.labels['elapsed'].get_text()} {self.labels['duration'].get_text()}"
|
|
self.buttons['elapsed'].set_label(elapsed_label)
|
|
find_widget(self.buttons['elapsed'], Gtk.Label).set_ellipsize(Pango.EllipsizeMode.END)
|
|
|
|
last_time = self.file_metadata['last_time'] if "last_time" in self.file_metadata else 0
|
|
slicer_time = self.file_metadata['estimated_time'] if 'estimated_time' in self.file_metadata else 0
|
|
print_duration = float(self._printer.get_stat('print_stats', 'print_duration'))
|
|
if print_duration < 1: # No-extrusion
|
|
if last_time:
|
|
print_duration = last_time * progress
|
|
elif slicer_time:
|
|
print_duration = slicer_time * progress
|
|
else:
|
|
print_duration = float(self._printer.get_stat('print_stats', 'total_duration'))
|
|
|
|
fila_used = float(self._printer.get_stat('print_stats', 'filament_used'))
|
|
if 'filament_total' in self.file_metadata and self.file_metadata['filament_total'] >= fila_used > 0:
|
|
filament_time = (print_duration / (fila_used / self.file_metadata['filament_total']))
|
|
self.labels["filament_time"].set_label(self.format_time(filament_time))
|
|
else:
|
|
filament_time = 0
|
|
if progress > 0:
|
|
file_time = (print_duration / progress)
|
|
self.labels["file_time"].set_label(self.format_time(file_time))
|
|
else:
|
|
file_time = 0
|
|
|
|
estimated = 0
|
|
timeleft_type = self._config.get_config()['main'].get('print_estimate_method', 'auto')
|
|
if timeleft_type == "file":
|
|
estimated = file_time
|
|
elif timeleft_type == "filament":
|
|
estimated = filament_time
|
|
elif timeleft_type == "slicer":
|
|
estimated = slicer_time
|
|
else:
|
|
estimated = self.estimate_time(
|
|
progress, print_duration, file_time, filament_time, slicer_time, last_time
|
|
)
|
|
if estimated > 1:
|
|
progress = min(max(print_duration / estimated, 0), 1)
|
|
self.labels["est_time"].set_label(self.format_time(estimated))
|
|
self.labels["time_left"].set_label(self.format_eta(estimated, print_duration))
|
|
remaining_label = f"{self.labels['left'].get_text()} {self.labels['time_left'].get_text()}"
|
|
self.buttons['left'].set_label(remaining_label)
|
|
find_widget(self.buttons['left'], Gtk.Label).set_ellipsize(Pango.EllipsizeMode.END)
|
|
self.update_progress(progress)
|
|
|
|
def estimate_time(self, progress, print_duration, file_time, filament_time, slicer_time, last_time):
|
|
estimate_above = 0.3
|
|
slicer_time /= sqrt(self.speed_factor)
|
|
if progress <= estimate_above:
|
|
return last_time or slicer_time or filament_time or file_time
|
|
objects = self._printer.get_stat("exclude_object", "objects")
|
|
excluded_objects = self._printer.get_stat("exclude_object", "excluded_objects")
|
|
exclude_compensation = 3 * (len(excluded_objects) / len(objects)) if len(objects) > 0 else 0
|
|
weight_last = 4.0 - exclude_compensation if print_duration < last_time else 0
|
|
weight_slicer = 1.0 + estimate_above - progress - exclude_compensation if print_duration < slicer_time else 0
|
|
weight_filament = min(progress - estimate_above, 0.33) if print_duration < filament_time else 0
|
|
weight_file = progress - estimate_above
|
|
total_weight = weight_last + weight_slicer + weight_filament + weight_file
|
|
if total_weight == 0:
|
|
return 0
|
|
return (
|
|
(
|
|
last_time * weight_last
|
|
+ slicer_time * weight_slicer
|
|
+ filament_time * weight_filament
|
|
+ file_time * weight_file
|
|
)
|
|
/ total_weight
|
|
)
|
|
|
|
def update_progress(self, progress: float):
|
|
self.progress = progress
|
|
self.labels['progress_text'].set_label(f"{trunc(progress * 100)}%")
|
|
self.labels['darea'].queue_draw()
|
|
|
|
def set_state(self, state, msg=""):
|
|
if state == "printing":
|
|
self._screen.set_panel_title(
|
|
_("Printing") if self._printer.extrudercount > 0 else _("Working")
|
|
)
|
|
elif state == "complete":
|
|
self.update_progress(1)
|
|
self._screen.set_panel_title(_("Complete"))
|
|
self.buttons['left'].set_label("-")
|
|
self._add_timeout(self._config.get_main_config().getint("job_complete_timeout", 0))
|
|
elif state == "error":
|
|
self._screen.set_panel_title(_("Error"))
|
|
self._screen.show_popup_message(msg)
|
|
self._add_timeout(self._config.get_main_config().getint("job_error_timeout", 0))
|
|
elif state == "cancelling":
|
|
self._screen.set_panel_title(_("Cancelling"))
|
|
elif state == "cancelled" or (state == "standby" and self.state == "cancelled"):
|
|
self._screen.set_panel_title(_("Cancelled"))
|
|
self._add_timeout(self._config.get_main_config().getint("job_cancelled_timeout", 0))
|
|
elif state == "paused":
|
|
self._screen.set_panel_title(_("Paused"))
|
|
elif state == "standby":
|
|
self._screen.set_panel_title(_("Standby"))
|
|
if self.state != state:
|
|
logging.debug(f"Changing job_status state from '{self.state}' to '{state}'")
|
|
self.state = state
|
|
if self.thumb_dialog:
|
|
self.close_dialog(self.thumb_dialog)
|
|
self.show_buttons_for_state()
|
|
|
|
def _add_timeout(self, timeout):
|
|
self._screen.close_screensaver()
|
|
if timeout != 0:
|
|
GLib.timeout_add_seconds(timeout, self.close_panel)
|
|
|
|
def show_buttons_for_state(self):
|
|
self.buttons['button_grid'].remove_row(0)
|
|
self.buttons['button_grid'].insert_row(0)
|
|
if self.state == "printing":
|
|
self.buttons['button_grid'].attach(self.buttons['pause'], 0, 0, 1, 1)
|
|
self.buttons['button_grid'].attach(self.buttons['cancel'], 1, 0, 1, 1)
|
|
self.buttons['button_grid'].attach(self.buttons['fine_tune'], 2, 0, 1, 1)
|
|
self.buttons['button_grid'].attach(self.buttons['control'], 3, 0, 1, 1)
|
|
self.enable_button("pause", "cancel")
|
|
self.can_close = False
|
|
elif self.state == "paused":
|
|
self.buttons['button_grid'].attach(self.buttons['resume'], 0, 0, 1, 1)
|
|
self.buttons['button_grid'].attach(self.buttons['cancel'], 1, 0, 1, 1)
|
|
self.buttons['button_grid'].attach(self.buttons['fine_tune'], 2, 0, 1, 1)
|
|
self.buttons['button_grid'].attach(self.buttons['control'], 3, 0, 1, 1)
|
|
self.enable_button("resume", "cancel")
|
|
self.can_close = False
|
|
else:
|
|
active_extruder = self._printer.get_stat("toolhead", "extruder")
|
|
offset = self._printer.get_stat("gcode_move", "homing_origin")
|
|
self.zoffset = float(offset[2]) if offset else 0
|
|
if self.zoffset != 0 and active_extruder == "extruder":
|
|
if "Z_OFFSET_APPLY_ENDSTOP" in self._printer.available_commands:
|
|
self.buttons['button_grid'].attach(self.buttons["save_offset_endstop"], 0, 0, 1, 1)
|
|
else:
|
|
self.buttons['button_grid'].attach(Gtk.Label(), 0, 0, 1, 1)
|
|
if "Z_OFFSET_APPLY_PROBE" in self._printer.available_commands:
|
|
self.buttons['button_grid'].attach(self.buttons["save_offset_probe"], 1, 0, 1, 1)
|
|
else:
|
|
self.buttons['button_grid'].attach(Gtk.Label(), 1, 0, 1, 1)
|
|
else:
|
|
self.buttons['button_grid'].attach(Gtk.Label(), 0, 0, 1, 1)
|
|
self.buttons['button_grid'].attach(Gtk.Label(), 1, 0, 1, 1)
|
|
|
|
if self.filename:
|
|
self.buttons['button_grid'].attach(self.buttons['restart'], 2, 0, 1, 1)
|
|
self.enable_button("restart")
|
|
else:
|
|
self.disable_button("restart")
|
|
if self.state != "cancelling":
|
|
self.buttons['button_grid'].attach(self.buttons['menu'], 3, 0, 1, 1)
|
|
self.can_close = True
|
|
self.content.show_all()
|
|
|
|
def show_file_thumbnail(self):
|
|
if self._screen.vertical_mode:
|
|
max_width = self._screen.width * 0.9
|
|
max_height = self._screen.height / 4
|
|
else:
|
|
max_width = self._screen.width * .25
|
|
max_height = self._gtk.content_height * 0.47
|
|
width = min(self.labels['thumbnail'].get_allocated_width(), max_width)
|
|
height = min(self.labels['thumbnail'].get_allocated_height(), max_height)
|
|
if width <= 1 or height <= 1:
|
|
width = max_width
|
|
height = max_height
|
|
pixbuf = self.get_file_image(self.filename, width, height)
|
|
if pixbuf is None:
|
|
logging.debug("no pixbuf")
|
|
return
|
|
if image := find_widget(self.labels['thumbnail'], Gtk.Image):
|
|
image.set_from_pixbuf(pixbuf)
|
|
|
|
def show_fullscreen_thumbnail(self, widget):
|
|
pixbuf = self.get_file_image(self.filename, self._screen.width * .9, self._screen.height * .75)
|
|
if pixbuf is None:
|
|
return
|
|
image = Gtk.Image.new_from_pixbuf(pixbuf)
|
|
image.set_vexpand(True)
|
|
self.thumb_dialog = self._gtk.Dialog(self.filename, None, image, self.close_dialog)
|
|
|
|
def close_dialog(self, dialog=None, response_id=None):
|
|
self._gtk.remove_dialog(dialog)
|
|
self.thumb_dialog = None
|
|
|
|
def update_filename(self, filename):
|
|
if not filename or filename == self.filename:
|
|
return
|
|
|
|
self.filename = filename
|
|
logging.debug(f"Updating filename to {filename}")
|
|
self.labels["file"].set_label(os.path.splitext(self.filename)[0])
|
|
self.filename_label = {
|
|
"complete": self.labels['file'].get_label(),
|
|
"current": self.labels['file'].get_label(),
|
|
}
|
|
self.get_file_metadata()
|
|
|
|
def animate_label(self):
|
|
if ellipsized := self.labels['file'].get_layout().is_ellipsized():
|
|
self.filename_label['current'] = self.filename_label['current'][1:]
|
|
self.labels['file'].set_label(self.filename_label['current'] + " " * 6)
|
|
else:
|
|
self.filename_label['current'] = self.filename_label['complete']
|
|
self.labels['file'].set_label(self.filename_label['complete'])
|
|
return True
|
|
|
|
def get_file_metadata(self, response=False):
|
|
if self._files.file_metadata_exists(self.filename):
|
|
self._update_file_metadata()
|
|
elif not response:
|
|
logging.debug("Cannot find file metadata. Listening for updated metadata")
|
|
self._files.request_metadata(self.filename)
|
|
else:
|
|
logging.debug("Cannot load file metadata")
|
|
self.show_file_thumbnail()
|
|
|
|
def _update_file_metadata(self):
|
|
self.file_metadata = self._files.get_file_info(self.filename)
|
|
logging.info(f"Update Metadata. File: {self.filename} Size: {self.file_metadata['size']}")
|
|
if "estimated_time" in self.file_metadata:
|
|
if self.timeleft_type == "slicer":
|
|
self.labels["est_time"].set_label(self.format_time(self.file_metadata['estimated_time']))
|
|
self.labels["slicer_time"].set_label(self.format_time(self.file_metadata['estimated_time']))
|
|
if "object_height" in self.file_metadata:
|
|
self.oheight = float(self.file_metadata['object_height'])
|
|
self.labels['height'].set_label(f"{self.oheight:.2f} {self.mm}")
|
|
if "filament_total" in self.file_metadata:
|
|
self.labels['filament_total'].set_label(f"{float(self.file_metadata['filament_total']) / 1000:.1f} m")
|
|
if "job_id" in self.file_metadata and self.file_metadata['job_id']:
|
|
history = self._screen.apiclient.send_request(f"server/history/job?uid={self.file_metadata['job_id']}")
|
|
if history and history['job']['status'] == "completed" and history['job']['print_duration']:
|
|
self.file_metadata["last_time"] = history['job']['print_duration']
|