import customtkinter as ctk import subprocess import threading import sys import os from PIL import Image, ImageTk import webbrowser import winreg if getattr(sys, 'frozen', False): # Wenn das Skript in einer exe läuft, sind die Dateien im temporären Ordner bundle_dir = sys._MEIPASS pdf_export_path = os.path.join('./export.exe') else: # Wenn das Skript nicht in einer exe läuft, benutze das aktuelle Arbeitsverzeichnis bundle_dir = os.path.dirname(os.path.abspath(__file__)) pdf_export_path = os.path.join('./export.exe') print(pdf_export_path) # Pfade für eingebundene Ressourcen logo_path = os.path.join(bundle_dir, 'logo.png') gif_path = os.path.join(bundle_dir, 'printer.gif') reg_check_path = os.path.join(bundle_dir, 'reg_check.py') icon_path = os.path.join(bundle_dir, 'printer.ico') class CustomerThinkerApp(ctk.CTk): def __init__(self): super().__init__() self.iconbitmap(icon_path) # Setzt das Icon self.title("CustomerThinker PDF Export Tool") window_width = 400 window_height = 450 # Bildschirmgröße ermitteln screen_width = self.winfo_screenwidth() screen_height = self.winfo_screenheight() # Position zum Zentrieren berechnen x = int((screen_width / 2) - (window_width / 2)) y = int((screen_height / 2) - (window_height / 2)) self.geometry(f"{window_width}x{window_height}+{x}+{y}") self.resizable(False, False) ctk.set_appearance_mode("System") # "Dark", "Light", "System" ctk.set_default_color_theme("blue") # Andere Themes: "green", "dark-blue" self.script_path = pdf_export_path # Verändere dies auf den richtigen Pfad self.labels_dir = "label" self.orders_dir = "orders" self.frames = [] self.current_gif_frame = 0 self.animation_running = False self.build_gui() self.load_gif() self.update_file_dropdown() def build_gui(self): # Titel self.title_label = ctk.CTkLabel(self, text="PDF Export Tool", font=ctk.CTkFont(size=24, weight="bold")) self.title_label.pack(pady=20) # Button self.run_button = ctk.CTkButton(self, text="Alle Aufträge drucken", command=self.run_script) self.run_button.pack(pady=10) # Auswahl: Letzte Labels oder Orders self.dropdown_select = ctk.CTkComboBox(self, values=["Letzte Labels", "Letzte Orders"], command=self.update_file_dropdown, width=200) self.dropdown_select.set("Auswählen") self.dropdown_select.pack(pady=10) # Werte-Dropdown self.dropdown_values = ctk.CTkComboBox(self, values=[], command=self.file_selected, width=200) self.dropdown_values.pack(pady=10) # Status self.status_label = ctk.CTkLabel(self, text="", font=ctk.CTkFont(size=16)) self.status_label.pack(pady=20) # Status Animation self.status_label_logo = ctk.CTkLabel(self, text="") self.status_label_logo.pack(pady=10) # Logo unten rechts self.logo_image = ctk.CTkImage(Image.open(logo_path), size=(50, 50)) # Hier dein Logo self.logo_label = ctk.CTkLabel(self, image=self.logo_image, text="", fg_color="transparent") self.logo_label.bind("", self.open_link) # Klick-Event self.logo_label.bind("", self.on_logo_hover) # Hover-Ereignis (Maus über Logo) self.logo_label.bind("", self.on_logo_leave) # Wenn die Maus das Logo verlässt self.logo_label.place(x=0, y=0, anchor="se") # Vorläufige Position setzen # Konfigurations-Button unten links self.config_button = ctk.CTkButton(self, text="Konfiguration", width=100, command=self.run_reg_check) self.config_button.place(x=10, y=self.winfo_height() - 10, anchor="sw") # Einmaliges Binden: Position von Logo UND Button aktualisieren self.bind("", self.update_positions) def run_reg_check(self): show_config_gui(self) # Direkter Aufruf, kein Thread! def update_positions(self, event=None): # Logo rechts unten self.logo_label.place(x=self.winfo_width() - 10, y=self.winfo_height() - 10, anchor="se") # Konfig-Button links unten self.config_button.place(x=10, y=self.winfo_height() - 10, anchor="sw") def open_link(self, event=None): webbrowser.open("https://www.itdata-gera.de") # Ändere dies auf die gewünschte URL def on_logo_hover(self, event=None): self.logo_label.configure(cursor="hand2") # Cursor auf Hand setzen, wenn Maus über dem Logo schwebt def on_logo_leave(self, event=None): self.logo_label.configure(cursor="") # Setzt den Cursor zurück, wenn die Maus das Logo verlässt def load_gif(self): if not os.path.exists(gif_path): return try: gif = Image.open(gif_path) while True: frame = ImageTk.PhotoImage(gif.copy()) self.frames.append(frame) gif.seek(len(self.frames)) except EOFError: pass def load_files(self, directory): try: return [f for f in os.listdir(directory) if os.path.isfile(os.path.join(directory, f))] except FileNotFoundError: return [] def update_file_dropdown(self, event=None): selected_option = self.dropdown_select.get() directory = self.labels_dir if selected_option == "Letzte Labels" else self.orders_dir files = self.load_files(directory) if files: self.dropdown_values.configure(values=files) self.dropdown_values.set(files[0]) else: self.dropdown_values.configure(values=[]) self.dropdown_values.set("") self.run_button.configure(text="Alle Aufträge drucken", command=self.run_script) def file_selected(self, event=None): selected_file = self.dropdown_values.get() if not selected_file: return selected_folder = self.labels_dir if self.dropdown_select.get() == "Letzte Labels" else self.orders_dir full_path = os.path.join(selected_folder, selected_file) self.run_button.configure(text=f"{selected_file} drucken", command=lambda: self.run_single_file(full_path)) def run_script(self): print("run_script") self.set_status("Alle Aufträge werden gedruckt...", "blue") self.start_animation() threading.Thread(target=self.execute_script).start() def run_single_file(self, full_path): filename = os.path.basename(full_path) self.set_status(f"{filename} wird gedruckt...", "blue") self.start_animation() threading.Thread(target=self.execute_single_file, args=(full_path,)).start() def execute_script(self): try: print("execute_script") print(self.script_path) result = subprocess.run([self.script_path], capture_output=True, text=True) if result.returncode == 0: self.set_status("✅ Alle Aufträge wurden gedruckt!", "green") else: self.set_status("❌ Fehler beim Ausführen des Skripts.", "red") self.show_error(result.stderr) except Exception as e: self.set_status("❌ Unerwarteter Fehler.", "red") self.show_error(str(e)) finally: self.stop_animation() def execute_single_file(self, full_path): try: result = subprocess.run([self.script_path, full_path], capture_output=True, text=True) if result.returncode == 0: filename = os.path.basename(full_path) self.set_status(f"✅ {filename} wurde gedruckt!", "green") else: self.set_status("❌ Fehler beim Drucken.", "red") self.show_error(result.stderr) except Exception as e: self.set_status("❌ Unerwarteter Fehler.", "red") self.show_error(str(e)) finally: self.stop_animation() self.run_button.configure(text="Alle Aufträge drucken", command=self.run_script) def set_status(self, text, color): self.status_label.configure(text=text, text_color=color) def start_animation(self): self.animation_running = True self.animate() def stop_animation(self): self.animation_running = False def animate(self): if self.animation_running and self.frames: frame = self.frames[self.current_gif_frame] self.status_label_logo.configure(image=frame) self.current_gif_frame = (self.current_gif_frame + 1) % len(self.frames) self.after(30, self.animate) def show_error(self, message): ctk.CTkMessagebox(title="Fehler", message=message, icon="cancel") if hasattr(ctk, "CTkMessagebox") else print(message) REG_PATH = r"Software\PDFExporter" def read_registry_value(name): try: key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, REG_PATH, 0, winreg.KEY_READ) value, _ = winreg.QueryValueEx(key, name) winreg.CloseKey(key) return value except FileNotFoundError: return None def write_registry_value(name, value): try: key = winreg.CreateKey(winreg.HKEY_CURRENT_USER, REG_PATH) winreg.SetValueEx(key, name, 0, winreg.REG_SZ, value) winreg.CloseKey(key) except Exception as e: print(f"Fehler beim Schreiben in Registry: {e}") # def config_exists(): # return read_registry_value("APIKey") is not None def save_config_and_close(api_entry, server_entry, label_entry, order_entry, app): write_registry_value("APIKey", api_entry.get()) write_registry_value("Server", server_entry.get()) write_registry_value("LabelPrinter", label_entry.get()) write_registry_value("OrderPrinter", order_entry.get()) app.destroy() def show_config_gui(parent): ctk.set_appearance_mode("System") ctk.set_default_color_theme("blue") app = ctk.CTkToplevel(parent) app.iconbitmap(icon_path) app.title("Erstkonfiguration") window_width = 400 window_height = 400 # Bildschirmgröße ermitteln screen_width = app.winfo_screenwidth() screen_height = app.winfo_screenheight() # Position zum Zentrieren berechnen x = int((screen_width / 2) - (window_width / 2)) y = int((screen_height / 2) - (window_height / 2)) app.geometry(f"{window_width}x{window_height}+{x}+{y}") frame = ctk.CTkFrame(master=app) frame.pack(pady=20, padx=20, fill="both", expand=True) # Vorhandene Werte aus der Registry lesen existing_api = read_registry_value("APIKey") or "" existing_server = read_registry_value("Server") or "" existing_label = read_registry_value("LabelPrinter") or "" existing_order = read_registry_value("OrderPrinter") or "" # GUI Felder api_label = ctk.CTkLabel(master=frame, text="API Key:") api_label.pack(pady=5) api_entry = ctk.CTkEntry(master=frame, width=300) api_entry.insert(0, existing_api) api_entry.pack() server_label = ctk.CTkLabel(master=frame, text="Server:") server_label.pack(pady=5) server_entry = ctk.CTkEntry(master=frame, width=300) server_entry.insert(0, existing_server) server_entry.pack() label_label = ctk.CTkLabel(master=frame, text="Label-Drucker:") label_label.pack(pady=5) label_entry = ctk.CTkEntry(master=frame, width=300) label_entry.insert(0, existing_label) label_entry.pack() order_label = ctk.CTkLabel(master=frame, text="Order-Drucker:") order_label.pack(pady=5) order_entry = ctk.CTkEntry(master=frame, width=300) order_entry.insert(0, existing_order) order_entry.pack() save_button = ctk.CTkButton(master=frame, text="Speichern", command=lambda: save_config_and_close( api_entry, server_entry, label_entry, order_entry, app)) save_button.pack(pady=15) app.focus() # Setzt den Fokus app.grab_set() # Macht das Fenster modal app.lift() # Holt es in den Vordergrund if __name__ == "__main__": app = CustomerThinkerApp() app.mainloop()