#!/usr/bin/env python3 import tkinter as tk from tkinter import Menu import subprocess import threading import sys # Try to import pystray for system tray try: from PIL import Image, ImageDraw import pystray HAS_TRAY = True except ImportError: print("Installing required packages for system tray...") subprocess.run([sys.executable, "-m", "pip", "install", "pystray", "pillow"], check=True) from PIL import Image, ImageDraw import pystray HAS_TRAY = True class SystemTrayApp: def __init__(self): self.icon = None self.current_status = {} self.update_status() def run_command(self, cmd): try: result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=5) return result.stdout.strip() except Exception as e: return "" def update_status(self): """Get current system status""" self.current_status = { 'temp': self.run_command("cat /sys/class/hwmon/hwmon5/temp1_input | awk '{print int($1/1000)}'"), 'governor': self.run_command("cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor"), 'battery': self.run_command("cat /sys/class/power_supply/BAT0/capacity"), 'charging': self.run_command("cat /sys/class/power_supply/BAT0/status"), 'fan': self.run_command("grep '^level' /proc/acpi/ibm/fan | awk '{print $NF}'") } def create_image(self): """Create system tray icon""" # Create a simple icon image = Image.new('RGB', (64, 64), color='black') draw = ImageDraw.Draw(image) draw.ellipse([16, 16, 48, 48], fill='#0066cc', outline='white') return image def open_full_gui(self, icon=None, item=None): """Open the main GUI""" subprocess.Popen(['python3', '/home/rwiegand/Nextcloud/entwicklung/Werkzeuge/battery_management/system-settings-gui.py']) def set_governor(self, gov): subprocess.run(f"pkexec /usr/local/bin/system-settings-helper.sh cpu-governor {gov}", shell=True) self.update_status() if self.icon: self.icon.title = self.get_tooltip() def set_battery(self, start, end): subprocess.run(f"pkexec /usr/local/bin/system-settings-helper.sh battery-start {start}", shell=True) subprocess.run(f"pkexec /usr/local/bin/system-settings-helper.sh battery-end {end}", shell=True) self.update_status() if self.icon: self.icon.title = self.get_tooltip() def charge_now(self): subprocess.run("pkexec /usr/local/bin/system-settings-helper.sh battery-start 0", shell=True) subprocess.run("pkexec /usr/local/bin/system-settings-helper.sh battery-end 100", shell=True) self.update_status() if self.icon: self.icon.title = self.get_tooltip() def set_fan(self, level): if level == 2: # Level 2 = automatic control subprocess.run("pkexec /usr/local/bin/system-settings-helper.sh fan-start-thinkfan", shell=True) else: # Other levels = manual control subprocess.run("pkexec /usr/local/bin/system-settings-helper.sh fan-stop-thinkfan", shell=True) subprocess.run(f"pkexec /usr/local/bin/system-settings-helper.sh fan-level {level}", shell=True) self.update_status() if self.icon: self.icon.title = self.get_tooltip() def get_tooltip(self): """Generate tooltip text""" return f"T14: {self.current_status['temp']}°C | {self.current_status['governor']} | {self.current_status['battery']}% {self.current_status['charging']}" def create_menu(self): """Create system tray menu""" return pystray.Menu( pystray.MenuItem("T14 System Settings", pystray.Menu.SEPARATOR), pystray.MenuItem("Open Full GUI", self.open_full_gui, default=True), pystray.MenuItem("CPU Governor", pystray.Menu( pystray.MenuItem("Performance", lambda: self.set_governor("performance")), pystray.MenuItem("Powersave", lambda: self.set_governor("powersave")) )), pystray.MenuItem("Fan Level", pystray.Menu( pystray.MenuItem("Level 1", lambda: self.set_fan(1)), pystray.MenuItem("Level 2", lambda: self.set_fan(2)), pystray.MenuItem("Level 3", lambda: self.set_fan(3)), pystray.MenuItem("Level 4", lambda: self.set_fan(4)), pystray.MenuItem("Level 5", lambda: self.set_fan(5)), pystray.MenuItem("Level 6", lambda: self.set_fan(6)), pystray.MenuItem("Level 7", lambda: self.set_fan(7)) )), pystray.MenuItem("Battery", pystray.Menu( pystray.MenuItem("⚡ Charge to 100% NOW", self.charge_now), pystray.MenuItem("Conservative (75-80%)", lambda: self.set_battery(75, 80)), pystray.MenuItem("Moderate (80-90%)", lambda: self.set_battery(80, 90)), pystray.MenuItem("Full (0-100%)", lambda: self.set_battery(0, 100)) )), pystray.MenuItem("Refresh Status", lambda: self.refresh_status()), pystray.MenuItem("Quit", self.quit_app) ) def refresh_status(self): self.update_status() if self.icon: self.icon.title = self.get_tooltip() def quit_app(self, icon=None, item=None): if self.icon: self.icon.stop() def run(self): """Run the system tray application""" self.icon = pystray.Icon( "t14_settings", self.create_image(), self.get_tooltip(), self.create_menu() ) # Update status every 30 seconds def update_loop(): import time while True: time.sleep(30) self.refresh_status() thread = threading.Thread(target=update_loop, daemon=True) thread.start() self.icon.run() if __name__ == "__main__": app = SystemTrayApp() app.run()