zkk d822333489 优化翻译,耗材检测提示和一些细节问题
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
2024-12-31 15:14:35 +08:00

425 lines
19 KiB
Python

# -*- coding: utf-8 -*-
import logging
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import GLib, Gtk, Pango
from jinja2 import Environment
from datetime import datetime
from math import log
from ks_includes.screen_panel import ScreenPanel
class BasePanel(ScreenPanel):
def __init__(self, screen, title=None):
super().__init__(screen, title)
self.current_panel = None
self.time_min = -1
self.time_format = self._config.get_main_config().getboolean("24htime", True)
self.time_update = None
self.titlebar_items = []
self.titlebar_name_type = None
self.current_extruder = None
self.last_usage_report = datetime.now()
self.usage_report = 0
# Action bar buttons
abscale = self.bts * 1.1
self.control['back'] = self._gtk.Button('back', scale=abscale)
self.control['back'].connect("clicked", self.back)
self.control['back'].set_no_show_all(True)
self.control['home'] = self._gtk.Button('main', scale=abscale)
self.control['home'].connect("clicked", self._screen._menu_go_back, True)
self.control['home'].set_no_show_all(True)
self.move = {
"panel": "move",
}
self.control['move'] = self._gtk.Button('move', scale=abscale)
self.control['move'].connect("clicked", self.menu_item_clicked, self.move)
self.control['move'].set_no_show_all(True)
self.extrude = {
"panel": "extrude",
}
self.control['extrude'] = self._gtk.Button('filament', scale=abscale)
self.control['extrude'].connect("clicked", self.menu_item_clicked, self.extrude)
self.control['extrude'].set_no_show_all(True)
self.files = {
"panel": "gcodes",
}
self.control['files'] = self._gtk.Button('files', scale=abscale)
self.control['files'].connect("clicked", self.menu_item_clicked, self.files)
self.control['files'].set_no_show_all(True)
self.more = {
"panel": "more",
}
self.control['more'] = self._gtk.Button('settings', scale=abscale)
self.control['more'].connect("clicked", self._screen._go_to_submenu, "more")
self.control['more'].set_no_show_all(True)
for control in self.control:
self.set_control_sensitive(False, control)
self.control['estop'] = self._gtk.Button('emergency', scale=abscale)
self.control['estop'].connect("clicked", self.emergency_stop)
self.control['estop'].set_no_show_all(True)
self.control['printer_select'] = self._gtk.Button('shuffle', scale=abscale)
self.control['printer_select'].connect("clicked", self._screen.show_printer_select)
self.control['printer_select'].set_no_show_all(True)
self.shorcut = {
"panel": "gcode_macros",
"icon": "custom-script",
}
# Any action bar button should close the keyboard
for item in self.control:
self.control[item].connect("clicked", self._screen.remove_keyboard)
# Action bar
self.action_bar = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
if self._screen.vertical_mode:
self.action_bar.set_hexpand(True)
self.action_bar.set_vexpand(False)
else:
self.action_bar.set_hexpand(False)
self.action_bar.set_vexpand(True)
self.action_bar.get_style_context().add_class('action_bar')
self.action_bar.add(self.control['back'])
self.action_bar.add(self.control['home'])
self.action_bar.add(self.control['move'])
self.action_bar.add(self.control['extrude'])
self.action_bar.add(self.control['files'])
self.action_bar.add(self.control['more'])
self.action_bar.add(self.control['printer_select'])
self.action_bar.add(self.control['estop'])
self.show_printer_select(len(self._config.get_printers()) > 1)
# Titlebar
# This box will be populated by show_heaters
self.control['temp_box'] = Gtk.Box(spacing=10)
self.titlelbl = Gtk.Label(hexpand=True, halign=Gtk.Align.CENTER, ellipsize=Pango.EllipsizeMode.END)
self.control['time'] = Gtk.Label(label="00:00 AM")
self.control['time_box'] = Gtk.Box(halign=Gtk.Align.END)
self.control['time_box'].pack_end(self.control['time'], True, True, 10)
self.titlebar = Gtk.Box(spacing=5, valign=Gtk.Align.CENTER)
self.titlebar.get_style_context().add_class("title_bar")
self.titlebar.add(self.control['temp_box'])
self.titlebar.add(self.titlelbl)
self.titlebar.add(self.control['time_box'])
self.set_title(title)
# Main layout
self.main_grid = Gtk.Grid()
if self._screen.vertical_mode:
self.main_grid.attach(self.titlebar, 0, 0, 1, 1)
self.main_grid.attach(self.content, 0, 1, 1, 1)
self.main_grid.attach(self.action_bar, 0, 2, 1, 1)
self.action_bar.set_orientation(orientation=Gtk.Orientation.HORIZONTAL)
else:
self.main_grid.attach(self.action_bar, 0, 0, 1, 2)
self.action_bar.set_orientation(orientation=Gtk.Orientation.VERTICAL)
self.main_grid.attach(self.titlebar, 1, 0, 1, 1)
self.main_grid.attach(self.content, 1, 1, 1, 1)
self.update_time()
def reload_icons(self):
button: Gtk.Button
for button in self.action_bar.get_children():
img = button.get_image()
name = button.get_name()
pixbuf = img.get_pixbuf()
width = pixbuf.get_width()
height = pixbuf.get_height()
button.set_image(self._gtk.Image(name, width, height))
def show_heaters(self, show=True):
try:
for child in self.control['temp_box'].get_children():
self.control['temp_box'].remove(child)
devices = self._printer.get_temp_devices()
if not show or not devices:
return
img_size = self._gtk.img_scale * self.bts
for device in devices:
self.labels[device] = Gtk.Label(ellipsize=Pango.EllipsizeMode.START)
self.labels[f'{device}_box'] = Gtk.Box()
icon = self.get_icon(device, img_size)
if icon is not None:
self.labels[f'{device}_box'].pack_start(icon, False, False, 3)
self.labels[f'{device}_box'].pack_start(self.labels[device], False, False, 0)
# Limit the number of items according to resolution
nlimit = int(round(log(self._screen.width, 10) * 5 - 10.5))
n = 0
if len(self._printer.get_tools()) > (nlimit - 1):
self.current_extruder = self._printer.get_stat("toolhead", "extruder")
if self.current_extruder and f"{self.current_extruder}_box" in self.labels:
self.control['temp_box'].add(self.labels[f"{self.current_extruder}_box"])
else:
self.current_extruder = False
for device in devices:
if n >= nlimit:
break
if device.startswith("extruder") and self.current_extruder is False:
self.control['temp_box'].add(self.labels[f"{device}_box"])
n += 1
elif device.startswith("heater"):
self.control['temp_box'].add(self.labels[f"{device}_box"])
n += 1
for device in devices:
# Users can fill the bar if they want
if n >= nlimit + 1:
break
name = device.split()[1] if len(device.split()) > 1 else device
for item in self.titlebar_items:
if name == item:
self.control['temp_box'].add(self.labels[f"{device}_box"])
n += 1
break
self.control['temp_box'].show_all()
except Exception as e:
logging.debug(f"Couldn't create heaters box: {e}")
def get_icon(self, device, img_size):
if device.startswith("extruder"):
if self._printer.extrudercount > 1:
if device == "extruder":
device = "extruder0"
return self._gtk.Image(f"extruder-{device[8:]}", img_size, img_size)
return self._gtk.Image("extruder", img_size, img_size)
elif device.startswith("heater_bed"):
return self._gtk.Image("bed", img_size, img_size)
elif device.startswith("heater_generic chamber"):
return self._gtk.Image("chamber", img_size, img_size)
# Extra items
elif self.titlebar_name_type is not None:
# The item has a name, do not use an icon
return None
elif device.startswith("temperature_fan"):
return self._gtk.Image("fan", img_size, img_size)
elif device.startswith("heater_generic"):
return self._gtk.Image("heater", img_size, img_size)
else:
return self._gtk.Image("heat-up", img_size, img_size)
def activate(self):
if self.time_update is None:
self.time_update = GLib.timeout_add_seconds(1, self.update_time)
def add_content(self, panel):
printing = self._printer and self._printer.state in {"printing", "paused"}
connected = self._printer and self._printer.state not in {'disconnected', 'startup', 'shutdown', 'error'}
self.control['estop'].set_visible(printing)
self.control['move'].set_visible(not printing and connected)
self.control['extrude'].set_visible(not printing and connected)
self.control['files'].set_visible(not printing and connected)
self.control['more'].set_visible(not printing and connected)
self.control['home'].set_visible(connected)
self.show_shortcut(connected)
self.show_heaters(connected)
for control in ('back', 'home'):
self.set_control_sensitive(len(self._screen._cur_panels) > 1, control=control)
panels_has_back = ['gcodes', 'temperature']
cur_panel_count = len(self._screen._cur_panels)
is_last_panel_in_back_list = self._screen._cur_panels[-1] in panels_has_back
should_show_back = (cur_panel_count > 2 or is_last_panel_in_back_list or
(self._screen._cur_panels[0] != 'main_menu' and cur_panel_count >= 2))
self.control['back'].set_visible(should_show_back)
if any(child.get_visible() for child in self.action_bar.get_children()):
self.show_action_bar()
else:
self.hide_action_bar()
self.current_panel = panel
self.set_title(panel.title)
self.content.add(panel.content)
def back(self, widget=None):
if self.current_panel is None:
return
self._screen.remove_keyboard()
if hasattr(self.current_panel, "back") \
and not self.current_panel.back() \
or not hasattr(self.current_panel, "back"):
self._screen._menu_go_back()
def process_update(self, action, data):
if action == "notify_proc_stat_update":
cpu = data["system_cpu_usage"]["cpu"]
memory = (data["system_memory"]["used"] / data["system_memory"]["total"]) * 100
error = "message_popup_error"
ctx = self.titlebar.get_style_context()
msg = f"CPU: {cpu:2.0f}% RAM: {memory:2.0f}%"
if cpu > 80 or memory > 85:
if self.usage_report < 3:
self.usage_report += 1
return
self.last_usage_report = datetime.now()
if not ctx.has_class(error):
ctx.add_class(error)
self._screen.log_notification(f"{self._screen.connecting_to_printer}: {msg}", 2)
self.titlelbl.set_label(msg)
elif ctx.has_class(error):
if (datetime.now() - self.last_usage_report).seconds < 5:
self.titlelbl.set_label(msg)
return
self.usage_report = 0
ctx.remove_class(error)
self.titlelbl.set_label(f"{self._screen.connecting_to_printer}")
return
if action == "notify_update_response":
if self.update_dialog is None:
self.show_update_dialog()
if 'message' in data:
self.labels['update_progress'].set_text(
f"{self.labels['update_progress'].get_text().strip()}\n"
f"{data['message']}\n")
if 'complete' in data and data['complete']:
logging.info("Update complete")
if self.update_dialog is not None:
try:
self.update_dialog.set_response_sensitive(Gtk.ResponseType.OK, True)
self.update_dialog.get_widget_for_response(Gtk.ResponseType.OK).show()
except AttributeError:
logging.error("error trying to show the updater button the dialog might be closed")
self._screen.updating = False
for dialog in self._screen.dialogs:
self._gtk.remove_dialog(dialog)
return
if action != "notify_status_update" or self._screen.printer is None:
return
for device in self._printer.get_temp_devices():
temp = self._printer.get_stat(device, "temperature")
if temp and device in self.labels:
name = ""
if not (device.startswith("extruder") or device.startswith("heater_bed")):
if self.titlebar_name_type == "full":
name = device.split()[1] if len(device.split()) > 1 else device
name = f'{self.prettify(name)}: '
elif self.titlebar_name_type == "short":
name = device.split()[1] if len(device.split()) > 1 else device
name = f"{name[:1].upper()}: "
self.labels[device].set_label(f"{name}{temp:.0f}°")
if (self.current_extruder and 'toolhead' in data and 'extruder' in data['toolhead']
and data["toolhead"]["extruder"] != self.current_extruder):
self.control['temp_box'].remove(self.labels[f"{self.current_extruder}_box"])
self.current_extruder = data["toolhead"]["extruder"]
self.control['temp_box'].pack_start(self.labels[f"{self.current_extruder}_box"], True, True, 3)
self.control['temp_box'].reorder_child(self.labels[f"{self.current_extruder}_box"], 0)
self.control['temp_box'].show_all()
return False
def remove(self, widget):
self.content.remove(widget)
def set_control_sensitive(self, value=True, control='home'):
self.control[control].set_sensitive(value)
def show_shortcut(self, show=True):
show = (
show
and self._config.get_main_config().getboolean('side_macro_shortcut', True)
and self._printer.get_printer_status_data()["printer"]["gcode_macros"]["count"] > 0
and self._screen._cur_panels[-1] != 'printer_select'
)
self.set_control_sensitive(self._screen._cur_panels[-1] != self.shorcut['panel'])
self.set_control_sensitive(self._screen._cur_panels[-1] != self.move['panel'], control='move')
self.set_control_sensitive(self._screen._cur_panels[-1] != self.extrude['panel'], control='extrude')
self.set_control_sensitive(self._screen._cur_panels[-1] != self.files['panel'], control='files')
self.set_control_sensitive(self._screen._cur_panels[-1] != self.more['panel'], control='more')
def show_action_bar(self):
self.action_bar.set_size_request(self._gtk.action_bar_width, self._gtk.action_bar_height)
self.control['home'].set_visible(True)
def hide_action_bar(self):
self.action_bar.set_size_request(-1, -1)
self.control['home'].set_visible(False)
def show_printer_select(self, show=True):
self.control['printer_select'].set_visible(
show and 'printer_select' not in self._screen._cur_panels
)
def set_title(self, title):
self.titlebar.get_style_context().remove_class("message_popup_error")
if not title:
self.titlelbl.set_label(f"{self._screen.connecting_to_printer}")
return
try:
env = Environment(extensions=["jinja2.ext.i18n"], autoescape=True)
env.install_gettext_translations(self._config.get_lang())
j2_temp = env.from_string(title)
title = j2_temp.render()
except Exception as e:
logging.debug(f"Error parsing jinja for title: {title}\n{e}")
title_text = f"{self._screen.connecting_to_printer} | {title}" if self._screen.connecting_to_printer is not None else title
self.titlelbl.set_label(title_text)
def update_time(self):
now = datetime.now()
confopt = self._config.get_main_config().getboolean("24htime", True)
if now.minute != self.time_min or self.time_format != confopt:
if confopt:
self.control['time'].set_text(f'{now:%H:%M }')
else:
self.control['time'].set_text(f'{now:%I:%M %p}')
self.time_min = now.minute
self.time_format = confopt
return True
def set_ks_printer_cfg(self, printer):
ScreenPanel.ks_printer_cfg = self._config.get_printer_config(printer)
if self.ks_printer_cfg is not None:
self.titlebar_name_type = self.ks_printer_cfg.get("titlebar_name_type", None)
titlebar_items = self.ks_printer_cfg.get("titlebar_items", None)
if titlebar_items is not None:
self.titlebar_items = [str(i.strip()) for i in titlebar_items.split(',')]
logging.info(f"Titlebar name type: {self.titlebar_name_type} items: {self.titlebar_items}")
else:
self.titlebar_items = []
def show_update_dialog(self):
if self.update_dialog is not None:
return
button = [{"name": _("Finish"), "response": Gtk.ResponseType.OK}]
self.labels['update_progress'] = Gtk.Label(hexpand=True, vexpand=True, ellipsize=Pango.EllipsizeMode.END)
self.labels['update_scroll'] = self._gtk.ScrolledWindow(steppers=False)
self.labels['update_scroll'].set_property("overlay-scrolling", True)
self.labels['update_scroll'].add(self.labels['update_progress'])
self.labels['update_scroll'].connect("size-allocate", self._autoscroll)
dialog = self._gtk.Dialog(_("Updating"), button, self.labels['update_scroll'], self.finish_updating)
dialog.connect("delete-event", self.close_update_dialog)
dialog.set_response_sensitive(Gtk.ResponseType.OK, False)
dialog.get_widget_for_response(Gtk.ResponseType.OK).hide()
self.update_dialog = dialog
self._screen.updating = True
def finish_updating(self, dialog, response_id):
if response_id != Gtk.ResponseType.OK:
return
logging.info("Finishing update")
self._screen.updating = False
self._gtk.remove_dialog(dialog)
self._screen._menu_go_back(home=True)
def close_update_dialog(self, *args):
logging.info("Closing update dialog")
if self.update_dialog in self._screen.dialogs:
self._screen.dialogs.remove(self.update_dialog)
self.update_dialog = None
self._screen._menu_go_back(home=True)