Lauderbach_PDF_Export/gui.py

358 lines
13 KiB
Python

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('dist/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("PDFExporter 1.0")
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 Aufträge drucken
self.run_button = ctk.CTkButton(self, text="Alle Aufträge drucken", command=self.run_script,width=200,height=60,font=ctk.CTkFont(size=18) )
self.run_button.pack(pady=50)
# 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)
# Archiv Buttons
button_frame = ctk.CTkFrame(self, fg_color="transparent")
button_frame.pack(pady=0)
## Archive Label
self.labels_button = ctk.CTkButton(
button_frame,
text="Archiv Labels",
command=self.open_labels_folder,
width=100,
height=50
)
self.labels_button.pack(side="left",padx=10, pady=0)
self.paketlist_button = ctk.CTkButton(
button_frame,
text="Archiv Paketlisten",
command=self.open_paketlist_folder,
width=100,
height=50
)
self.paketlist_button.pack(side="right",padx=10, pady=0)
# 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("<Button-1>", self.open_link) # Klick-Event
self.logo_label.bind("<Enter>", self.on_logo_hover) # Hover-Ereignis (Maus über Logo)
self.logo_label.bind("<Leave>", 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("<Configure>", 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_labels_folder(self):
folder_path = os.path.abspath("label")
if sys.platform == "win32":
os.startfile(folder_path)
def open_paketlist_folder(self):
folder_path = os.path.abspath("orders")
if sys.platform == "win32":
os.startfile(folder_path)
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")
self.stop_animation()
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.status_label_logo.pack(pady=10)
self.animation_running = True
self.animate()
def stop_animation(self):
self.animation_running = False
self.status_label_logo.pack_forget()
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()