import os import subprocess import threading import tkinter as tk import webbrowser from functools import partial from pathlib import Path from tkinter import ttk from logger import app_logger from shared_libs.common_tools import ConfigManager, Tooltip from shared_libs.gitea import GiteaUpdate from shared_libs.animated_icon import AnimatedIcon, PIL_AVAILABLE from shared_libs.message import MessageDialog from shared_libs.wp_app_config import AppConfig, Msg class MenuBar(ttk.Frame): def __init__(self, container, image_manager, tooltip_state, on_theme_toggle, toggle_log_window, **kwargs): super().__init__(container, **kwargs) self.image_manager = image_manager self.tooltip_state = tooltip_state self.on_theme_toggle = on_theme_toggle self.options_btn = ttk.Menubutton(self, text=Msg.STR["options"]) self.options_btn.grid(column=0, row=0) Tooltip(self.options_btn, Msg.TTIP["settings"], state_var=self.tooltip_state) self.set_update = tk.IntVar() self.settings = tk.Menu(self, relief="flat") self.options_btn.configure(menu=self.settings, style="Toolbutton") self.settings.add_checkbutton( label=Msg.STR["disable_updates"], command=lambda: self.update_setting(self.set_update.get()), variable=self.set_update, ) self.update_label = tk.StringVar() self.update_label_widget = ttk.Label(self, textvariable=self.update_label) self.update_label_widget.grid(column=4, row=0, padx=10) self.animated_icon_frame = ttk.Frame(self) self.animated_icon_frame.grid(column=5, row=0, padx=10) current_theme = ConfigManager.get("theme") bg_color = "#ffffff" if current_theme == "light" else "#333333" self.animated_icon = AnimatedIcon( self.animated_icon_frame, animation_type="blink", use_pillow=PIL_AVAILABLE, bg=bg_color) self.animated_icon.pack() self.animated_icon_frame.bind("", lambda e: self.updater()) self.animated_icon.bind("", lambda e: self.updater()) # Tooltip Menu self.tooltip_label = tk.StringVar() self.tooltip_update_label() self.settings.add_command( label=self.tooltip_label.get(), command=self.tooltips_toggle ) # Label show dark or light self.theme_label = tk.StringVar() self.update_theme_label() self.settings.add_command( label=self.theme_label.get(), command=self.on_theme_toggle ) # About BTN Menu / Label self.about_btn = ttk.Button( self, text=Msg.STR["about"], style="Toolbutton", command=self.about ) self.about_btn.grid(column=1, row=0) # Add a column with weight to push button to the right self.columnconfigure(10, weight=1) self.log_btn = ttk.Button( self, image=self.image_manager.get_icon("log_small"), style="Toolbutton", command=toggle_log_window, ) self.log_btn.grid(column=11, row=0, sticky='e') Tooltip(self.log_btn, "Show Log", state_var=self.tooltip_state) self.update_thread = threading.Thread(target=self.check_for_updates, daemon=True) self.update_thread.start() def check_for_updates(self): """ Checks for updates in a separate thread. """ res = GiteaUpdate.api_down( AppConfig.UPDATE_URL, AppConfig.VERSION, ConfigManager.get("updates") ) # Schedule the UI update in the main thread self.after(0, self.update_ui_for_update, res) def update_ui_for_update(self, res): self.animated_icon_frame.grid_remove() self.animated_icon.hide() self.update_label.set("") tooltip_msg = "" if res == "False": self.set_update.set(value=1) self.update_label.set(Msg.STR["update_search_off"]) self.update_label_widget.configure(foreground="") tooltip_msg = Msg.TTIP["updates_disabled"] elif res == "No Internet Connection!": self.update_label.set(Msg.STR["no_server_connection"]) self.update_label_widget.configure(foreground="red") tooltip_msg = Msg.TTIP["no_server_conn_tt"] elif res == "No Updates": self.animated_icon_frame.grid() self.animated_icon.stop() tooltip_msg = Msg.TTIP["up_to_date"] else: self.set_update.set(value=0) self.animated_icon_frame.grid() self.animated_icon.start() tooltip_msg = Msg.TTIP["install_new_version"] if not PIL_AVAILABLE: tooltip_msg += f"\n\n{Msg.TTIP['no_pillow']}" Tooltip(self.animated_icon_frame, tooltip_msg, state_var=self.tooltip_state) def updater(self): tmp_dir = Path("/tmp/lxtools") Path.mkdir(tmp_dir, exist_ok=True) os.chdir(tmp_dir) result = subprocess.run( ["/usr/local/bin/lxtools_installer"], check=False) if result.returncode != 0: MessageDialog("error", result.stderr) @staticmethod def about() -> None: MessageDialog( "info", Msg.STR["about_msg"], buttons=["OK", Msg.STR["goto_git"]], title=Msg.STR["info"], commands=[ None, partial(webbrowser.open, "https://git.ilunix.de/punix/Wire-Py"), ], icon="/usr/share/icons/lx-icons/64/wg_vpn.png", wraplength=420, ) def update_setting(self, update_res) -> None: if update_res == 1: ConfigManager.set("updates", "off") self.update_ui_for_update("False") else: ConfigManager.set("updates", "on") try: res = GiteaUpdate.api_down( AppConfig.UPDATE_URL, AppConfig.VERSION, "on") self.update_ui_for_update(res) except Exception as e: app_logger.log(f"Error checking for updates: {e}") self.update_ui_for_update("No Internet Connection!") def tooltip_update_label(self) -> None: if self.tooltip_state.get(): self.tooltip_label.set(Msg.STR["disable_tooltips"]) else: self.tooltip_label.set(Msg.STR["enable_tooltips"]) def tooltips_toggle(self): new_bool_state = not self.tooltip_state.get() ConfigManager.set("tooltips", str(new_bool_state)) self.tooltip_state.set(new_bool_state) self.tooltip_update_label() self.settings.entryconfigure(1, label=self.tooltip_label.get()) def update_theme_label(self) -> None: current_theme = ConfigManager.get("theme") if current_theme == "light": self.theme_label.set(Msg.STR["dark"]) else: self.theme_label.set(Msg.STR["light"]) def update_theme(self): self.update_theme_label() self.after(100, self._update_bg) def _update_bg(self): current_theme = ConfigManager.get("theme") bg_color = "#ffffff" if current_theme == "light" else "#333333" self.animated_icon.configure(bg=bg_color)