245 lines
9.5 KiB
Python
245 lines
9.5 KiB
Python
import configparser
|
|
import logging
|
|
import os.path
|
|
import pathlib
|
|
|
|
import gi
|
|
|
|
gi.require_version("Gtk", "3.0")
|
|
from datetime import datetime
|
|
|
|
from gi.repository import GLib, Gtk
|
|
|
|
from ks_includes.KlippyFactory import KlippyFactory
|
|
from ks_includes.ModelConfig import ModelConfig
|
|
from ks_includes.screen_panel import ScreenPanel
|
|
|
|
|
|
class Panel(ScreenPanel):
|
|
def __init__(self, screen, title):
|
|
title = title or "factory settings"
|
|
super().__init__(screen, title)
|
|
klipperscreendir = pathlib.Path(__file__).parent.resolve().parent
|
|
self.model_list_path = os.path.join(klipperscreendir, "config", "model_menu.conf")
|
|
self.model_list_config = configparser.ConfigParser()
|
|
self.model_list_config.read(self.model_list_path, encoding="utf-8")
|
|
self.last_drop_time = datetime.now()
|
|
self.factory_settings_list = [
|
|
{
|
|
"Select Model": {
|
|
"section": "main",
|
|
"name": _("Select Model"),
|
|
"type": "button",
|
|
"callback": self.show_select_model,
|
|
}
|
|
},
|
|
{
|
|
"Enable Guide": {
|
|
"section": "main",
|
|
"name": _("Pack"),
|
|
"type": "button",
|
|
"callback": self.reset_factory_settings,
|
|
}
|
|
},
|
|
{
|
|
"License key": {
|
|
"section": "main",
|
|
"name": _("License key"),
|
|
"type": "button",
|
|
"callback": self.license_key,
|
|
}
|
|
},
|
|
{
|
|
"version_info": {
|
|
"section": "main",
|
|
"name": _("Version Selection"),
|
|
"type": "dropdown",
|
|
"value": "stable",
|
|
"callback": self.version_selection,
|
|
"options": [
|
|
{"name": _("Stable") + " " + _("(default)"), "value": "stable"},
|
|
{"name": _("Beta"), "value": "beta"},
|
|
{"name": _("Dev"), "value": "dev"},
|
|
],
|
|
}
|
|
},
|
|
]
|
|
self.settings = {}
|
|
self.select_model = False
|
|
self.select_model_version = False
|
|
self.labels["setting_menu"] = self._gtk.ScrolledWindow()
|
|
self.labels["settings"] = Gtk.Grid()
|
|
self.labels["setting_menu"].add(self.labels["settings"])
|
|
self.option_res = {}
|
|
for option in self.factory_settings_list:
|
|
name = list(option)[0]
|
|
self.option_res.update(self.add_option("settings", self.settings, name, option[name]))
|
|
|
|
version_dropdown = self.option_res.get("version_info")
|
|
version_dropdown.connect("notify::popup-shown", self.on_popup_shown)
|
|
|
|
self.content.add(self.labels["setting_menu"])
|
|
self.content.show_all()
|
|
|
|
def back(self):
|
|
if self.select_model_version:
|
|
self.hide_select_model_version()
|
|
return True
|
|
if self.select_model:
|
|
self.hide_select_model()
|
|
return True
|
|
return False
|
|
|
|
def on_popup_shown(self, combo_box, param):
|
|
if combo_box.get_property("popup-shown"):
|
|
logging.debug("Dropdown popup show")
|
|
self.last_drop_time = datetime.now()
|
|
else:
|
|
elapsed = (datetime.now() - self.last_drop_time).total_seconds()
|
|
if elapsed < 0.2:
|
|
logging.debug(f"Dropdown closed too fast ({elapsed}s)")
|
|
GLib.timeout_add(50, lambda: self.dropdown_keep_open(combo_box))
|
|
return
|
|
logging.debug("Dropdown popup close")
|
|
|
|
def dropdown_keep_open(self, combo_box):
|
|
if isinstance(combo_box, Gtk.ComboBox):
|
|
combo_box.popup()
|
|
return False
|
|
|
|
def create_list_menu(self, menu_list, callback=None):
|
|
if "model_menu" in self.labels:
|
|
del self.labels["model_menu"]
|
|
self.labels["model_menu"] = self._gtk.ScrolledWindow()
|
|
self.labels["model"] = Gtk.Grid()
|
|
self.labels["model_menu"].add(self.labels["model"])
|
|
self.models = {}
|
|
for value in menu_list:
|
|
self.models[value] = {
|
|
"name": value,
|
|
"type": "button",
|
|
"callback": callback,
|
|
}
|
|
self.add_option("model", self.models, value, self.models[value])
|
|
|
|
def show_select_model(self, widget=None, option=None):
|
|
self.create_list_menu(self.model_list_config.sections(), self._on_model_selected)
|
|
for child in self.content.get_children():
|
|
self.content.remove(child)
|
|
self.content.add(self.labels["model_menu"])
|
|
self.content.show_all()
|
|
self.select_model = True
|
|
|
|
def show_select_model_version(self, model):
|
|
versions_str = self.model_list_config[model].get("versions", "")
|
|
versions = [v.strip() for v in versions_str.split(",") if v.strip()]
|
|
self.create_list_menu(versions, self._on_version_selected)
|
|
self.select_model_version = True
|
|
self.model = model
|
|
|
|
def _on_model_selected(self, widget, event):
|
|
for child in self.content.get_children():
|
|
self.content.remove(child)
|
|
self.show_select_model_version(event)
|
|
self.content.add(self.labels["model_menu"])
|
|
self.content.show_all()
|
|
|
|
def _on_version_selected(self, widget, version):
|
|
if not hasattr(self, "model_config") or self.model_config is None:
|
|
self.model_config = ModelConfig()
|
|
self.model_config.generate_config(self.model, version)
|
|
|
|
def hide_select_model_version(self):
|
|
for child in self.content.get_children():
|
|
self.content.remove(child)
|
|
self.show_select_model()
|
|
self.select_model_version = False
|
|
|
|
def hide_select_model(self):
|
|
for child in self.content.get_children():
|
|
self.content.remove(child)
|
|
if "setting_menu" in self.labels:
|
|
self.content.add(self.labels["setting_menu"])
|
|
self.content.show_all()
|
|
self.select_model = False
|
|
|
|
def license_key(self, *args):
|
|
self._screen.show_panel("license", title="license", remove_all=False, full=True)
|
|
|
|
def reset_factory_settings(self, *args):
|
|
buttons = [
|
|
{"name": _("Accept"), "response": Gtk.ResponseType.OK, "style": "dialog-error"},
|
|
{"name": _("Cancel"), "response": Gtk.ResponseType.CANCEL, "style": "dialog-info"},
|
|
]
|
|
|
|
text = _("Are you sure?\n") + "\n\n" + _("The system will reboot!")
|
|
label = Gtk.Label(wrap=True, vexpand=True)
|
|
label.set_markup(text)
|
|
label.set_margin_top(100)
|
|
|
|
checkbox = Gtk.CheckButton(label=" " + _("Enable Registration Code"))
|
|
checkbox.set_halign(Gtk.Align.CENTER)
|
|
checkbox.set_valign(Gtk.Align.CENTER)
|
|
|
|
grid = Gtk.Grid(row_homogeneous=True, column_homogeneous=True)
|
|
grid.set_row_spacing(20)
|
|
grid.set_column_spacing(0)
|
|
grid.attach(label, 0, 0, 1, 1)
|
|
if self._screen.license.is_interface_valid() and self._screen.license.is_active():
|
|
grid.attach(checkbox, 0, 1, 1, 1)
|
|
|
|
self._gtk.Dialog(
|
|
_("factory settings"),
|
|
buttons,
|
|
grid,
|
|
self.confirm_factory_reset_production,
|
|
checkbox,
|
|
)
|
|
|
|
def confirm_factory_reset_production(self, dialog, response_id, checkbox):
|
|
self._gtk.remove_dialog(dialog)
|
|
if response_id == Gtk.ResponseType.OK:
|
|
if checkbox.get_active():
|
|
if self._screen.license.is_interface_valid():
|
|
self._screen.license.enabled_registration()
|
|
KlippyFactory.production_factory_reset(self._screen._ws.klippy, self._config)
|
|
|
|
def version_selection(self, val):
|
|
config_updater = ConfigMoonrakerUpdateManager()
|
|
config_updater.enable_version_selection(val)
|
|
if val == "stable":
|
|
self._screen._send_action(None, "machine.update.rollback", {"name": "klipper"})
|
|
self._screen._send_action(None, "machine.update.rollback", {"name": "KlipperScreen"})
|
|
self._screen._send_action(None, "machine.update.rollback", {"name": "moonraker"})
|
|
else:
|
|
self._screen._send_action(None, "machine.services.restart", {"service": "moonraker"})
|
|
logging.info(f"version selection:{val}")
|
|
|
|
class ConfigMoonrakerUpdateManager:
|
|
def __init__(self):
|
|
self.moonraker_config = configparser.ConfigParser()
|
|
self.moonraker_config_path = "/home/klipper/printer_data/config/moonraker.conf"
|
|
|
|
def _set_update_manager_channel(self, section, channel="dev"):
|
|
if not self.moonraker_config.has_section(section):
|
|
self.moonraker_config.add_section(section)
|
|
self.moonraker_config.set(section, "channel", channel)
|
|
|
|
def enable_version_selection(self, val):
|
|
update_managet_list = ["update_manager", "update_manager klipper", "update_manager KlipperScreen"]
|
|
try:
|
|
self.moonraker_config.read(self.moonraker_config_path)
|
|
|
|
if "dev" == val or "beta" == val:
|
|
for section in update_managet_list:
|
|
self._set_update_manager_channel(section, val)
|
|
else:
|
|
for section in update_managet_list:
|
|
self.moonraker_config.remove_section(section)
|
|
|
|
with open(self.moonraker_config_path, "w") as configfile:
|
|
self.moonraker_config.write(configfile)
|
|
except Exception as e:
|
|
msg = f"Error reading or writing config: \n{e}"
|
|
logging.exception(msg)
|