From 4af1997682d63acd4235d6ff8af550b8ea9b2d92 Mon Sep 17 00:00:00 2001 From: Ircama Date: Sun, 17 Nov 2024 18:59:55 +0100 Subject: [PATCH] Improved debug console --- .gitignore | 2 +- ui.py | 563 +++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 439 insertions(+), 126 deletions(-) diff --git a/.gitignore b/.gitignore index 984f09a..0a8a145 100644 --- a/.gitignore +++ b/.gitignore @@ -163,4 +163,4 @@ devices.xml *.srs *.pickle -.python_history +.console_history diff --git a/ui.py b/ui.py index 67629fa..cd61248 100644 --- a/ui.py +++ b/ui.py @@ -36,10 +36,10 @@ from find_printers import PrinterScanner -VERSION = "5.2.18" +VERSION = "5.2.19" NO_CONF_ERROR = ( - "[ERROR] Please select a printer model and a valid IP address," + " Please select a printer model and a valid IP address," " or press 'Detect Printers'.\n" ) @@ -53,7 +53,7 @@ class History(list): - def __init__(self, history_file=".python_history"): + def __init__(self, history_file=".console_history"): super().__init__() self.history_file = history_file @@ -89,7 +89,15 @@ def __init__(self, main, master, **kw): banner = kw.pop('banner', 'Python %s\n' % sys.version) self._prompt1 = kw.pop('prompt1') self._prompt2 = kw.pop('prompt2') - tk.Text.__init__(self, master, **kw) + super().__init__(master, **kw) + self.tag_configure("errors", foreground="red") + font_config = self.tag_cget("errors", "font") + font_obj = tkfont.nametofont(self.cget("font")) + font_size = font_obj.actual("size") + self.tag_configure("errors", font=("Courier", font_size - 2)) + self.tag_configure("banner", foreground="darkred") + self.tag_configure("prompt", foreground="green", font=("Courier", font_size - 2)) + self.tag_configure("input_color", foreground="blue") # --- history self.history = History() self._hist_item = 0 @@ -108,6 +116,20 @@ def __init__(self, main, master, **kw): self.mark_set('input', 'insert') self.mark_gravity('input', 'left') + # Bind right-click (context menu) + self.bind("", self.show_context_menu) + + # Create the context menu + self.context_menu = Menu(self, tearoff=0) + self.context_menu.add_command(label="Cut", command=self.cut) + self.context_menu.add_command(label="Copy", command=self.copy) + self.context_menu.add_command(label="Paste", command=self.paste) + self.context_menu.add_separator() + self.context_menu.add_command(label="Clear", command=self.clear) + + # Add the menu bar + self.create_menu(master) + # --- bindings self.bind('', self.on_ctrl_return) self.bind('', self.on_shift_return) @@ -121,14 +143,175 @@ def __init__(self, main, master, **kw): self.bind('', self.on_ctrl_c) self.bind('<>', self.on_paste) - @property - def h(self): - """Override the history property to return the formatted history as a string.""" - self.insert( - 'end', "\n".join( - f"{i + 1}: {command}" for i, command in enumerate(self.history) - ) + '\n' + def create_menu(self, master): + """Create the menu bar at the top of the window.""" + menu_bar = Menu(master) + master.config(menu=menu_bar) + + # File menu + file_menu = Menu(menu_bar, tearoff=0) + file_menu.add_command(label="Clear Console", command=self.clear_console) + file_menu.add_command(label="History", command=self.dump_history) + file_menu.add_command(label="Close Window", command=master.destroy) + file_menu.add_command(label="Quit Application", command=self.quit) + menu_bar.add_cascade(label="File", menu=file_menu) + + # Edit menu + edit_menu = Menu(menu_bar, tearoff=0) + edit_menu.add_command(label="Cut", command=self.cut) + edit_menu.add_command(label="Copy", command=self.copy) + edit_menu.add_command(label="Paste", command=self.paste) + menu_bar.add_cascade(label="Edit", menu=edit_menu) + + # Help menu + help_menu = Menu(menu_bar, tearoff=0) + help_menu.add_command(label="Usage", command=self.show_help) + help_menu.add_command(label="About", command=self.show_about) + menu_bar.add_cascade(label="Help", menu=help_menu) + + def clear_console(self): + """Clear the text in the console.""" + self.clear() + + def show_about(self): + """Show the About dialog.""" + messagebox.showinfo( + "About", + "epson_print_conf Debug Console." + ) + + def show_help(self): + """Open a separate window with help text.""" + help_window = tk.Toplevel(self) + help_window.title("Help") + help_window.geometry("1000x400") + + # Add a scrollbar and text widget + scrollbar = tk.Scrollbar(help_window) + scrollbar.pack(side="right", fill="y") + + help_text = tk.Text(help_window, wrap="word", yscrollcommand=scrollbar.set) + help_text.tag_configure("title", foreground="purple") + help_text.tag_configure("section", foreground="blue") + + help_text.insert( + tk.END, + 'Welcome to the epson_print_conf Debug Console\n\n', + "title" + ) + help_text.insert( + tk.END, + 'Features:\n\n', + "section" + ) + help_text.insert( + tk.END, + ( + "- Clear Console: Clears all text in the console.\n" + "- Context Menu: Right-click for cut, copy, paste, or clear.\n" + "- Help: Provides this text.\n\n" + ) + ) + help_text.insert( + tk.END, + 'Keyboard Shortcuts from the main window:\n\n', + "section" + ) + help_text.insert( + tk.END, + ( + "- F7: Open the debug console.\n\n" + ) + ) + help_text.insert( + tk.END, + 'Tokens:\n\n', + "section" + ) + help_text.insert( + tk.END, + ( + "self: EpsonPrinterUI self\n" + "master: TextConsole widget\n" + "kw: kw dictionary ({'width': 50, 'wrap': 'word'})\n" + "local: TextConsole self\n\n" + ) + ) + help_text.insert( + tk.END, + 'Examples of commands:\n\n', + "section" ) + help_text.insert( + tk.END, + ( + "self.printer.model\n" + "self.printer.reverse_caesar(b'Hpttzqjv')\n" + 'self.printer.reverse_caesar(bytes.fromhex("48 62 7B 62 6F 6A 62 2B"))\n' + 'import pprint;pprint.pprint(self.printer.status_parser(self.printer.snmp_mib("1.3.6.1.4.1.1248.1.2.2.1.1.1.4.1")[1]))\n' + "self.printer.read_eeprom_many([0])\n" + "self.printer.read_eeprom(0)\n" + "self.printer.snmp_mib(self.printer.eeprom_oid_read_address(0))\n" + "self.printer.snmp_mib('1.3.6.1.4.1.1248.1.2.2.44.1.1.2.1.124.124.7.0.25.7.65.190.160.0.0')\n" + "self.get_ti_date(cursor=True)" + ) + ) + help_text.config(state="disabled") # Make the text read-only + help_text.pack(fill="both", expand=True) + scrollbar.config(command=help_text.yview) + + def show_context_menu(self, event): + """Show the context menu at the cursor position.""" + self.context_menu.post(event.x_root, event.y_root) + + def cut(self): + """Cut the selected text to the clipboard.""" + try: + self.event_generate("<>") + except tk.TclError: + pass + + def copy(self): + """Copy the selected text to the clipboard.""" + try: + self.event_generate("<>") + except tk.TclError: + pass + + def paste(self): + """Paste text from the clipboard.""" + try: + self.event_generate("<>") + except tk.TclError: + pass + + def clear(self): + """Clear all text from the console.""" + self.delete("1.0", "end") + self.insert("1.0", self._prompt1) # Reinsert the prompt + self.delete('input', 'insert lineend') + + def dump_history(self): + """Open a separate window with the output of the history.""" + history_window = tk.Toplevel(self) + history_window.title("History") + history_window.geometry("1000x400") + + # Add a scrollbar and text widget + scrollbar = tk.Scrollbar(history_window) + scrollbar.pack(side="right", fill="y") + + history_txt = tk.Text( + history_window, wrap="word", yscrollcommand=scrollbar.set + ) + history_txt.tag_configure("title", foreground="red") + history_txt.tag_configure("counter", foreground="blue") + for i, command in enumerate(self.history): + history_txt.insert('end', f"{i + 1}\t| ", "counter") + history_txt.insert('end', f"{command}\n") + history_txt.config(state="disabled") # Make the text read-only + history_txt.pack(fill="both", expand=True) + scrollbar.config(command=history_txt.yview) def on_ctrl_c(self, event): """Copy selected code, removing prompts first""" @@ -171,15 +354,20 @@ def on_key_press(self, event): """Prevent text insertion in command history""" if self.compare('insert', '<', 'input') and event.keysym not in ['Left', 'Right']: self._hist_item = len(self.history) - self.mark_set('insert', 'input lineend') if not event.char.isalnum(): return 'break' + else: + if event.keysym not in ['Return']: + self.tag_add("input_color", "input", "insert lineend") def on_key_release(self, event): """Reset history scrolling""" if self.compare('insert', '<', 'input') and event.keysym not in ['Left', 'Right']: self._hist_item = len(self.history) return 'break' + else: + if event.keysym not in ['Return']: + self.tag_add("input_color", "input", "insert lineend") def on_up(self, event): """Handle up arrow key press""" @@ -212,8 +400,16 @@ def on_up(self, event): self.insert_cmd(item) # Update input with the matched command self.mark_set('insert', index) else: - # No match: reset the history index - self._hist_item = hist_item + # No match: use the last history item + self._hist_item = len(self.history) - 1 + if self._hist_item >= 0: + item = self.history[self._hist_item] + index = self.index('insert') + self.insert_cmd(item) # Update input with the last command + self.mark_set('insert', index) + else: + # No history at all, do nothing + self._hist_item = hist_item return 'break' @@ -336,6 +532,7 @@ def eval_current(self, auto_indent=False): index = self.index('input') lines = self.get('input', 'insert lineend').splitlines() # commands to execute self.mark_set('insert', 'insert lineend') + #self.tag_add("input_color", "input", "insert lineend") if lines: # there is code to execute # remove prompts lines = [lines[0].rstrip()] + [line[len(self._prompt2):].rstrip() for line in lines[1:]] @@ -353,7 +550,7 @@ def eval_current(self, auto_indent=False): # if res is True, this is a partial command, e.g. 'def test():' and we need to wait for the rest of the code errors = err.getvalue() if errors: # there were errors during the execution - self.insert('end', errors) # display the traceback + self.insert('end', errors, 'errors') # display the traceback self.mark_set('input', 'end') self.see('end') self.prompt() # insert new prompt @@ -535,11 +732,11 @@ def __init__( self.rowconfigure(0, weight=1) # Setup the menu - menubar = tk.Menu(self) + menubar = Menu(self) self.config(menu=menubar) # Create File menu - file_menu = tk.Menu(menubar, tearoff=0) + file_menu = Menu(menubar, tearoff=0) menubar.add_cascade(label="File", menu=file_menu) LOAD_LABEL_NAME = "%s printer configuration file or web URL..." LOAD_LABEL_TITLE = "Select a %s printer configuration file, or enter a Web URL" @@ -587,9 +784,10 @@ def __init__( label="Save the selected printer configuration to a PICKLE file...", command=self.save_to_file ) + file_menu.add_command(label="Quit Application", command=self.quit) # Create Help menu - help_menu = tk.Menu(menubar, tearoff=0) + help_menu = Menu(menubar, tearoff=0) menubar.add_cascade(label="Settings", menu=help_menu) help_menu.add_command(label="Show printer parameters of the selected model", command=self.printer_config) @@ -607,14 +805,14 @@ def __init__( help_menu.add_command(label="Clear printer list", command=self.clear_printer_list) help_menu.entryconfig("Clear printer list", accelerator="F6") - help_menu.add_command(label="Run debug shell", command=self.tk_console) - help_menu.entryconfig("Run debug shell", accelerator="F7") + help_menu.add_command(label="Debug shell", command=self.tk_console) + help_menu.entryconfig("Debug shell", accelerator="F7") help_menu.add_command(label="Get next local IP addresss", command=lambda: self.next_ip(0)) help_menu.entryconfig("Get next local IP addresss", accelerator="F9") # Create Help menu - help_menu = tk.Menu(menubar, tearoff=0) + help_menu = Menu(menubar, tearoff=0) menubar.add_cascade(label="Help", menu=help_menu) help_menu.add_command(label="Help", command=self.open_help_browser) help_menu.add_command(label="Program Information", command=self.show_program_info) @@ -675,12 +873,12 @@ def __init__( "Select the model of the printer, or press 'Detect Printers'." " Special features are allowed via F2, F3, F4, F5, or F6.\n" ) - self.model_dropdown.bind("", self.printer_config) - self.model_dropdown.bind("", self.key_values) - self.model_dropdown.bind("", lambda event: self.remove_printer_conf()) - self.model_dropdown.bind("", lambda event: self.keep_printer_conf()) - self.model_dropdown.bind("", lambda event: self.clear_printer_list()) - self.model_dropdown.bind("", lambda event: self.tk_console()) + self.bind_all("", self.printer_config) + self.bind_all("", self.key_values) + self.bind_all("", lambda event: self.remove_printer_conf()) + self.bind_all("", lambda event: self.keep_printer_conf()) + self.bind_all("", lambda event: self.clear_printer_list()) + self.bind_all("", lambda event: self.tk_console()) # BOX IP address ip_frame = ttk.LabelFrame( @@ -1070,6 +1268,10 @@ def __init__( self.status_text = ScrolledText( status_frame, wrap=tk.WORD, font=("TkDefaultFont") ) + self.status_text.tag_configure("error", foreground="red") + self.status_text.tag_configure("warn", foreground="blue") + self.status_text.tag_configure("note", foreground="purple") + self.status_text.tag_configure("info", foreground="green") self.status_text.grid( row=0, column=0, @@ -1180,9 +1382,10 @@ def __init__( def save_to_file(self): if not self.model_var.get(): self.show_status_text_view() + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - '[ERROR]: Unknown printer model.' + ': Unknown printer model.' ) return if not self.printer: @@ -1192,9 +1395,10 @@ def save_to_file(self): ) if not self.printer or not self.printer.parm: self.show_status_text_view() + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - '[ERROR]: No printer configuration defined.' + ': No printer configuration defined.' ) return # Open file dialog to enter the file @@ -1224,14 +1428,16 @@ def save_to_file(self): pickle.dump(normalized_config, file) # serialize the list except Exception: self.show_status_text_view() + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - f"[ERROR] File save operation failed.\n" + f" File save operation failed.\n" ) return + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( tk.END, - f'[INFO] "{os.path.basename(file_path)}" file save operation completed.\n' + f' "{os.path.basename(file_path)}" file save operation completed.\n' ) def load_from_file(self, file_type, type): @@ -1259,14 +1465,16 @@ def load_from_file(self, file_type, type): self.update_idletasks() self.show_status_text_view() if not file_path.tell(): + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - f"[ERROR] Empty PICKLE FILE {file_path}.\n" + f" Empty PICKLE FILE {file_path}.\n" ) else: + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - f"[ERROR] Cannot load PICKLE file {file_path}. {e}\n" + f" Cannot load PICKLE file {file_path}. {e}\n" ) return if ( @@ -1281,9 +1489,10 @@ def load_from_file(self, file_type, type): self.model_var.set(self.conf_dict["internal_data"]["default_model"]) else: self.config(cursor="watch") + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( tk.END, - f"[INFO] Converting file, please wait...\n" + f" Converting file, please wait...\n" ) self.update_idletasks() if type == 1: @@ -1293,9 +1502,10 @@ def load_from_file(self, file_type, type): if not printer_config: self.config(cursor="") self.show_status_text_view() + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - f"[ERROR] Cannot load file {file_path}\n" + f" Cannot load file {file_path}\n" ) return self.conf_dict = normalize_config(config=printer_config) @@ -1307,17 +1517,19 @@ def load_from_file(self, file_type, type): self.update_idletasks() if file_path: self.show_status_text_view() + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( tk.END, - f"[INFO] Loaded file {os.path.basename(file_path)}.\n" + f" Loaded file {os.path.basename(file_path)}.\n" ) def keep_printer_conf(self): self.show_status_text_view() if not self.model_var.get(): + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - '[ERROR]: Select a valid printer model.\n' + ': Select a valid printer model.\n' ) return keep_model = self.model_var.get() @@ -1327,17 +1539,19 @@ def keep_printer_conf(self): self.replace_conf = True self.show_status_text_view() self.update_idletasks() + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( tk.END, - f"[INFO] Printer {keep_model} is the only one in the list.\n" + f" Printer {keep_model} is the only one in the list.\n" ) def remove_printer_conf(self): self.show_status_text_view() if not self.model_var.get(): + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - '[ERROR]: Select a valid printer model.\n' + ': Select a valid printer model.\n' ) return remove_model = self.model_var.get() @@ -1348,9 +1562,10 @@ def remove_printer_conf(self): self.replace_conf = True self.show_status_text_view() self.update_idletasks() + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( tk.END, - f"[INFO] Configuation of printer {remove_model} removed.\n" + f" Configuation of printer {remove_model} removed.\n" ) def clear_printer_list(self): @@ -1360,15 +1575,16 @@ def clear_printer_list(self): self.replace_conf = True self.show_status_text_view() self.update_idletasks() + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( tk.END, - f"[INFO] Printer list cleared.\n" + f" Printer list cleared.\n" ) def tk_console(self): console_window = tk.Toplevel(self) console_window.title("Debug Console") - console_window.geometry("600x400") + console_window.geometry("800x400") console = TextConsole(self, console_window) console.pack(fill='both', expand=True) # Use pack within the frame @@ -1384,16 +1600,19 @@ def open_help_browser(self): try: ret = webbrowser.open(url) if ret: + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( - tk.END, f"[INFO] The browser is being opened.\n" + tk.END, f" The browser is being opened.\n" ) else: + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( - tk.END, f"[ERROR] Cannot open browser.\n" + tk.END, f" Cannot open browser.\n" ) except Exception as e: + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( - tk.END, f"[ERROR] Cannot open web browser: {e}\n" + tk.END, f" Cannot open web browser: {e}\n" ) finally: self.config(cursor="") @@ -1605,12 +1824,14 @@ def copy_to_clipboard(self, text_widget): def handle_printer_error(self, e): self.show_status_text_view() if isinstance(e, TimeoutError): + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( - tk.END, f"[ERROR] Printer is unreachable or offline.\n" + tk.END, f" Printer is unreachable or offline.\n" ) else: + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( - tk.END, f"[ERROR] {e}\n{traceback.format_exc()}\n" + tk.END, f" {e}\n{traceback.format_exc()}\n" ) def get_po_mins(self, cursor=True): @@ -1624,6 +1845,7 @@ def get_po_mins(self, cursor=True): self.show_status_text_view() ip_address = self.ip_var.get() if not self._is_valid_ip(ip_address): + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert(tk.END, NO_CONF_ERROR) self.config(cursor="") self.update() @@ -1631,17 +1853,19 @@ def get_po_mins(self, cursor=True): if not self.printer: return if not self.printer.parm.get("stats", {}).get("Power off timer"): + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - f"[ERROR]: Missing 'Power off timer' in configuration\n", + f": Missing 'Power off timer' in configuration\n", ) self.config(cursor="") self.update_idletasks() return try: po_timer = self.printer.stats()["stats"]["Power off timer"] + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( - tk.END, f"[INFO] Power off timer: {po_timer} minutes.\n" + tk.END, f" Power off timer: {po_timer} minutes.\n" ) self.po_timer_var.set(po_timer) except Exception as e: @@ -1661,6 +1885,7 @@ def get_ser_number(self, cursor=True): self.show_status_text_view() ip_address = self.ip_var.get() if not self._is_valid_ip(ip_address): + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert(tk.END, NO_CONF_ERROR) self.config(cursor="") self.update() @@ -1675,23 +1900,26 @@ def get_ser_number(self, cursor=True): self.update_idletasks() return if ser_num is False: + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - f"[ERROR]: Improper values in printer serial number.\n", + f": Improper values in printer serial number.\n", ) self.config(cursor="") self.update_idletasks() return if not ser_num or "?" in ser_num: + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - f"[ERROR]: Cannot retrieve the printer serial number.\n", + f": Cannot retrieve the printer serial number.\n", ) self.config(cursor="") self.update_idletasks() return + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( - tk.END, f"[INFO] Printer serial number: {ser_num}.\n" + tk.END, f" Printer serial number: {ser_num}.\n" ) self.ser_num_var.set(ser_num) self.config(cursor="") @@ -1708,6 +1936,7 @@ def get_mac_address(self, cursor=True): self.show_status_text_view() ip_address = self.ip_var.get() if not self._is_valid_ip(ip_address): + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert(tk.END, NO_CONF_ERROR) self.config(cursor="") self.update() @@ -1722,15 +1951,17 @@ def get_mac_address(self, cursor=True): self.update_idletasks() return if not mac_addr: + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - f"[ERROR]: Cannot retrieve the printer WiFi MAC address.\n", + f": Cannot retrieve the printer WiFi MAC address.\n", ) self.config(cursor="") self.update_idletasks() return + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( - tk.END, f"[INFO] Printer WiFi MAC address: {mac_addr}.\n" + tk.END, f" Printer WiFi MAC address: {mac_addr}.\n" ) self.mac_addr_var.set(mac_addr) self.config(cursor="") @@ -1744,14 +1975,16 @@ def get_current_eeprom_values(self, values, label): ) ) if org_values: + self.status_text.insert(tk.END, '[NOTE]', "note") self.status_text.insert( tk.END, - f"[NOTE] Current EEPROM values for {label}: {org_values}.\n" + f" Current EEPROM values for {label}: {org_values}.\n" ) else: + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - f'[ERROR] Cannot read EEPROM values for "{label}"' + f' Cannot read EEPROM values for "{label}"' f': invalid printer model selected: {self.printer.model}.\n' ) self.config(cursor="") @@ -1777,6 +2010,7 @@ def set_po_mins(self, cursor=True): self.show_status_text_view() ip_address = self.ip_var.get() if not self._is_valid_ip(ip_address): + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert(tk.END, NO_CONF_ERROR) self.config(cursor="") self.update_idletasks() @@ -1784,9 +2018,10 @@ def set_po_mins(self, cursor=True): if not self.printer: return if not self.printer.parm.get("stats", {}).get("Power off timer"): + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - f"[ERROR]: Missing 'Power off timer' in configuration\n", + f": Missing 'Power off timer' in configuration\n", ) self.config(cursor="") self.update_idletasks() @@ -1795,8 +2030,9 @@ def set_po_mins(self, cursor=True): self.config(cursor="") self.update_idletasks() if not po_timer.isnumeric(): + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( - tk.END, "[ERROR] Please Use a valid value for minutes.\n" + tk.END, " Please Use a valid value for minutes.\n" ) self.config(cursor="") self.update_idletasks() @@ -1814,17 +2050,19 @@ def set_po_mins(self, cursor=True): self.config(cursor="") self.update_idletasks() return + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( tk.END, - f"[INFO] Set Power off timer: {po_timer} minutes. Restarting" + f" Set Power off timer: {po_timer} minutes. Restarting" " the printer is required for this change to take effect.\n" ) response = messagebox.askyesno(*CONFIRM_MESSAGE, default='no') if response: try: self.printer.write_poweroff_timer(int(po_timer)) + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( - tk.END, "[INFO] Update operation completed.\n" + tk.END, " Update operation completed.\n" ) except Exception as e: self.handle_printer_error(e) @@ -1856,8 +2094,9 @@ def set_mac_address(self, cursor=True): if not mac or not self.validate_mac_address( self.mac_addr_var.get() ): + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( - tk.END, "[ERROR] Please Use a valid MAC address.\n" + tk.END, " Please Use a valid MAC address.\n" ) self.config(cursor="") self.update_idletasks() @@ -1889,9 +2128,10 @@ def set_mac_address(self, cursor=True): self.config(cursor="") self.update_idletasks() return + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( tk.END, - f"[INFO] Set WiFi MAC Address: {self.mac_addr_var.get()}.\n" + f" Set WiFi MAC Address: {self.mac_addr_var.get()}.\n" ) response = messagebox.askyesno(*CONFIRM_MESSAGE, default='no') if not response: @@ -1901,9 +2141,10 @@ def set_mac_address(self, cursor=True): self.config(cursor="") self.update_idletasks() return + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( tk.END, - "[INFO] Changing the WiFi MAC address of the printer. Restarting" + " Changing the WiFi MAC address of the printer. Restarting" " the printer is required for this change to take effect.\n" ) ret = None @@ -1916,12 +2157,14 @@ def set_mac_address(self, cursor=True): except Exception as e: self.handle_printer_error(e) if ret: + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( - tk.END, "[INFO] Update operation completed.\n" + tk.END, " Update operation completed.\n" ) else: + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( - tk.END, f"[ERROR] Write operation failed.\n" + tk.END, f" Write operation failed.\n" ) self.config(cursor="") self.update_idletasks() @@ -1937,6 +2180,7 @@ def set_ser_number(self, cursor=True): self.show_status_text_view() ip_address = self.ip_var.get() if not self._is_valid_ip(ip_address): + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert(tk.END, NO_CONF_ERROR) self.config(cursor="") self.update_idletasks() @@ -1946,8 +2190,9 @@ def set_ser_number(self, cursor=True): if not self.ser_num_var.get() or not self.validate_ser_number( self.ser_num_var.get() ): + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( - tk.END, "[ERROR] Please Use a valid serial number.\n" + tk.END, " Please Use a valid serial number.\n" ) self.config(cursor="") self.update_idletasks() @@ -1968,9 +2213,10 @@ def set_ser_number(self, cursor=True): self.config(cursor="") self.update_idletasks() return + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( tk.END, - f"[INFO] Set Printer Serial Number: {self.ser_num_var.get()}.\n" + f" Set Printer Serial Number: {self.ser_num_var.get()}.\n" ) response = messagebox.askyesno(*CONFIRM_MESSAGE, default='no') if not response: @@ -1980,9 +2226,10 @@ def set_ser_number(self, cursor=True): self.config(cursor="") self.update_idletasks() return + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( tk.END, - "[INFO] Changing the serial number of the printer. Restarting" + " Changing the serial number of the printer. Restarting" " the printer is required for this change to take effect.\n" ) ret = None @@ -1995,12 +2242,14 @@ def set_ser_number(self, cursor=True): except Exception as e: self.handle_printer_error(e) if ret: + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( - tk.END, "[INFO] Update operation completed.\n" + tk.END, " Update operation completed.\n" ) else: + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( - tk.END, f"[ERROR] Write operation failed.\n" + tk.END, f" Write operation failed.\n" ) self.config(cursor="") self.update_idletasks() @@ -2016,6 +2265,7 @@ def get_ti_date(self, cursor=True): self.show_status_text_view() ip_address = self.ip_var.get() if not self._is_valid_ip(ip_address): + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert(tk.END, NO_CONF_ERROR) self.config(cursor="") self.update_idletasks() @@ -2023,9 +2273,10 @@ def get_ti_date(self, cursor=True): if not self.printer: return if not self.printer.parm.get("stats", {}).get("First TI received time"): + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - f"[ERROR]: Missing 'First TI received time' in configuration\n", + f": Missing 'First TI received time' in configuration\n", ) self.config(cursor="") self.update_idletasks() @@ -2033,18 +2284,20 @@ def get_ti_date(self, cursor=True): try: d = self.printer.stats()["stats"]["First TI received time"] if d == "?": + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - "[ERROR]: No data from 'First TI received time'." + ": No data from 'First TI received time'." " Check printer configuration.\n", ) self.config(cursor="") self.update_idletasks() return date_string = datetime.strptime(d, "%d %b %Y").strftime("%Y-%m-%d") + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( tk.END, - f"[INFO] First TI received time (YYYY-MM-DD): {date_string}.\n", + f" First TI received time (YYYY-MM-DD): {date_string}.\n", ) self.date_entry.set_date(date_string) except Exception as e: @@ -2064,6 +2317,7 @@ def set_ti_date(self, cursor=True): self.show_status_text_view() ip_address = self.ip_var.get() if not self._is_valid_ip(ip_address): + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert(tk.END, NO_CONF_ERROR) self.config(cursor="") self.update_idletasks() @@ -2071,9 +2325,10 @@ def set_ti_date(self, cursor=True): if not self.printer: return if not self.printer.parm.get("stats", {}).get("First TI received time"): + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - f"[ERROR]: Missing 'First TI received time' in configuration\n", + f": Missing 'First TI received time' in configuration\n", ) self.config(cursor="") self.update_idletasks() @@ -2092,9 +2347,10 @@ def set_ti_date(self, cursor=True): self.config(cursor="") self.update_idletasks() return + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( tk.END, - f"[INFO] Set 'First TI received time' (YYYY-MM-DD) to: " + f" Set 'First TI received time' (YYYY-MM-DD) to: " f"{date_string.strftime('%Y-%m-%d')}.\n", ) response = messagebox.askyesno(*CONFIRM_MESSAGE, default='no') @@ -2103,8 +2359,9 @@ def set_ti_date(self, cursor=True): self.printer.write_first_ti_received_time( date_string.year, date_string.month, date_string.day ) + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( - tk.END, "[INFO] Update operation completed.\n" + tk.END, " Update operation completed.\n" ) except Exception as e: self.handle_printer_error(e) @@ -2172,9 +2429,10 @@ def printer_status(self, cursor=True): model = self.model_var.get() ip_address = self.ip_var.get() if not self._is_valid_ip(ip_address): + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - "[ERROR] Please enter a valid IP address, or " + " Please enter a valid IP address, or " "press 'Detect Printers'.\n" ) self.config(cursor="") @@ -2215,15 +2473,17 @@ def printer_status(self, cursor=True): def reset_printer_model(self): self.show_status_text_view() if self.model_var.get(): + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - '[ERROR]: Unknown printer model ' + ': Unknown printer model ' f'"{self.model_var.get()}"\n', ) else: + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - '[ERROR]: Select a valid printer model.\n' + ': Select a valid printer model.\n' ) self.config(cursor="") self.update() @@ -2406,14 +2666,16 @@ def get_values(addresses): self.update_idletasks() return if values: + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( tk.END, - f"[INFO] EEPROM values: {values}.\n" + f" EEPROM values: {values}.\n" ) else: + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - f'[ERROR] Cannot read EEPROM values for addresses "{addresses}"' + f' Cannot read EEPROM values for addresses "{addresses}"' ': invalid printer model selected.\n' ) self.config(cursor="") @@ -2422,6 +2684,7 @@ def get_values(addresses): self.show_status_text_view() ip_address = self.ip_var.get() if not self._is_valid_ip(ip_address): + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert(tk.END, NO_CONF_ERROR) self.config(cursor="") self.update_idletasks() @@ -2445,6 +2708,7 @@ def run_detection(): current_log_level = logging.getLogger().getEffectiveLevel() logging.getLogger().setLevel(logging.ERROR) if not self._is_valid_ip(ip_address): + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert(tk.END, NO_CONF_ERROR) logging.getLogger().setLevel(current_log_level) self.config(cursor="") @@ -2458,9 +2722,10 @@ def run_detection(): self.printer.parm = {'read_key': None} # Detect the read_key + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( tk.END, - f"[INFO] Detecting the read_key...\n" + f" Detecting the read_key...\n" ) self.update_idletasks() read_key = None @@ -2473,12 +2738,14 @@ def run_detection(): self.update_idletasks() return if read_key: + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( - tk.END, f"[INFO] Detected read_key: {read_key}.\n" + tk.END, f" Detected read_key: {read_key}.\n" ) else: + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( - tk.END, f"[ERROR] Could not detect read_key.\n" + tk.END, f" Could not detect read_key.\n" ) logging.getLogger().setLevel(current_log_level) self.config(cursor="") @@ -2497,17 +2764,19 @@ def run_detection(): and self.printer.parm['read_key'] != read_key ): if self.printer.parm['read_key']: + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - f"[ERROR] You selected a model with the wrong read_key " + f" You selected a model with the wrong read_key " f"{self.printer.parm['read_key']} instead of " f"{read_key}. Using the detected one to go on.\n" ) self.printer.PRINTER_CONFIG[DETECTED] = {'read_key': read_key} self.printer.parm = self.printer.PRINTER_CONFIG[DETECTED] + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( tk.END, - f"[INFO] Detecting the serial number...\n" + f" Detecting the serial number...\n" ) try: hex_bytes, matches = self.printer.find_serial_number( @@ -2520,23 +2789,26 @@ def run_detection(): self.update_idletasks() return if not matches: + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - f"[ERROR] Cannot detect the serial number.\n" + f" Cannot detect the serial number.\n" ) left_ser_num = None for match in matches: tmp_ser_num = match.group() if left_ser_num is not None and tmp_ser_num != left_ser_num: + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - "[ERROR] More than one pattern appears to be" + " More than one pattern appears to be" " a serial number with different values:\n" ) for match in matches: + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - f'[ERROR] - found pattern "{match.group()}"' + f' - found pattern "{match.group()}"' f" at address {match.start()}\n" ) left_ser_num = None @@ -2550,24 +2822,27 @@ def run_detection(): serial_number_address, serial_number_address + len_ser_num ) + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( tk.END, - f'[INFO] Detected serial number "{serial_number}"' + f' Detected serial number "{serial_number}"' f" at address {serial_number_address}.\n" ) last_ser_num_addr = serial_number_address + len_ser_num - 1 last_ser_num_value = int(hex_bytes[last_ser_num_addr], 16) + self.status_text.insert(tk.END, '[NOTE]', "note") self.status_text.insert( tk.END, - f"[NOTE] Current EEPROM value for the last byte of the" + f" Current EEPROM value for the last byte of the" f" serial number:" f" {last_ser_num_addr}: {last_ser_num_value}.\n" ) if last_ser_num_addr is None: + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - "[ERROR] Could not detect serial number.\n" + " Could not detect serial number.\n" ) logging.getLogger().setLevel(current_log_level) self.config(cursor="") @@ -2578,9 +2853,10 @@ def run_detection(): or self.printer.parm['serial_number'] != serial_number_range ): if 'serial_number' in self.printer.parm: + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - f"[ERROR] The serial number addresses" + f" The serial number addresses" f" {self.printer.parm['serial_number']} of the" f" selected printer is different from the detected" f" one {serial_number_range}," @@ -2596,9 +2872,10 @@ def run_detection(): write_key_list = self.printer.write_key_list(read_key) # Validate the write_key against any of the known values + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( tk.END, - "[INFO] Detecting the write_key," + " Detecting the write_key," " do not power off the printer now...\n" ) old_write_key = self.printer.parm.get('write_key') @@ -2614,9 +2891,10 @@ def run_detection(): ) assert valid is not None except AssertionError: + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - "[ERROR] Write operation failed. Check whether the" + " Write operation failed. Check whether the" " serial number is changed and restore it manually.\n" ) self.printer.parm['write_key'] = old_write_key @@ -2632,8 +2910,9 @@ def run_detection(): self.update_idletasks() return if valid is None: + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( - tk.END, "[ERROR] Operation interrupted with errors.\n" + tk.END, " Operation interrupted with errors.\n" ) self.printer.parm['write_key'] = old_write_key logging.getLogger().setLevel(current_log_level) @@ -2645,14 +2924,16 @@ def run_detection(): found_write_key = write_key self.printer.parm['write_key'] = old_write_key + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( - tk.END, f"[INFO] Detected write_key: {found_write_key}\n" + tk.END, f" Detected write_key: {found_write_key}\n" ) if not old_write_key or old_write_key != found_write_key: if old_write_key and old_write_key != found_write_key: + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - f"[ERROR] The selected write key {old_write_key}" + f" The selected write key {old_write_key}" f" is different from the detected one, which will" f" be used to go on.\n" ) @@ -2684,39 +2965,45 @@ def run_detection(): ): rwk_kist.append(p) if rk_kist: + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( tk.END, - f"[INFO] Models with same read_key: {rk_kist}\n" + f" Models with same read_key: {rk_kist}\n" ) if wk_kist: + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( tk.END, - f"[INFO] Models with same write_key: {wk_kist}\n" + f" Models with same write_key: {wk_kist}\n" ) if rwk_kist: + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( tk.END, - f"[INFO] Models with same access keys: {rwk_kist}\n" + f" Models with same access keys: {rwk_kist}\n" ) if ( DETECTED in self.printer.PRINTER_CONFIG and self.printer.PRINTER_CONFIG[DETECTED] ): + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( tk.END, - f'[INFO] Found data: ' + f' Found data: ' f'{self.printer.PRINTER_CONFIG[DETECTED]}.\n' ) self.detect_configuration_button.state(["!disabled"]) + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( - tk.END, "[INFO] Detect operation completed.\n" + tk.END, " Detect operation completed.\n" ) break if not found_write_key: + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - "[ERROR] Unable to detect the write key by validating" + " Unable to detect the write key by validating" " against any of the known ones.\n" ) logging.getLogger().setLevel(current_log_level) @@ -2727,6 +3014,7 @@ def run_detection(): self.show_status_text_view() ip_address = self.ip_var.get() if not self._is_valid_ip(ip_address): + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert(tk.END, NO_CONF_ERROR) return response = messagebox.askyesno( @@ -2740,9 +3028,10 @@ def run_detection(): default='no' ) if response: + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( tk.END, - f"[INFO] Starting the access key detection, please wait for many minutes...\n" + f" Starting the access key detection, please wait for many minutes...\n" ) self.config(cursor="watch") self.update() @@ -2765,6 +3054,7 @@ def web_interface(self, cursor=True): self.show_status_text_view() ip_address = self.ip_var.get() if not self._is_valid_ip(ip_address): + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert(tk.END, NO_CONF_ERROR) self.config(cursor="") self.update() @@ -2774,16 +3064,19 @@ def web_interface(self, cursor=True): try: ret = webbrowser.open(ip_address) if ret: + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( - tk.END, f"[INFO] The browser is being opened.\n" + tk.END, f" The browser is being opened.\n" ) else: + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( - tk.END, f"[ERROR] Cannot open browser.\n" + tk.END, f" Cannot open browser.\n" ) except Exception as e: + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( - tk.END, f"[ERROR] Cannot open web browser: {e}\n" + tk.END, f" Cannot open web browser: {e}\n" ) finally: self.config(cursor="") @@ -2812,15 +3105,17 @@ def detect_sequence(eeprom, sequence): self.show_status_text_view() ip_address = self.ip_var.get() if not self._is_valid_ip(ip_address): + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert(tk.END, NO_CONF_ERROR) self.config(cursor="") self.update() return if not self.printer: return + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( tk.END, - f"[INFO] Reading Printer SNMP values...\n" + f" Reading Printer SNMP values...\n" ) try: stats = self.printer.stats() @@ -2830,17 +3125,19 @@ def detect_sequence(eeprom, sequence): self.update_idletasks() return False if not "snmp_info" in stats: + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - '[ERROR] No SNMP values could be found.\n' + ' No SNMP values could be found.\n' ) self.update() self.config(cursor="") self.update_idletasks() return False + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( tk.END, - f"[INFO] Reading EEPROM values, please wait for some minutes...\n" + f" Reading EEPROM values, please wait for some minutes...\n" ) self.update() try: @@ -2854,9 +3151,10 @@ def detect_sequence(eeprom, sequence): ) } if not eeprom or eeprom == {0: None}: + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - '[ERROR] Cannot read EEPROM values: invalid printer model selected.\n' + ' Cannot read EEPROM values: invalid printer model selected.\n' ) self.update() self.config(cursor="") @@ -2867,9 +3165,10 @@ def detect_sequence(eeprom, sequence): self.config(cursor="") self.update_idletasks() return False + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( tk.END, - f"[INFO] Analyzing EEPROM values...\n" + f" Analyzing EEPROM values...\n" ) self.update() @@ -2970,9 +3269,10 @@ def detect_sequence(eeprom, sequence): except Exception as e: self.handle_printer_error(e) finally: + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( tk.END, - f"[INFO] Operation completed.\n" + f" Operation completed.\n" ) self.update_idletasks() self.config(cursor="") @@ -3066,8 +3366,9 @@ def write_eeprom_values(dict_addr_val): return False except Exception as e: self.handle_printer_error(e) + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( - tk.END, f"[INFO] Write EEPROM completed.\n" + tk.END, f" Write EEPROM completed.\n" ) self.config(cursor="") self.update_idletasks() @@ -3075,14 +3376,16 @@ def write_eeprom_values(dict_addr_val): self.show_status_text_view() ip_address = self.ip_var.get() if not self._is_valid_ip(ip_address): + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert(tk.END, NO_CONF_ERROR) return dict_addr_val = get_input() if dict_addr_val is not None: self.config(cursor="watch") self.update() + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( - tk.END, f"[INFO] Going to write EEPROM: {dict_addr_val}.\n" + tk.END, f" Going to write EEPROM: {dict_addr_val}.\n" ) self.after(200, lambda: dialog_write_values(dict_addr_val)) @@ -3103,6 +3406,7 @@ def reset_waste_ink(self, cursor=True): or "read_key" not in self.printer.parm or "write_key" not in self.printer.parm ): + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert(tk.END, NO_CONF_ERROR) self.config(cursor="") self.update_idletasks() @@ -3136,9 +3440,10 @@ def reset_waste_ink(self, cursor=True): if response: try: self.printer.reset_waste_ink_levels() + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( tk.END, - "[INFO] Waste ink levels have been reset." + " Waste ink levels have been reset." " Perform a power cycle of the printer now.\n" ) except Exception as e: @@ -3152,8 +3457,9 @@ def reset_waste_ink(self, cursor=True): def start_detect_printers(self): self.show_status_text_view() + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( - tk.END, "[INFO] Detecting printers... (this might take a while)\n" + tk.END, " Detecting printers... (this might take a while)\n" ) # run printer detection in new thread, as it can take a while @@ -3175,9 +3481,10 @@ def detect_printers_thread(self, cursor=True): ) if len(printers) > 0: if len(printers) == 1: + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( tk.END, - f"[INFO] Found printer '{printers[0]['name']}' " + f" Found printer '{printers[0]['name']}' " f"at {printers[0]['ip']} " f"(hostname: {printers[0]['hostname']})\n", ) @@ -3190,23 +3497,27 @@ def detect_printers_thread(self, cursor=True): self.model_var.set(model) break if self.model_var.get() == "": + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( tk.END, - f'[ERROR] Printer model unknown.\n' + f' Printer model unknown.\n' ) self.model_var.set("") else: + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( - tk.END, f"[INFO] Found {len(printers)} printers:\n" + tk.END, f" Found {len(printers)} printers:\n" ) for printer in printers: + self.status_text.insert(tk.END, '[INFO]', "info") self.status_text.insert( tk.END, - f"[INFO] {printer['name']} found at {printer['ip']}" + f" {printer['name']} found at {printer['ip']}" f" (hostname: {printer['hostname']})\n", ) else: - self.status_text.insert(tk.END, "[WARN] No printers found.\n") + self.status_text.insert(tk.END, '[WARN]', "warn") + self.status_text.insert(tk.END, " No printers found.\n") except Exception as e: self.handle_printer_error(e) finally: @@ -3346,8 +3657,9 @@ def print_items(self, text): ip_address = self.ip_var.get() if not self._is_valid_ip(ip_address): self.show_status_text_view() + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( - tk.END, f"[ERROR] Missing IP address or printer host name.\n" + tk.END, f" Missing IP address or printer host name.\n" ) return try: @@ -3362,8 +3674,9 @@ def print_items(self, text): ) except Exception as e: self.show_status_text_view() + self.status_text.insert(tk.END, '[ERROR]', "error") self.status_text.insert( - tk.END, f"[ERROR] Printer is unreachable or offline.\n" + tk.END, f" Printer is unreachable or offline.\n" )