From 7a531dc92ad3ef9bfe45a1887b5c59137f101a7f Mon Sep 17 00:00:00 2001 From: rattatwinko Date: Thu, 17 Apr 2025 18:49:33 +0200 Subject: [PATCH] updated some stuff (not worthy of a vb!) --- PfandApplication/main.py | 27 ++-- PfandApplication/tgtg_orderchecker/main.py | 134 +++++++++---------- PfandApplication/wiki/__init__.py | 0 PfandApplication/wiki/main.py | 147 +++++++++++++-------- run.py | 17 ++- 5 files changed, 179 insertions(+), 146 deletions(-) create mode 100644 PfandApplication/wiki/__init__.py diff --git a/PfandApplication/main.py b/PfandApplication/main.py index 8f6110b..11e89d9 100644 --- a/PfandApplication/main.py +++ b/PfandApplication/main.py @@ -16,7 +16,7 @@ import numpy as np import shutil # Local Dependencies -from PfandApplication.wiki import main as WIKI +from PfandApplication.wiki import main as wiki from PfandApplication.pfand_scanner import launch_pfand_scanner from PfandApplication.updater import open_updater as open_updater, run_silent_update from PfandApplication.tgtg_orderchecker import main as tgtg @@ -33,6 +33,7 @@ class Achievement: class PfandCalculator: def __init__(self, root): + self.achievement_image_gray = None self.root = root self.root.title("Österreichischer Pfandrechner") @@ -63,7 +64,8 @@ class PfandCalculator: self.achievement_image = self.load_achievement_image() - def load_image(self, product_name): + @staticmethod + def load_image(product_name): try: # Use Flaschen icon for Bierflasche if product_name == "Bierflasche": @@ -115,7 +117,8 @@ class PfandCalculator: print(f"Error loading achievement image: {e}") return None - def initialize_achievements(self): + @staticmethod + def initialize_achievements(): return { "each_100": Achievement("Krass, Weiter So!", "Du hast bis jetzt 100 von jedem Element gesammelt!", "each_element", 100), "each_500": Achievement("Adlersson wäre neidisch!", "Adlersson wäre neidisch auf dich! Du hast 500 von jedem Element gesammelt!", "each_element", 500), @@ -463,7 +466,7 @@ class PfandCalculator: file_menu.add_command(label="Neulanden der UI", command=self.recreate_widgets, accelerator="Strg+R") file_menu.add_command(label="Updater", command=open_updater, accelerator="Strg+U") # Added this to the File Menu too! file_menu.add_separator() - file_menu.add_command(label="Öffne PfandListe", command=WIKI.select_file, accelerator="Strg+L") + file_menu.add_command(label="Öffne PfandListe", command=wiki.select_file, accelerator="Strg+L") file_menu.add_command(label="Beenden", command=self.root.quit, accelerator="Strg+Q") file_menu.add_separator() file_menu.add_command(label="Über Programm", command=self.create_credits, accelerator="Strg+F10") @@ -538,7 +541,7 @@ class PfandCalculator: self.root.bind('', lambda e: self.export_barcodes_csv() if e.state & 0x1 else self.export_history_csv()) self.root.bind('', lambda e: self.show_add_product_window()) self.root.bind('', lambda e: self.show_manage_products_window() if e.state & 0x1 else self.show_add_product_window()) - self.root.bind('', lambda e: WIKI.select_file()) + self.root.bind('', lambda e: wiki.select_file()) self.root.bind('', lambda e: self.recreate_widgets()) self.root.bind('', lambda e: open_updater()) # New Update Feature (Version 7.4.000 UPDATER) @@ -741,7 +744,7 @@ class PfandCalculator: def confirm_deposit(): date = date_picker.get_date().strftime("%d.%m.%Y") - current_total = sum(self.quantities[product] * self.PRICES[product] + current_total = sum(self.quantities[product] * self.PRICES[product] for product in self.products) deposit_record = { @@ -1564,12 +1567,14 @@ class PfandCalculator: root = tk.Tk() app = PfandCalculator(root) - if check_for_update == True: - root.after(1, run_silent_update) # Run uc on start (1s delay) => updater.py module || UNCOMMENT IN PROD - else: + if check_for_update is None: + root.after(500, root.destroy) # We do a lil bit of Trolling here + elif not check_for_update: pass + else: + root.after(1, run_silent_update) root.mainloop() -if __name__ == "__main__": - PfandCalculator.launch(True) +# Run AutoUpdates by default +if __name__ == "__main__": PfandCalculator.launch(True) diff --git a/PfandApplication/tgtg_orderchecker/main.py b/PfandApplication/tgtg_orderchecker/main.py index f5e6877..6b325a5 100644 --- a/PfandApplication/tgtg_orderchecker/main.py +++ b/PfandApplication/tgtg_orderchecker/main.py @@ -11,115 +11,112 @@ class TGTGOrdersApp: self.parent = parent self.frame = tk.Frame(self.parent, bg="#ffffff") self.frame.pack(fill="both", expand=True) - + self.notebook = ttk.Notebook(self.frame) self.notebook.pack(fill="both", expand=True) - + self.orders_tab = tk.Frame(self.notebook, bg="#ffffff") - self.notebook.add(self.orders_tab, text="Orders") - + self.notebook.add(self.orders_tab, text="Bestellungen") + self.log_tab = tk.Frame(self.notebook, bg="#ffffff") - self.notebook.add(self.log_tab, text="Log") - + self.notebook.add(self.log_tab, text="Protokoll") + self.log_text = tk.Text(self.log_tab, wrap=tk.WORD, height=15, font=("Arial", 10), bg="#f0f0f0") self.log_text.pack(fill="both", expand=True, padx=10, pady=10) - + self.order_frame = tk.Frame(self.orders_tab, bg="#ffffff") self.order_frame.pack(fill="both", expand=True, padx=10, pady=10) - + self.menu = Menu(self.parent) self.parent.config(menu=self.menu) self.filemenu = Menu(self.menu) - self.menu.add_cascade(label="File", menu=self.filemenu) - self.filemenu.add_command(label="Exit", command=self.exit_applet) - self.filemenu.add_command(label="Refetch", command=self.display_orders) - self.filemenu.add_command(label="Save Log", command=self.save_log) + self.menu.add_cascade(label="Datei", menu=self.filemenu) + self.filemenu.add_command(label="Beenden", command=self.exit_applet) + self.filemenu.add_command(label="Aktualisieren", command=self.display_orders) + self.filemenu.add_command(label="Protokoll speichern", command=self.save_log) self.filemenu.add_separator() - self.filemenu.add_command(label="About", command=self.about) - + self.filemenu.add_command(label="Über", command=self.about) + self.parent.after(1000, self.on_startup) - + def log_message(self, message): timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") self.log_text.insert(tk.END, f"{timestamp} - {message}\n") self.log_text.yview(tk.END) - - def format_time(self, iso_time): + + @staticmethod + def format_time(iso_time): try: dt = datetime.fromisoformat(iso_time.replace("Z", "+00:00")) local_time = dt.astimezone() return local_time.strftime("%H:%M") except ValueError: - return "Unknown Error!" - + return "Unbekannter Fehler!" + def fetch_orders(self): - self.log_message("[ INFO ]: Fetching orders...") + self.log_message("[ INFO ]: Bestellungen werden abgerufen...") try: active_orders = client.get_active() if not isinstance(active_orders, dict) or "orders" not in active_orders: - raise ValueError("Unexpected API response format.") + raise ValueError("Unerwartetes API-Antwortformat.") orders_list = active_orders.get("orders", []) except Exception as e: - self.log_message(f"[ ERROR ]: Error fetching active orders: {e}") - messagebox.showerror("Error", f"Error fetching active orders: {e}") + self.log_message(f"[ FEHLER ]: Fehler beim Abrufen aktiver Bestellungen: {e}") + messagebox.showerror("Fehler", f"Fehler beim Abrufen aktiver Bestellungen: {e}") return [] - + orders_data = [] for order in orders_list: try: order_info = { - "name": order.get("item_name", "Unknown"), - "store_name": order.get("store_name", "Unknown"), - "address": order.get("pickup_location", {}).get("address", {}).get("address_line", "Unknown"), + "name": order.get("item_name", "Unbekannt"), + "store_name": order.get("store_name", "Unbekannt"), + "address": order.get("pickup_location", {}).get("address", {}).get("address_line", "Unbekannt"), "quantity": order.get("quantity", 1), "price": order.get("total_price", {}).get("minor_units", 0) / (10 ** order.get("total_price", {}).get("decimals", 2)), - "currency": order.get("total_price", {}).get("code", "Unknown"), - "payment_method": order.get("payment_method_display_name", "Unknown"), + "currency": order.get("total_price", {}).get("code", "Unbekannt"), + "payment_method": order.get("payment_method_display_name", "Unbekannt"), "pickup_window": { - "start": self.format_time(order.get("pickup_interval", {}).get("start", "Unknown")), - "end": self.format_time(order.get("pickup_interval", {}).get("end", "Unknown")) + "start": self.format_time(order.get("pickup_interval", {}).get("start", "Unbekannt")), + "end": self.format_time(order.get("pickup_interval", {}).get("end", "Unbekannt")) }, "image_url": order.get("item_cover_image", {}).get("current_url", "") } orders_data.append(order_info) except Exception as e: - self.log_message(f"[ FATAL ERROR ]: Skipping an order due to an error: {e}") + self.log_message(f"[ KRITISCHER FEHLER ]: Eine Bestellung wird übersprungen: {e}") return orders_data - - + def display_orders(self): - self.log_message("[ INFO ]: Displaying orders...") + self.log_message("[ INFO ]: Bestellungen werden angezeigt...") orders = self.fetch_orders() if not orders: - messagebox.showinfo("Info", "No active orders found.") - self.log_message("[ ERROR ]: No active orders found.") + messagebox.showinfo("Info", "Keine aktiven Bestellungen gefunden.") + self.log_message("[ FEHLER ]: Keine aktiven Bestellungen gefunden.") return - # Clear existing widgets for widget in self.order_frame.winfo_children(): widget.destroy() - # Create a scrollable frame inside a Canvas canvas = tk.Canvas(self.order_frame, bg="#ffffff") scroll_frame = tk.Frame(canvas, bg="#ffffff") scrollbar = tk.Scrollbar(self.order_frame, orient="vertical", command=canvas.yview) canvas.configure(yscrollcommand=scrollbar.set) - + scrollbar.pack(side="right", fill="y") canvas.pack(side="left", fill="both", expand=True) canvas.create_window((0, 0), window=scroll_frame, anchor="nw") - # Store image references to prevent garbage collection image_refs = [] for order in orders: text = (f"{order['name']} - {order['store_name']}\n" - f"Address: {order['address']}\n" - f"Quantity: {order['quantity']}\n" - f"Price: {order['price']} {order['currency']}\n" - f"Payment: {order['payment_method']}\n" - f"Pickup: {order['pickup_window']['start']} to {order['pickup_window']['end']}\n") + f"Adresse: {order['address']}\n" + f"Menge: {order['quantity']}\n" + f"Preis: {order['price']} {order['currency']}\n" + f"Zahlung: {order['payment_method']}\n" + f"Abholung: {order['pickup_window']['start']} bis {order['pickup_window']['end']}\n") label = tk.Label(scroll_frame, text=text, justify="left", padx=10, pady=5, anchor="w", font=("Arial", 10), bg="#f0f0f0", relief="ridge") @@ -134,50 +131,47 @@ class TGTGOrdersApp: img_tk = ImageTk.PhotoImage(img) img_label = tk.Label(scroll_frame, image=img_tk) - img_label.image = img_tk # Store reference - image_refs.append(img_tk) # Prevent garbage collection + img_label.image = img_tk + image_refs.append(img_tk) img_label.pack(pady=5) except Exception as e: - self.log_message(f"[ ERROR ]: Failed to load image: {e}") + self.log_message(f"[ FEHLER ]: Bild konnte nicht geladen werden: {e}") - # Update scroll region scroll_frame.update_idletasks() canvas.config(scrollregion=canvas.bbox("all")) - # Enable scrolling with the mouse wheel def on_mouse_wheel(event): canvas.yview_scroll(-1 * (event.delta // 120), "units") - canvas.bind_all("", on_mouse_wheel) # Windows & MacOS - canvas.bind_all("", lambda e: canvas.yview_scroll(-1, "units")) # Linux Scroll Up - canvas.bind_all("", lambda e: canvas.yview_scroll(1, "units")) # Linux Scroll Down - + canvas.bind_all("", on_mouse_wheel) + canvas.bind_all("", lambda e: canvas.yview_scroll(-1, "units")) + canvas.bind_all("", lambda e: canvas.yview_scroll(1, "units")) + def on_startup(self): - self.log_message("[ INFO ]: Application started.") + self.log_message("[ INFO ]: Anwendung gestartet.") self.display_orders() - + def exit_applet(self): - self.log_message("[ INFO ]: Exiting Applet") + self.log_message("[ INFO ]: Anwendung wird beendet.") self.parent.quit() - - def about(self): - messagebox.showinfo("About", "PythonTGTG Script for fetching Orders on Desktop") - + + @staticmethod + def about(): + messagebox.showinfo("Über", "TGTG OrderChecker PV2-PKG1\n PfandApplication ©") + def save_log(self): try: log_content = self.log_text.get("1.0", tk.END) - with open("log_file.log", "w") as log_file: + with open("protokoll_datei.log", "w") as log_file: log_file.write(log_content) - self.log_message("[ INFO ]: Log file saved successfully.") + self.log_message("[ INFO ]: Protokolldatei erfolgreich gespeichert.") except Exception as e: - self.log_message(f"[ ERROR ]: Error saving log file: {e}") - messagebox.showerror("Error", f"Error saving log file: {e}") + self.log_message(f"[ FEHLER ]: Fehler beim Speichern des Protokolls: {e}") + messagebox.showerror("Fehler", f"Fehler beim Speichern des Protokolls: {e}") def start_tgtg(parent=None): - new_window = tk.Toplevel(parent) # Create a new window - new_window.title("TGTG Bestellungen") + new_window = tk.Toplevel(parent) + new_window.title("TGTG Orders") new_window.geometry("500x600") - # Start the TGTGOrdersApp inside this new window app = TGTGOrdersApp(new_window) - diff --git a/PfandApplication/wiki/__init__.py b/PfandApplication/wiki/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/PfandApplication/wiki/main.py b/PfandApplication/wiki/main.py index e980eda..c1b4683 100644 --- a/PfandApplication/wiki/main.py +++ b/PfandApplication/wiki/main.py @@ -1,8 +1,9 @@ -import tkinter as tk -from tkinter import ttk import csv import os import re +import tkinter as tk +from tkinter import ttk + def select_file(callback=None): def set_choice(choice): @@ -15,23 +16,23 @@ def select_file(callback=None): callback(filename) else: start_app(filename) - + select_window = tk.Tk() select_window.title("Wähle eine Liste") select_window.geometry("300x200") - + label = tk.Label(select_window, text="Bitte eine Liste wählen:", font=("Arial", 12)) label.pack(pady=10) - + spar_button = tk.Button(select_window, text="SPAR", command=lambda: set_choice("SPAR"), width=15) spar_button.pack(pady=5) - + hofer_button = tk.Button(select_window, text="HOFER", command=lambda: set_choice("HOFER"), width=15) hofer_button.pack(pady=5) - + wiki_button = tk.Button(select_window, text="Wiki", command=lambda: set_choice("Wiki"), width=15) wiki_button.pack(pady=5) - + select_window.mainloop() class CSVViewerApp: @@ -39,95 +40,129 @@ class CSVViewerApp: self.root = root title = "PFANDLISTE - SPAR" if "SPAR" in filename else "PFANDLISTE - HOFER" self.root.title(title) - self.root.geometry("600x400") - + self.root.geometry("800x600") + self.label = tk.Label(root, text=title, font=("Arial", 16, "bold")) self.label.pack(pady=10) - + self.frame = tk.Frame(root) self.frame.pack(fill=tk.BOTH, expand=True) - - self.tree = ttk.Treeview(self.frame) + + self.tree = ttk.Treeview(self.frame, show="headings") self.tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) - + self.scrollbar = ttk.Scrollbar(self.frame, orient="vertical", command=self.tree.yview) self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y) - + self.tree.configure(yscroll=self.scrollbar.set) - + + # Create a frame for search functionality and style it + search_frame = tk.Frame(root, pady=10, padx=20) + search_frame.pack(fill=tk.X) + + self.search_label = tk.Label(search_frame, text="Search:", font=("Arial", 12), anchor="w") + self.search_label.pack(side=tk.LEFT) + + self.search_entry = tk.Entry(search_frame, font=("Arial", 12), relief="solid", borderwidth=2) + self.search_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=10) + self.search_entry.bind("", self.search) + self.load_csv(filename) - - def load_csv(self, filename): + + def search(self, event): + search_term = self.search_entry.get().lower() + for row in self.tree.get_children(): + self.tree.delete(row) + self.load_csv(self.filename, search_term) + + def load_csv(self, filename, search_term=""): + self.filename = filename try: with open(filename, newline='', encoding='utf-8') as file: reader = csv.reader(file) headers = next(reader, None) - - self.tree['columns'] = headers + + self.tree["columns"] = headers self.tree.heading("#0", text="#") # First column for index - self.tree.column("#0", width=50) - + self.tree.column("#0", width=50, anchor="center") + for header in headers: self.tree.heading(header, text=header) self.tree.column(header, anchor="center") - + for i, row in enumerate(reader, start=1): - self.tree.insert("", "end", text=i, values=row) + if any(search_term.lower() in str(cell).lower() for cell in row): + self.tree.insert("", "end", text=i, values=row) except FileNotFoundError: print(f"Error: {filename} not found!") except Exception as e: print(f"Error loading CSV: {e}") -## Doesnt really work yet -## In the Future maybe -def format_markdown(text_area, text): - text_area.tag_configure("bold", font=("Arial", 10, "bold")) - text_area.tag_configure("center", justify="center") - - text_area.delete("1.0", tk.END) - - segments = [] - last_end = 0 - - for match in re.finditer(r'

(.*?)

|\*\*(.*?)\*\*', text, re.DOTALL): - segments.append((text[last_end:match.start()], None)) - - if match.group(1): # Centered text - segments.append((match.group(1), "center")) - elif match.group(2): # Bold text - segments.append((match.group(2), "bold")) - - last_end = match.end() - - segments.append((text[last_end:], None)) - - for segment, tag in segments: - text_area.insert(tk.END, segment, tag if tag else "") + def sort_column(self, col): + data = [(self.tree.item(item)["values"], item) for item in self.tree.get_children("")] + data.sort(key=lambda x: x[0][col]) + for idx, item in enumerate(data): + self.tree.move(item[1], '', idx) + + def right_click_menu(self, event): + selected_item = self.tree.selection() + menu = tk.Menu(self.root, tearoff=0) + menu.add_command(label="Copy", command=lambda: self.copy_cell(selected_item)) + menu.post(event.x_root, event.y_root) + + def copy_cell(self, selected_item): + # Copy data from the selected row to clipboard + if selected_item: + row_values = self.tree.item(selected_item[0])["values"] + self.root.clipboard_clear() + self.root.clipboard_append(' | '.join(row_values)) def open_wiki(): wiki_window = tk.Tk() wiki_window.title("Wiki") wiki_window.geometry("500x400") - + text_area = tk.Text(wiki_window, wrap=tk.WORD) text_area.pack(expand=True, fill=tk.BOTH) - + filename = os.path.join("PfandApplication/wiki", "wiki.md") - + try: with open(filename, "r", encoding="utf-8") as file: content = file.read() format_markdown(text_area, content) except FileNotFoundError: text_area.insert(tk.END, f"Fehler: '{filename}' nicht gefunden!") - + wiki_window.mainloop() +def format_markdown(text_area, text): + text_area.tag_configure("bold", font=("Arial", 10, "bold")) + text_area.tag_configure("center", justify="center") + + text_area.delete("1.0", tk.END) + + segments = [] + last_end = 0 + + for match in re.finditer(r'

(.*?)

|\*\*(.*?)\*\*', text, re.DOTALL): + segments.append((text[last_end:match.start()], None)) + + if match.group(1): # Centered text + segments.append((match.group(1), "center")) + elif match.group(2): # Bold text + segments.append((match.group(2), "bold")) + + last_end = match.end() + + segments.append((text[last_end:], None)) + + for segment, tag in segments: + text_area.insert(tk.END, segment, tag if tag else "") + def start_app(filename): root = tk.Tk() app = CSVViewerApp(root, filename) root.mainloop() -if __name__ == "__main__": - select_file() - +if __name__ == "__main__": select_file() \ No newline at end of file diff --git a/run.py b/run.py index 421b8f7..0337a5c 100644 --- a/run.py +++ b/run.py @@ -1,15 +1,14 @@ from PfandApplication import main +if __name__ == "__main__": main.PfandCalculator.launch(False) """ -If the function launch gets called with - -False -> No autoupdates will be run || Best for Debugging! - -True -> Autoupdates will be run +/******************************************** +* Launch Function Parameters * +* * +* True -> Auto-Update * +* False -> Dont Auto-Update * +* None -> Idk check it :3 * +********************************************/ """ - - -if __name__ == "__main__": - main.PfandCalculator.launch(False)