Frédéric Beaucamp 84f7c1acff
Improve params pattern to catch more macros ()
The current pattern can only take into account params followed by default. The proposal catches more parameters and removes white spaces if present.
2024-03-09 12:31:51 -03:00

182 lines
7.2 KiB
Python

import logging
import re
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib, Pango
from ks_includes.screen_panel import ScreenPanel
class Panel(ScreenPanel):
def __init__(self, screen, title):
super().__init__(screen, title)
self.sort_reverse = False
self.sort_btn = self._gtk.Button("arrow-up", _("Name"), "color1", self.bts, Gtk.PositionType.RIGHT, 1)
self.sort_btn.connect("clicked", self.change_sort)
self.sort_btn.set_hexpand(True)
self.sort_btn.get_style_context().add_class("buttons_slim")
self.options = {}
self.macros = {}
self.menu = ['macros_menu']
adjust = self._gtk.Button("settings", " " + _("Settings"), "color2", self.bts, Gtk.PositionType.LEFT, 1)
adjust.get_style_context().add_class("buttons_slim")
adjust.connect("clicked", self.load_menu, 'options', _("Settings"))
adjust.set_hexpand(False)
sbox = Gtk.Box(vexpand=False)
sbox.pack_start(self.sort_btn, True, True, 5)
sbox.pack_start(adjust, True, True, 5)
self.labels['macros_list'] = self._gtk.ScrolledWindow()
self.labels['macros'] = Gtk.Grid()
self.labels['macros_list'].add(self.labels['macros'])
self.labels['macros_menu'] = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, vexpand=True)
self.labels['macros_menu'].pack_start(sbox, False, False, 0)
self.labels['macros_menu'].pack_start(self.labels['macros_list'], True, True, 0)
self.content.add(self.labels['macros_menu'])
self.labels['options_menu'] = self._gtk.ScrolledWindow()
self.labels['options'] = Gtk.Grid()
self.labels['options_menu'].add(self.labels['options'])
def activate(self):
while len(self.menu) > 1:
self.unload_menu()
self.reload_macros()
def add_gcode_macro(self, macro):
section = self._printer.get_macro(macro)
if section:
if "rename_existing" in section:
return
if "gcode" in section:
gcode = section["gcode"].split("\n")
else:
logging.error(f"gcode not found in {macro}\n{section}")
return
else:
logging.debug(f"Couldn't load {macro}\n{section}")
return
name = Gtk.Label(hexpand=True, vexpand=True, halign=Gtk.Align.START, valign=Gtk.Align.CENTER,
wrap=True, wrap_mode=Pango.WrapMode.WORD_CHAR)
name.set_markup(f"<big><b>{macro}</b></big>")
btn = self._gtk.Button("resume", style="color3")
btn.connect("clicked", self.run_gcode_macro, macro)
btn.set_hexpand(False)
btn.set_halign(Gtk.Align.END)
labels = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
labels.add(name)
row = Gtk.Box(spacing=5)
row.get_style_context().add_class("frame-item")
row.add(labels)
row.add(btn)
self.macros[macro] = {
"row": row,
"params": {},
}
pattern = r'params\.(?P<param>[A-Z_0-9]+)(?:\s*\|.*\s*default\(\s*(?P<default>[^\)]+)\))?'
i = 0
for line in gcode:
if line.startswith("{") and "params." in line:
result = re.search(pattern, line)
if result:
result = result.groupdict()
default = result["default"] if "default" in result else ""
entry = Gtk.Entry(placeholder_text=default)
self.macros[macro]["params"].update({result["param"]: entry})
for param in self.macros[macro]["params"]:
labels.add(Gtk.Label(param))
self.macros[macro]["params"][param].connect("focus-in-event", self._screen.show_keyboard)
self.macros[macro]["params"][param].connect("focus-out-event", self._screen.remove_keyboard)
labels.add(self.macros[macro]["params"][param])
def run_gcode_macro(self, widget, macro):
params = ""
for param in self.macros[macro]["params"]:
value = self.macros[macro]["params"][param].get_text()
if value:
params += f' {param}={value}'
self._screen.show_popup_message(f"{macro} {params}", 1)
self._screen._send_action(widget, "printer.gcode.script", {"script": f"{macro}{params}"})
def change_sort(self, widget):
self.sort_reverse ^= True
if self.sort_reverse:
self.sort_btn.set_image(self._gtk.Image("arrow-down", self._gtk.img_scale * self.bts))
else:
self.sort_btn.set_image(self._gtk.Image("arrow-up", self._gtk.img_scale * self.bts))
self.sort_btn.show()
GLib.idle_add(self.reload_macros)
def reload_macros(self):
self.labels['macros'].remove_column(0)
self.macros = {}
self.options = {}
self.labels['options'].remove_column(0)
self.load_gcode_macros()
return False
def load_gcode_macros(self):
for macro in self._printer.get_gcode_macros():
self.options[macro] = {
"name": macro,
"section": f"displayed_macros {self._screen.connected_printer}",
}
show = self._config.get_config().getboolean(self.options[macro]["section"], macro.lower(), fallback=True)
if macro not in self.macros and show:
self.add_gcode_macro(macro)
for macro in list(self.options):
self.add_option('options', self.options, macro, self.options[macro])
macros = sorted(self.macros, reverse=self.sort_reverse, key=str.casefold)
for macro in macros:
pos = macros.index(macro)
self.labels['macros'].insert_row(pos)
self.labels['macros'].attach(self.macros[macro]['row'], 0, pos, 1, 1)
self.labels['macros'].show_all()
def add_option(self, boxname, opt_array, opt_name, option):
name = Gtk.Label(hexpand=True, vexpand=True, halign=Gtk.Align.START, valign=Gtk.Align.CENTER,
wrap=True, wrap_mode=Pango.WrapMode.WORD_CHAR)
name.set_markup(f"<big><b>{option['name']}</b></big>")
box = Gtk.Box(vexpand=False)
switch = Gtk.Switch(hexpand=False, vexpand=False,
width_request=round(self._gtk.font_size * 7),
height_request=round(self._gtk.font_size * 3.5),
active=self._config.get_config().getboolean(option['section'], opt_name, fallback=True))
switch.connect("notify::active", self.switch_config_option, option['section'], opt_name)
box.add(switch)
dev = Gtk.Box(hexpand=True, vexpand=False, valign=Gtk.Align.CENTER)
dev.get_style_context().add_class("frame-item")
dev.add(name)
dev.add(box)
opt_array[opt_name] = {
"name": option['name'],
"row": dev
}
opts = sorted(self.options, key=str.casefold)
pos = opts.index(opt_name)
self.labels[boxname].insert_row(pos)
self.labels[boxname].attach(opt_array[opt_name]['row'], 0, pos, 1, 1)
self.labels[boxname].show_all()
def back(self):
if len(self.menu) > 1:
self.unload_menu()
self.reload_macros()
return True
return False