From 29b8fc84dffc461471de47d470ffc85530955591 Mon Sep 17 00:00:00 2001 From: rattatwinko Date: Thu, 12 Jun 2025 21:16:43 +0200 Subject: [PATCH] refactored the logic of how todo list is loade --- PfandApplication/main.py | 1237 +++++++++++++++++++++------------ PfandApplication/todo/main.py | 33 +- 2 files changed, 819 insertions(+), 451 deletions(-) diff --git a/PfandApplication/main.py b/PfandApplication/main.py index 31b695d..96da56b 100644 --- a/PfandApplication/main.py +++ b/PfandApplication/main.py @@ -22,6 +22,8 @@ from PfandApplication.updater import open_updater as open_updater, run_silent_up from PfandApplication.tgtg_orderchecker import main as tgtg from PfandApplication.tgtg_orderchecker import setupkey as tgtg_kt from PfandApplication.todo import main as todo +from PfandApplication.todo.main import todo_instance + class Achievement: def __init__(self, title, description, condition_type, condition_value): @@ -32,37 +34,38 @@ class Achievement: self.unlocked = False self.unlock_date = None + class PfandCalculator: def __init__(self, root): self.achievement_image_gray = None self.root = root self.root.title("Österreichischer Pfandrechner") - + # Load products and prices from JSON self.load_products() - + self.quantities = {} self.images = {} self.spinboxes = {} # Store spinbox references self.deposit_history = self.load_deposit_history() self.scanned_barcodes = set() self.barcode_history = [] # Store barcode scan history - + self.achievements = self.initialize_achievements() self.load_achievements() - - if not os.path.exists('PfandApplication/images'): - os.makedirs('images') - + + if not os.path.exists("PfandApplication/images"): + os.makedirs("images") + self.create_menu() self.load_quantities() self.create_widgets() - + # Scanner window self.scanner_window = None self.cap = None self.scanning = False - + self.achievement_image = self.load_achievement_image() @staticmethod @@ -71,7 +74,7 @@ class PfandCalculator: # Use Flaschen icon for Bierflasche if product_name == "Bierflasche": product_name = "Flaschen" - + image_path = f"PfandApplication/images/{product_name.lower()}.png" if os.path.exists(image_path): try: @@ -87,7 +90,7 @@ class PfandCalculator: except Exception as e: print(f"Error loading image for {product_name}: {e}") return None - + def load_achievement_image(self): try: image_path = "PfandApplication/images/auszeichnung.png" @@ -98,7 +101,7 @@ class PfandCalculator: # Store both normal and gray versions self.achievement_image = ImageTk.PhotoImage(image) # Create grayscale version while preserving transparency - gray_image = Image.new('RGBA', image.size) + gray_image = Image.new("RGBA", image.size) for x in range(image.width): for y in range(image.height): r, g, b, a = image.getpixel((x, y)) @@ -121,61 +124,140 @@ class PfandCalculator: @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), - "each_1000": Achievement("Arbeitslos I", "Arbeitsamt hat angerufen! Du hast 1000 von jedem Element gesammelt!", "each_element", 1000), - "total_2000": Achievement("Arbeitslos II", "Das Arbeitsamt hat angst vor dir! Du hast 2000 totale Elemente gesammelt!", "total_elements", 2000), - "total_3000": Achievement("Arbeitslos III", "Drachenlord hat angst vor dir! Du hast mehr wie 3000 Elemente gesammelt!", "total_elements", 3000), - "total_over_3000": Achievement("Krankhafte Sucht!", "Du hast echt einen Vogel! Pfandangel #1! Du hast >3000 gesammelt!", "total_elements", 3001), + "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, + ), + "each_1000": Achievement( + "Arbeitslos I", + "Arbeitsamt hat angerufen! Du hast 1000 von jedem Element gesammelt!", + "each_element", + 1000, + ), + "total_2000": Achievement( + "Arbeitslos II", + "Das Arbeitsamt hat angst vor dir! Du hast 2000 totale Elemente gesammelt!", + "total_elements", + 2000, + ), + "total_3000": Achievement( + "Arbeitslos III", + "Drachenlord hat angst vor dir! Du hast mehr wie 3000 Elemente gesammelt!", + "total_elements", + 3000, + ), + "total_over_3000": Achievement( + "Krankhafte Sucht!", + "Du hast echt einen Vogel! Pfandangel #1! Du hast >3000 gesammelt!", + "total_elements", + 3001, + ), "first_deposit": Achievement("Depositer!", "Guter Anfang!", "deposits", 1), - "deposits_10": Achievement("Depositer I", "Cool, Weiter So!", "deposits", 10), - "deposits_50": Achievement("Depositer II", "WoW, Echt viele Abgaben!", "deposits", 50), - "deposits_100": Achievement("Depositer III", "Du bist der Meister der Abgaben!", "deposits", 100), - "deposits_150": Achievement("Meister Depositer", "Der Pfandautomat hat Angst vor dir, so viel wie du Abgegeben hast müsstest du eine Villa besitzen!", "deposits", 150), + "deposits_10": Achievement( + "Depositer I", "Cool, Weiter So!", "deposits", 10 + ), + "deposits_50": Achievement( + "Depositer II", "WoW, Echt viele Abgaben!", "deposits", 50 + ), + "deposits_100": Achievement( + "Depositer III", "Du bist der Meister der Abgaben!", "deposits", 100 + ), + "deposits_150": Achievement( + "Meister Depositer", + "Der Pfandautomat hat Angst vor dir, so viel wie du Abgegeben hast müsstest du eine Villa besitzen!", + "deposits", + 150, + ), # New scanner achievements - "first_scan": Achievement("Scanner Neuling", "Du hast deinen ersten Barcode gescannt!", "scans", 1), - "scans_50": Achievement("Scanner Pro", "50 Barcodes gescannt - du kennst dich aus!", "scans", 50), - "scans_100": Achievement("Scanner Meister", "100 Barcodes gescannt - der Profi ist da!", "scans", 100), - "scans_500": Achievement("Scanner Legende", "500 Barcodes gescannt - legendärer Scanner Status erreicht!", "scans", 500), - "daily_10": Achievement("Tages Champion", "10 Barcodes an einem Tag gescannt!", "daily_scans", 10), - "daily_25": Achievement("Tages Meister", "25 Barcodes an einem Tag gescannt - sehr fleißig!", "daily_scans", 25) + "first_scan": Achievement( + "Scanner Neuling", "Du hast deinen ersten Barcode gescannt!", "scans", 1 + ), + "scans_50": Achievement( + "Scanner Pro", "50 Barcodes gescannt - du kennst dich aus!", "scans", 50 + ), + "scans_100": Achievement( + "Scanner Meister", + "100 Barcodes gescannt - der Profi ist da!", + "scans", + 100, + ), + "scans_500": Achievement( + "Scanner Legende", + "500 Barcodes gescannt - legendärer Scanner Status erreicht!", + "scans", + 500, + ), + "daily_10": Achievement( + "Tages Champion", + "10 Barcodes an einem Tag gescannt!", + "daily_scans", + 10, + ), + "daily_25": Achievement( + "Tages Meister", + "25 Barcodes an einem Tag gescannt - sehr fleißig!", + "daily_scans", + 25, + ), } def load_achievements(self): try: - with open('achievements.json', 'r') as f: + with open("achievements.json", "r") as f: data = json.load(f) for key, achievement_data in data.items(): if key in self.achievements: - self.achievements[key].unlocked = achievement_data['unlocked'] - self.achievements[key].unlock_date = achievement_data['unlock_date'] + self.achievements[key].unlocked = achievement_data["unlocked"] + self.achievements[key].unlock_date = achievement_data[ + "unlock_date" + ] except FileNotFoundError: pass def save_achievements(self): data = { key: { - 'unlocked': achievement.unlocked, - 'unlock_date': achievement.unlock_date + "unlocked": achievement.unlocked, + "unlock_date": achievement.unlock_date, } for key, achievement in self.achievements.items() } - with open('achievements.json', 'w') as f: + with open("achievements.json", "w") as f: json.dump(data, f) def check_achievements(self): - total_elements = sum(self.deposit_history[-1]['quantities'].values()) if self.deposit_history else 0 - all_time_total = sum(sum(d['quantities'].values()) for d in self.deposit_history) + total_elements = ( + sum(self.deposit_history[-1]["quantities"].values()) + if self.deposit_history + else 0 + ) + all_time_total = sum( + sum(d["quantities"].values()) for d in self.deposit_history + ) deposits_count = len(self.deposit_history) - + for achievement in ["each_100", "each_500", "each_1000"]: if not self.achievements[achievement].unlocked: - if all(self.deposit_history[-1]['quantities'][product] >= self.achievements[achievement].condition_value - for product in self.products): + if all( + self.deposit_history[-1]["quantities"][product] + >= self.achievements[achievement].condition_value + for product in self.products + ): self.unlock_achievement(achievement) for achievement in ["total_2000", "total_3000", "total_over_3000"]: - if not self.achievements[achievement].unlocked and all_time_total >= self.achievements[achievement].condition_value: + if ( + not self.achievements[achievement].unlocked + and all_time_total >= self.achievements[achievement].condition_value + ): self.unlock_achievement(achievement) deposit_achievements = { @@ -183,11 +265,14 @@ class PfandCalculator: 10: "deposits_10", 50: "deposits_50", 100: "deposits_100", - 150: "deposits_150" + 150: "deposits_150", } - + for count, achievement_key in deposit_achievements.items(): - if not self.achievements[achievement_key].unlocked and deposits_count >= count: + if ( + not self.achievements[achievement_key].unlocked + and deposits_count >= count + ): self.unlock_achievement(achievement_key) def unlock_achievement(self, achievement_key): @@ -196,8 +281,10 @@ class PfandCalculator: achievement.unlocked = True achievement.unlock_date = datetime.now().strftime("%d.%m.%Y") self.save_achievements() - messagebox.showinfo("Auszeichnung freigeschaltet!", - f"Neue Auszeichnung: {achievement.title}\n\n{achievement.description}") + messagebox.showinfo( + "Auszeichnung freigeschaltet!", + f"Neue Auszeichnung: {achievement.title}\n\n{achievement.description}", + ) def show_achievements(self): achievements_window = tk.Toplevel(self.root) @@ -222,8 +309,7 @@ class PfandCalculator: scrollable_frame = ttk.Frame(canvas) scrollable_frame.bind( - "", - lambda e: canvas.configure(scrollregion=canvas.bbox("all")) + "", lambda e: canvas.configure(scrollregion=canvas.bbox("all")) ) canvas.create_window((0, 0), window=scrollable_frame, anchor="nw") @@ -233,11 +319,11 @@ class PfandCalculator: canvas.yview_scroll(int(-1 * (event.delta / 120)), "units") def _bind_mousewheel(widget): - widget.bind('', _on_mousewheel) + widget.bind("", _on_mousewheel) for child in widget.winfo_children(): _bind_mousewheel(child) - canvas.bind('', _on_mousewheel) + canvas.bind("", _on_mousewheel) _bind_mousewheel(scrollable_frame) sammeln_achievements = { @@ -246,7 +332,7 @@ class PfandCalculator: "each_1000": self.achievements["each_1000"], "total_2000": self.achievements["total_2000"], "total_3000": self.achievements["total_3000"], - "total_over_3000": self.achievements["total_over_3000"] + "total_over_3000": self.achievements["total_over_3000"], } abgeben_achievements = { @@ -254,7 +340,7 @@ class PfandCalculator: "deposits_10": self.achievements["deposits_10"], "deposits_50": self.achievements["deposits_50"], "deposits_100": self.achievements["deposits_100"], - "deposits_150": self.achievements["deposits_150"] + "deposits_150": self.achievements["deposits_150"], } scanner_achievements = { @@ -263,7 +349,7 @@ class PfandCalculator: "scans_100": self.achievements["scans_100"], "scans_500": self.achievements["scans_500"], "daily_10": self.achievements["daily_10"], - "daily_25": self.achievements["daily_25"] + "daily_25": self.achievements["daily_25"], } row = 0 @@ -271,15 +357,16 @@ class PfandCalculator: def add_group_header(title): nonlocal row header_frame = ttk.Frame(scrollable_frame) - header_frame.grid(row=row, column=0, sticky='ew', padx=5, pady=(15, 5)) - - header_label = ttk.Label(header_frame, text=title, - font=('TkDefaultFont', 12, 'bold')) - header_label.pack(anchor='w') - - separator = ttk.Separator(scrollable_frame, orient='horizontal') + header_frame.grid(row=row, column=0, sticky="ew", padx=5, pady=(15, 5)) + + header_label = ttk.Label( + header_frame, text=title, font=("TkDefaultFont", 12, "bold") + ) + header_label.pack(anchor="w") + + separator = ttk.Separator(scrollable_frame, orient="horizontal") row += 1 - separator.grid(row=row, column=0, sticky='ew', pady=2) + separator.grid(row=row, column=0, sticky="ew", pady=2) row += 1 def add_achievement(key, achievement): @@ -288,7 +375,7 @@ class PfandCalculator: return frame = ttk.Frame(scrollable_frame) - frame.grid(row=row, column=0, sticky='ew', padx=5, pady=5) + frame.grid(row=row, column=0, sticky="ew", padx=5, pady=5) if self.achievement_image: if achievement.unlocked: @@ -298,28 +385,34 @@ class PfandCalculator: image_label.grid(row=0, column=0, rowspan=2, padx=(5, 10), pady=5) content_frame = ttk.Frame(frame) - content_frame.grid(row=0, column=1, sticky='nsew', pady=5) + content_frame.grid(row=0, column=1, sticky="nsew", pady=5) - title_label = ttk.Label(content_frame, text=achievement.title, - font=('TkDefaultFont', 10, 'bold')) - title_label.grid(row=0, column=0, sticky='w') + title_label = ttk.Label( + content_frame, + text=achievement.title, + font=("TkDefaultFont", 10, "bold"), + ) + title_label.grid(row=0, column=0, sticky="w") if achievement.unlocked: - date_label = ttk.Label(content_frame, - text=f"Freigeschaltet am: {achievement.unlock_date}", - font=('TkDefaultFont', 8)) + date_label = ttk.Label( + content_frame, + text=f"Freigeschaltet am: {achievement.unlock_date}", + font=("TkDefaultFont", 8), + ) date_label.grid(row=0, column=1, padx=(20, 0)) - desc_label = ttk.Label(content_frame, text=achievement.description, - wraplength=600) - desc_label.grid(row=1, column=0, columnspan=2, sticky='w', pady=(2, 0)) + desc_label = ttk.Label( + content_frame, text=achievement.description, wraplength=600 + ) + desc_label.grid(row=1, column=0, columnspan=2, sticky="w", pady=(2, 0)) content_frame.grid_columnconfigure(0, weight=1) content_frame.grid_columnconfigure(1, weight=0) - separator = ttk.Separator(scrollable_frame, orient='horizontal') + separator = ttk.Separator(scrollable_frame, orient="horizontal") row += 1 - separator.grid(row=row, column=0, sticky='ew', pady=5) + separator.grid(row=row, column=0, sticky="ew", pady=5) row += 1 _bind_mousewheel(frame) @@ -352,6 +445,7 @@ class PfandCalculator: Basically create Toplevel Windows which display Details about each "Integration" Use a image for each one (path -> images/versions) """ + def create_credits(self, future_icons): about_window = tk.Toplevel(self.root) about_window.title("Über Programm") @@ -362,7 +456,9 @@ class PfandCalculator: about_window.grid_columnconfigure(1, weight=1) about_window.grid_rowconfigure(0, weight=1) - image_path = os.path.join(os.getcwd(), "PfandApplication", "images", "versions", "pineapple.png") + image_path = os.path.join( + os.getcwd(), "PfandApplication", "images", "versions", "pineapple.png" + ) try: img = Image.open(image_path).convert("RGBA") @@ -393,7 +489,7 @@ class PfandCalculator: padx=10, pady=10, justify="center", - anchor="center" + anchor="center", ) label.grid(row=1, column=0, columnspan=2, pady=0, sticky="nsew") @@ -401,41 +497,54 @@ class PfandCalculator: url_future_icons = "https://www.svgrepo.com/svg/266606/watermelon" # Website button - website_button = tk.Button(about_window, text="Webseite", command=lambda: webbrowser.open(url)) + website_button = tk.Button( + about_window, text="Webseite", command=lambda: webbrowser.open(url) + ) website_button.grid(row=2, column=0, padx=10, pady=10, sticky="ew") if future_icons: - future_icon_button = tk.Button(about_window, text="Futur-Icons", command=lambda: webbrowser.open(url_future_icons)) + future_icon_button = tk.Button( + about_window, + text="Futur-Icons", + command=lambda: webbrowser.open(url_future_icons), + ) future_icon_button.grid(row=3, column=0, padx=10, pady=10, sticky="ew") else: future_icon_button = None # Close button - close_button = tk.Button(about_window, text="Schließen", command=about_window.destroy) + close_button = tk.Button( + about_window, text="Schließen", command=about_window.destroy + ) close_button.grid(row=2, column=1, padx=10, pady=10, sticky="ew") - todo_button = tk.Button(about_window, text="Load Todo", command=self.create_todo_list) - todo_button.grid(row=3,column=2,padx=10,pady=10,sticky="ew") + todo_button = ( + tk.Button( # Looks like fucking shit , fix this horsecrap in the future + about_window, text="Load Todo", command=self.create_todo_list + ) + ) + todo_button.grid(row=2, column=3, padx=10, pady=10, sticky="ew") # Todo def create_todo_list(self): todo = tk.Toplevel(self.root) todo.title("Todo Liste") - todo.resizable(True,True) + todo.resizable(True, True) for col in range(2): - todo.grid_columnconfigure(col,weight=1) - todo.grid_rowconfigure(0,weight=0) + todo.grid_columnconfigure(col, weight=1) + todo.grid_rowconfigure(0, weight=0) # Shit will display here that is going to be loaded from external - label_todo = tk.Label ( + label_todo = tk.Label( todo, - text=(f"{todo_instance.load_todo()}"), + text=todo_instance.load_todo(), padx=10, pady=10, justify="center", - anchor="center" + anchor="center", ) + label_todo.grid(row=1, column=0, columnspan=2, pady=0, sticky="nsew") # TGTG Credits def TGTG_credits(self): @@ -447,7 +556,9 @@ class PfandCalculator: about_tgtg.grid_columnconfigure(col, weight=1) about_tgtg.grid_rowconfigure(0, weight=1) - image_path = os.path.join(os.getcwd(), "PfandApplication", "images", "versions", "tgtg.png") + image_path = os.path.join( + os.getcwd(), "PfandApplication", "images", "versions", "tgtg.png" + ) try: img = Image.open(image_path).convert("RGBA") @@ -465,29 +576,34 @@ class PfandCalculator: about_tgtg.tgtg_img = tgtg_img img_label = tk.Label(about_tgtg, image=tgtg_img) - img_label.grid(row=0, column=0, columnspan=2, pady=(15, 5), sticky='n') + img_label.grid(row=0, column=0, columnspan=2, pady=(15, 5), sticky="n") except Exception as e: print(f"Fehler beim Laden des Bildes: {e}") label_TGTG = tk.Label( about_tgtg, text=( - "PV2-PKG1 - ( PfandVersion 2 - Package 1 )\n" - "\nTooGoodToGo OrderChecker" + "PV2-PKG1 - ( PfandVersion 2 - Package 1 )\n\nTooGoodToGo OrderChecker" ), padx=10, pady=10, justify="center", - anchor="center" + anchor="center", ) label_TGTG.grid(row=1, column=0, columnspan=2, sticky="nsew") url_TGTG = "https://github.com/ZockerKatze/tgtg_orderchecker" - website_button = tk.Button(about_tgtg, text="Öffne Repository im Browser", command=lambda: webbrowser.open(url_TGTG)) + website_button = tk.Button( + about_tgtg, + text="Öffne Repository im Browser", + command=lambda: webbrowser.open(url_TGTG), + ) website_button.grid(row=2, column=0, padx=10, pady=10, sticky="ew") - close_button = tk.Button(about_tgtg, text="Schließen", command=about_tgtg.destroy) + close_button = tk.Button( + about_tgtg, text="Schließen", command=about_tgtg.destroy + ) close_button.grid(row=2, column=1, padx=10, pady=10, sticky="ew") def update_credits(self): @@ -503,7 +619,9 @@ class PfandCalculator: about_update.grid_rowconfigure(2, weight=0) # Load and process image - image_path = os.path.join(os.getcwd(), "PfandApplication", "images", "versions", "updates.png") + image_path = os.path.join( + os.getcwd(), "PfandApplication", "images", "versions", "updates.png" + ) try: img = Image.open(image_path).convert("RGBA") @@ -521,7 +639,7 @@ class PfandCalculator: about_update.update_img = update_img img_label = tk.Label(about_update, image=update_img) - img_label.grid(row=0, column=0, columnspan=2, pady=(15, 5), sticky='n') + img_label.grid(row=0, column=0, columnspan=2, pady=(15, 5), sticky="n") except Exception as e: print(f"Fehler beim Laden des Bildes: {e}") @@ -536,17 +654,25 @@ class PfandCalculator: ), justify="left", anchor="center", - wraplength=600 + wraplength=600, + ) + label_update_app.grid( + row=1, column=0, columnspan=2, sticky="nsew", padx=10, pady=10 ) - label_update_app.grid(row=1, column=0, columnspan=2, sticky='nsew', padx=10, pady=10) # Buttons url = "https://github.com/ZockerKatze/pfand_PKG" - close_button = tk.Button(about_update, text="Schließen", command=about_update.destroy) + close_button = tk.Button( + about_update, text="Schließen", command=about_update.destroy + ) close_button.grid(row=2, column=0, padx=10, pady=10, sticky="ew") - open_repo_button = tk.Button(about_update, text="Öffne Update-Repository", command=lambda: webbrowser.open(url)) + open_repo_button = tk.Button( + about_update, + text="Öffne Update-Repository", + command=lambda: webbrowser.open(url), + ) open_repo_button.grid(row=2, column=1, padx=10, pady=10, sticky="ew") def uscan_credits(self): @@ -558,7 +684,9 @@ class PfandCalculator: about_uscan.grid_rowconfigure(0, weight=1) about_uscan.grid_rowconfigure(1, weight=0) - image_path = os.path.join(os.getcwd(), "PfandApplication", "images", "versions", "uscan.png") + image_path = os.path.join( + os.getcwd(), "PfandApplication", "images", "versions", "uscan.png" + ) try: img = Image.open(image_path).convert("RGBA") @@ -577,7 +705,7 @@ class PfandCalculator: about_uscan.uscan_img = uscan_img img_label = tk.Label(about_uscan, image=uscan_img) - img_label.grid(row=0, column=0, columnspan=2, pady=(15, 5), sticky='n') + img_label.grid(row=0, column=0, columnspan=2, pady=(15, 5), sticky="n") except Exception as e: print(f"Fehler beim Laden des Bildes: {e}") @@ -592,122 +720,221 @@ class PfandCalculator: "Beachte das µScan eine Kamera benötigt die mindestens 30FPS aufnehmen kann (Process-FPS können eingestellt werden!)" ), justify="left", - anchor="center" + anchor="center", ) label_uscan_app.grid(row=1, column=0, sticky="nsew", padx=10, pady=10) - close_button = tk.Button(about_uscan, text="Schließen", command=about_uscan.destroy) - close_button.grid(row=2, column=0, sticky='ew', padx=10, pady=(0, 10)) + close_button = tk.Button( + about_uscan, text="Schließen", command=about_uscan.destroy + ) + close_button.grid(row=2, column=0, sticky="ew", padx=10, pady=(0, 10)) def create_menu(self): self.menubar = tk.Menu(self.root) self.root.config(menu=self.menubar) - + # "Datei" Menu file_menu = tk.Menu(self.menubar, tearoff=0) self.menubar.add_cascade(label="Datei", menu=file_menu) - file_menu.add_command(label="Speichern", command=self.save_quantities, accelerator="Strg+S") - file_menu.add_command(label="Ordner öffnen", command=self.open_file_location, accelerator="Strg+O") - file_menu.add_command(label="Speicherdatei löschen", command=self.remove_save_file, accelerator="Strg+Shift+F1") + file_menu.add_command( + label="Speichern", command=self.save_quantities, accelerator="Strg+S" + ) + file_menu.add_command( + label="Ordner öffnen", command=self.open_file_location, accelerator="Strg+O" + ) + file_menu.add_command( + label="Speicherdatei löschen", + command=self.remove_save_file, + accelerator="Strg+Shift+F1", + ) file_menu.add_separator() - 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_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="Beenden", command=self.root.quit, accelerator="Strg+Q") + 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=lambda: self.create_credits(False), accelerator="Strg+F10") # Else this will autolaunch (wo lambda) + file_menu.add_command( + label="Über Programm", + command=lambda: self.create_credits(False), + accelerator="Strg+F10", + ) # Else this will autolaunch (wo lambda) # Deposit Menu deposit_menu = tk.Menu(self.menubar, tearoff=0) self.menubar.add_cascade(label="Pfand", menu=deposit_menu) - deposit_menu.add_command(label="Pfand Abgeben", command=self.quick_deposit, accelerator="Strg+D") - deposit_menu.add_command(label="Abgabe Historie", command=self.show_deposit_history, accelerator="Strg+H") + deposit_menu.add_command( + label="Pfand Abgeben", command=self.quick_deposit, accelerator="Strg+D" + ) + deposit_menu.add_command( + label="Abgabe Historie", + command=self.show_deposit_history, + accelerator="Strg+H", + ) deposit_menu.add_separator() - deposit_menu.add_command(label="Historie Exportieren (CSV)", command=self.export_history_csv, accelerator="Strg+E") - deposit_menu.add_command(label="Historie Löschen", command=self.clear_deposit_history, accelerator="Strg+Shift+F2") + deposit_menu.add_command( + label="Historie Exportieren (CSV)", + command=self.export_history_csv, + accelerator="Strg+E", + ) + deposit_menu.add_command( + label="Historie Löschen", + command=self.clear_deposit_history, + accelerator="Strg+Shift+F2", + ) # Scanner Menu scanner_menu = tk.Menu(self.menubar, tearoff=0) self.menubar.add_cascade(label="Scanner", menu=scanner_menu) - scanner_menu.add_command(label="Scanner öffnen", command=self.open_scanner_window, accelerator="Strg+B") + scanner_menu.add_command( + label="Scanner öffnen", + command=self.open_scanner_window, + accelerator="Strg+B", + ) scanner_menu.add_separator() - scanner_menu.add_command(label="Öffne µScan", command=launch_pfand_scanner, accelerator="Strg+Shift+B") #µScan - scanner_menu.add_command(label="Über µScan", command=self.uscan_credits) #µScan credits + scanner_menu.add_command( + label="Öffne µScan", + command=launch_pfand_scanner, + accelerator="Strg+Shift+B", + ) # µScan + scanner_menu.add_command( + label="Über µScan", command=self.uscan_credits + ) # µScan credits scanner_menu.add_separator() - scanner_menu.add_command(label="Barcodes Exportieren (CSV)", command=self.export_barcodes_csv, accelerator="Strg+Shift+E") + scanner_menu.add_command( + label="Barcodes Exportieren (CSV)", + command=self.export_barcodes_csv, + accelerator="Strg+Shift+E", + ) # Achivements Menu achievements_menu = tk.Menu(self.menubar, tearoff=0) self.menubar.add_cascade(label="Auszeichnungen", menu=achievements_menu) - achievements_menu.add_command(label="Auszeichnungen anzeigen", command=self.show_achievements, accelerator="Strg+F6") - achievements_menu.add_command(label="Auszeichnungen löschen", command=self.delete_achievements, accelerator="Strg+F7") - + achievements_menu.add_command( + label="Auszeichnungen anzeigen", + command=self.show_achievements, + accelerator="Strg+F6", + ) + achievements_menu.add_command( + label="Auszeichnungen löschen", + command=self.delete_achievements, + accelerator="Strg+F7", + ) + # Add custom products menu products_menu = tk.Menu(self.menubar, tearoff=0) self.menubar.add_cascade(label="Produkte", menu=products_menu) - products_menu.add_command(label="Produkt hinzufügen", command=self.show_add_product_window, accelerator="Strg+P") - products_menu.add_command(label="Produkte verwalten", command=self.show_manage_products_window, accelerator="Strg+Shift+P") + products_menu.add_command( + label="Produkt hinzufügen", + command=self.show_add_product_window, + accelerator="Strg+P", + ) + products_menu.add_command( + label="Produkte verwalten", + command=self.show_manage_products_window, + accelerator="Strg+Shift+P", + ) # TGTG Menu (used to not exist) - + tgtg_menu = tk.Menu(self.menubar, tearoff=0) self.menubar.add_cascade(label="TGTG", menu=tgtg_menu) - tgtg_menu.add_command(label="Öffne TGTG-OC", command=tgtg.start_tgtg, accelerator="Strg+F12") - tgtg_menu.add_command(label="Öffne KeyTool", command=tgtg_kt.ask_for_tokens, accelerator="Strg+F11") + tgtg_menu.add_command( + label="Öffne TGTG-OC", command=tgtg.start_tgtg, accelerator="Strg+F12" + ) + tgtg_menu.add_command( + label="Öffne KeyTool", + command=tgtg_kt.ask_for_tokens, + accelerator="Strg+F11", + ) tgtg_menu.add_separator() - tgtg_menu.add_command(label="Über TGTG", command=self.TGTG_credits) # No keybind , why tf would you need one anyway + tgtg_menu.add_command( + label="Über TGTG", command=self.TGTG_credits + ) # No keybind , why tf would you need one anyway update_menu = tk.Menu(self.menubar, tearoff=0) self.menubar.add_cascade(label="Updater", menu=update_menu) - update_menu.add_command(label="Öffne Updater", command=open_updater, accelerator="Strg+U") # Version (7.4.000 Updater Version) + update_menu.add_command( + label="Öffne Updater", command=open_updater, accelerator="Strg+U" + ) # Version (7.4.000 Updater Version) update_menu.add_separator() - update_menu.add_command(label="Über Updater", command=self.update_credits) # Also no keybind here, same reason as the tgtg one #V7.4.001 + update_menu.add_command( + label="Über Updater", command=self.update_credits + ) # Also no keybind here, same reason as the tgtg one #V7.4.001 # Manage Keybinds - self.root.bind('', lambda e: self.save_quantities()) - self.root.bind('', lambda e: self.open_file_location()) - self.root.bind('', lambda e: self.root.quit()) - self.root.bind('', lambda e: self.quick_deposit()) - self.root.bind('', lambda e: self.show_deposit_history()) - self.root.bind('', lambda e: self.export_history_csv()) - self.root.bind('', lambda e: self.open_scanner_window()) - self.root.bind('', lambda e: launch_pfand_scanner()) #µScan - self.root.bind('', lambda e: self.handle_shift_f1(e)) - self.root.bind('', lambda e: self.handle_shift_f2(e)) - self.root.bind('', lambda e: self.show_achievements()) - self.root.bind('', lambda e: self.delete_achievements()) - self.root.bind('', lambda e: tgtg.start_tgtg(self.root)) - self.root.bind('', lambda e: tgtg_kt.ask_for_tokens()) - self.root.bind('', lambda e: self.create_credits(False)) # True this will show future Icons - 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: self.recreate_widgets()) - self.root.bind('', lambda e: open_updater()) # New Update Feature (Version 7.4.000 UPDATER) + self.root.bind("", lambda e: self.save_quantities()) + self.root.bind("", lambda e: self.open_file_location()) + self.root.bind("", lambda e: self.root.quit()) + self.root.bind("", lambda e: self.quick_deposit()) + self.root.bind("", lambda e: self.show_deposit_history()) + self.root.bind("", lambda e: self.export_history_csv()) + self.root.bind("", lambda e: self.open_scanner_window()) + self.root.bind("", lambda e: launch_pfand_scanner()) # µScan + self.root.bind("", lambda e: self.handle_shift_f1(e)) + self.root.bind("", lambda e: self.handle_shift_f2(e)) + self.root.bind("", lambda e: self.show_achievements()) + self.root.bind("", lambda e: self.delete_achievements()) + self.root.bind("", lambda e: tgtg.start_tgtg(self.root)) + self.root.bind("", lambda e: tgtg_kt.ask_for_tokens()) + self.root.bind( + "", lambda e: self.create_credits(False) + ) # True this will show future Icons + 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: self.recreate_widgets()) + self.root.bind( + "", lambda e: open_updater() + ) # New Update Feature (Version 7.4.000 UPDATER) def open_file_location(self): current_dir = os.getcwd() - if os.name == 'nt': # Windows + if os.name == "nt": # Windows os.startfile(current_dir) else: # Linux/Mac try: - subprocess.run(['xdg-open', current_dir]) + subprocess.run(["xdg-open", current_dir]) except: - subprocess.run(['open', current_dir]) + subprocess.run(["open", current_dir]) def remove_save_file(self): - if os.path.exists('quantities.json'): - if messagebox.askyesno("Löschen bestätigen", "Sind Sie sicher, dass Sie die Speicherdatei löschen möchten?"): + if os.path.exists("quantities.json"): + if messagebox.askyesno( + "Löschen bestätigen", + "Sind Sie sicher, dass Sie die Speicherdatei löschen möchten?", + ): try: - os.remove('quantities.json') - messagebox.showinfo("Erfolg", "Speicherdatei wurde erfolgreich gelöscht!") + os.remove("quantities.json") + messagebox.showinfo( + "Erfolg", "Speicherdatei wurde erfolgreich gelöscht!" + ) self.quantities = {product: 0 for product in self.products} self.update_total() for widget in self.root.winfo_children(): @@ -718,46 +945,52 @@ class PfandCalculator: if isinstance(grandchild, ttk.Spinbox): grandchild.set("0") except Exception as e: - messagebox.showerror("Fehler", f"Datei konnte nicht gelöscht werden: {str(e)}") + messagebox.showerror( + "Fehler", f"Datei konnte nicht gelöscht werden: {str(e)}" + ) else: messagebox.showinfo("Info", "Keine Speicherdatei vorhanden.") def load_quantities(self): try: - with open('quantities.json', 'r') as f: + with open("quantities.json", "r") as f: self.quantities = json.load(f) except FileNotFoundError: self.quantities = {product: 0 for product in self.products} - + def save_quantities(self): try: - with open('quantities.json', 'w') as f: + with open("quantities.json", "w") as f: json.dump(self.quantities, f) messagebox.showinfo("Erfolg", "Mengen wurden erfolgreich gespeichert!") except Exception as e: - messagebox.showerror("Fehler", f"Fehler beim Speichern der Mengen: {str(e)}") - + messagebox.showerror( + "Fehler", f"Fehler beim Speichern der Mengen: {str(e)}" + ) + def create_widgets(self): main_frame = ttk.Frame(self.root) main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S)) - + for i, product in enumerate(self.products): frame = ttk.Frame(main_frame) frame.grid(row=0, column=i, padx=10, pady=5) - + image = self.load_image(product) if image: - self.images[product] = image + self.images[product] = image label = ttk.Label(frame, image=self.images[product]) label.grid(row=0, column=0, pady=5) else: - canvas = tk.Canvas(frame, width=100, height=100, bg='white') + canvas = tk.Canvas(frame, width=100, height=100, bg="white") canvas.grid(row=0, column=0, pady=5) canvas.create_text(50, 50, text=f"Kein {product}\nBild gefunden") - + ttk.Label(frame, text=product).grid(row=1, column=0, pady=2) - ttk.Label(frame, text=f"€{self.PRICES[product]:.2f}").grid(row=2, column=0, pady=2) - + ttk.Label(frame, text=f"€{self.PRICES[product]:.2f}").grid( + row=2, column=0, pady=2 + ) + quantity_var = tk.StringVar(value=str(self.quantities.get(product, 0))) spinbox = ttk.Spinbox( frame, @@ -765,21 +998,29 @@ class PfandCalculator: to=100, width=5, textvariable=quantity_var, - command=lambda p=product, v=quantity_var: self.update_quantity(p, v) + command=lambda p=product, v=quantity_var: self.update_quantity(p, v), ) spinbox.grid(row=3, column=0, pady=5) - + # Store spinbox reference self.spinboxes[product] = spinbox - - spinbox.bind('', lambda event, p=product, v=quantity_var: self.update_quantity(p, v)) - spinbox.bind('', lambda event, p=product, v=quantity_var: self.update_quantity(p, v)) - - self.total_label = ttk.Label(main_frame, text="Gesamt: €0.00", font=('TkDefaultFont', 10, 'bold')) + + spinbox.bind( + "", + lambda event, p=product, v=quantity_var: self.update_quantity(p, v), + ) + spinbox.bind( + "", + lambda event, p=product, v=quantity_var: self.update_quantity(p, v), + ) + + self.total_label = ttk.Label( + main_frame, text="Gesamt: €0.00", font=("TkDefaultFont", 10, "bold") + ) self.total_label.grid(row=1, column=0, columnspan=len(self.products), pady=10) - + self.update_total() - + def update_quantity(self, product, var, event=None): try: quantity = int(var.get()) @@ -787,25 +1028,29 @@ class PfandCalculator: self.update_total() except ValueError: var.set(str(self.quantities.get(product, 0))) - + def update_total(self): - total = sum(self.quantities[product] * self.PRICES[product] for product in self.products) # get total + total = sum( + self.quantities[product] * self.PRICES[product] for product in self.products + ) # get total self.total_label.config(text=f"Gesamt: €{total:.2f}") @staticmethod def load_deposit_history(): try: - with open('deposit_history.json', 'r') as f: + with open("deposit_history.json", "r") as f: return json.load(f) except FileNotFoundError: return [] def save_deposit_history(self): try: - with open('deposit_history.json', 'w') as f: + with open("deposit_history.json", "w") as f: json.dump(self.deposit_history, f) except Exception as e: - messagebox.showerror("Fehler", f"Fehler beim Speichern der Historie: {str(e)}") + messagebox.showerror( + "Fehler", f"Fehler beim Speichern der Historie: {str(e)}" + ) # Changed in Version 7.4.101 def show_deposit_history(self): @@ -825,23 +1070,23 @@ class PfandCalculator: all_items = set() for deposit in deposit_history: - all_items.update(deposit['quantities'].keys()) + all_items.update(deposit["quantities"].keys()) item_columns = sorted(all_items) - columns = ['Datum'] + item_columns + ['Gesamt'] + columns = ["Datum"] + item_columns + ["Gesamt"] - tree = ttk.Treeview(main_frame, columns=columns, show='headings') + tree = ttk.Treeview(main_frame, columns=columns, show="headings") for col in columns: - tree.heading(col, text=col, anchor='center') - width = 100 if col == 'Datum' else 80 - tree.column(col, width=width, anchor='center' if col != 'Gesamt' else 'e') + tree.heading(col, text=col, anchor="center") + width = 100 if col == "Datum" else 80 + tree.column(col, width=width, anchor="center" if col != "Gesamt" else "e") scrollbar = ttk.Scrollbar(main_frame, orient=tk.VERTICAL, command=tree.yview) tree.configure(yscrollcommand=scrollbar.set) - tree.grid(row=0, column=0, sticky='nsew') - scrollbar.grid(row=0, column=1, sticky='ns') + tree.grid(row=0, column=0, sticky="nsew") + scrollbar.grid(row=0, column=1, sticky="ns") main_frame.grid_columnconfigure(0, weight=1) main_frame.grid_rowconfigure(0, weight=1) @@ -850,33 +1095,35 @@ class PfandCalculator: total_amount = 0 for deposit in deposit_history: - quantities = deposit.get('quantities', {}) - row = [deposit.get('date', '')] + quantities = deposit.get("quantities", {}) + row = [deposit.get("date", "")] for item in item_columns: count = quantities.get(item, 0) row.append(count) totals[item] += count - amount = deposit.get('total', 0.0) + amount = deposit.get("total", 0.0) row.append(f"{amount:.2f}") total_amount += amount - tree.insert('', tk.END, values=row) + tree.insert("", tk.END, values=row) totals_frame = ttk.Frame(main_frame) - totals_frame.grid(row=1, column=0, sticky='ew', pady=(5, 0)) + totals_frame.grid(row=1, column=0, sticky="ew", pady=(5, 0)) - separator = ttk.Separator(main_frame, orient='horizontal') - separator.grid(row=2, column=0, sticky='ew', pady=2) + separator = ttk.Separator(main_frame, orient="horizontal") + separator.grid(row=2, column=0, sticky="ew", pady=2) - bold_font = ('TkDefaultFont', 9, 'bold') + bold_font = ("TkDefaultFont", 9, "bold") row = ["Gesamt:"] for item in item_columns: - row.append(f"{totals[item]} {item}") - row.append(f"€{total_amount:.2f}") + row.append(f"{totals[item]} {item}") + row.append(f"€{total_amount:.2f}") for idx, value in enumerate(row): - ttk.Label(totals_frame, text=value, font=bold_font).grid(row=0, column=idx, sticky='w', padx=5) + ttk.Label(totals_frame, text=value, font=bold_font).grid( + row=0, column=idx, sticky="w", padx=5 + ) - separator.grid(row=3, column=0, sticky='ew', pady=5) + separator.grid(row=3, column=0, sticky="ew", pady=5) def make_deposit(self): deposit_dialog = tk.Toplevel(self.root) @@ -886,19 +1133,27 @@ class PfandCalculator: deposit_dialog.grab_set() ttk.Label(deposit_dialog, text="Abgabe Datum:").pack(pady=5) - date_picker = DateEntry(deposit_dialog, width=12, background='darkblue', - foreground='white', borderwidth=2, locale='de_DE') + date_picker = DateEntry( + deposit_dialog, + width=12, + background="darkblue", + foreground="white", + borderwidth=2, + locale="de_DE", + ) date_picker.pack(pady=5) def confirm_deposit(): date = date_picker.get_date().strftime("%d.%m.%Y") - current_total = sum(self.quantities[product] * self.PRICES[product] - for product in self.products) - + current_total = sum( + self.quantities[product] * self.PRICES[product] + for product in self.products + ) + deposit_record = { - 'date': date, - 'quantities': dict(self.quantities), - 'total': current_total + "date": date, + "quantities": dict(self.quantities), + "total": current_total, } self.deposit_history.append(deposit_record) self.save_deposit_history() @@ -920,27 +1175,35 @@ class PfandCalculator: button_frame = ttk.Frame(deposit_dialog) button_frame.pack(pady=20) - ttk.Button(button_frame, text="Abgeben", command=confirm_deposit).pack(side=tk.LEFT, padx=5) - ttk.Button(button_frame, text="Abbrechen", command=deposit_dialog.destroy).pack(side=tk.LEFT, padx=5) + ttk.Button(button_frame, text="Abgeben", command=confirm_deposit).pack( + side=tk.LEFT, padx=5 + ) + ttk.Button(button_frame, text="Abbrechen", command=deposit_dialog.destroy).pack( + side=tk.LEFT, padx=5 + ) def quick_deposit(self): if sum(self.quantities.values()) == 0: messagebox.showinfo("Info", "Keine Mengen zum Abgeben vorhanden.") return - if messagebox.askyesno("Pfand Abgeben", "Möchten Sie den Pfand mit dem heutigen Datum abgeben?"): + if messagebox.askyesno( + "Pfand Abgeben", "Möchten Sie den Pfand mit dem heutigen Datum abgeben?" + ): current_date = datetime.now().strftime("%d.%m.%Y") - current_total = sum(self.quantities[product] * self.PRICES[product] - for product in self.products) - + current_total = sum( + self.quantities[product] * self.PRICES[product] + for product in self.products + ) + deposit_record = { - 'date': current_date, - 'quantities': dict(self.quantities), - 'total': current_total + "date": current_date, + "quantities": dict(self.quantities), + "total": current_total, } self.deposit_history.append(deposit_record) self.save_deposit_history() - + self.check_achievements() self.quantities = {product: 0 for product in self.products} @@ -968,27 +1231,27 @@ class PfandCalculator: file_path = filedialog.asksaveasfilename( defaultextension=".csv", filetypes=[("CSV Dateien", "*.csv")], - initialfile="pfand_historie.csv" + initialfile="pfand_historie.csv", ) - + if not file_path: return - with open(file_path, 'w', newline='', encoding='utf-8') as csvfile: - writer = csv.writer(csvfile, delimiter=';') - + with open(file_path, "w", newline="", encoding="utf-8") as csvfile: + writer = csv.writer(csvfile, delimiter=";") + # Create header with all products - header = ['Datum'] + self.products + ['Gesamt (€)'] + header = ["Datum"] + self.products + ["Gesamt (€)"] writer.writerow(header) - + for deposit in self.deposit_history: # Create row with all products - row = [deposit['date']] + row = [deposit["date"]] for product in self.products: - row.append(deposit['quantities'].get(product, 0)) + row.append(deposit["quantities"].get(product, 0)) row.append(f"{deposit['total']:.2f}") writer.writerow(row) - + messagebox.showinfo("Erfolg", "Historie wurde erfolgreich exportiert!") except Exception as e: messagebox.showerror("Fehler", f"Fehler beim Exportieren: {str(e)}") @@ -998,16 +1261,22 @@ class PfandCalculator: messagebox.showinfo("Info", "Keine Historie zum Löschen vorhanden.") return - if messagebox.askyesno("Löschen bestätigen", - "Sind Sie sicher, dass Sie die gesamte Abgabe-Historie löschen möchten?\n" - "Dieser Vorgang kann nicht rückgängig gemacht werden!"): + if messagebox.askyesno( + "Löschen bestätigen", + "Sind Sie sicher, dass Sie die gesamte Abgabe-Historie löschen möchten?\n" + "Dieser Vorgang kann nicht rückgängig gemacht werden!", + ): try: self.deposit_history = [] - if os.path.exists('deposit_history.json'): - os.remove('deposit_history.json') - messagebox.showinfo("Erfolg", "Abgabe-Historie wurde erfolgreich gelöscht!") + if os.path.exists("deposit_history.json"): + os.remove("deposit_history.json") + messagebox.showinfo( + "Erfolg", "Abgabe-Historie wurde erfolgreich gelöscht!" + ) except Exception as e: - messagebox.showerror("Fehler", f"Fehler beim Löschen der Historie: {str(e)}") + messagebox.showerror( + "Fehler", f"Fehler beim Löschen der Historie: {str(e)}" + ) def handle_shift_f1(self, event): if event.state & 0x1: @@ -1022,85 +1291,101 @@ class PfandCalculator: messagebox.showinfo("Info", "Keine Auszeichnungen zum Löschen vorhanden.") return - if messagebox.askyesno("Löschen bestätigen", - "Sind Sie sicher, dass Sie alle Auszeichnungen löschen möchten?\n" - "Dieser Vorgang kann nicht rückgängig gemacht werden!"): + if messagebox.askyesno( + "Löschen bestätigen", + "Sind Sie sicher, dass Sie alle Auszeichnungen löschen möchten?\n" + "Dieser Vorgang kann nicht rückgängig gemacht werden!", + ): try: for achievement in self.achievements.values(): achievement.unlocked = False achievement.unlock_date = None - - if os.path.exists('achievements.json'): - os.remove('achievements.json') - messagebox.showinfo("Erfolg", "Alle Auszeichnungen wurden erfolgreich gelöscht!") + + if os.path.exists("achievements.json"): + os.remove("achievements.json") + messagebox.showinfo( + "Erfolg", "Alle Auszeichnungen wurden erfolgreich gelöscht!" + ) except Exception as e: - messagebox.showerror("Fehler", f"Fehler beim Löschen der Auszeichnungen: {str(e)}") + messagebox.showerror( + "Fehler", f"Fehler beim Löschen der Auszeichnungen: {str(e)}" + ) def open_scanner_window(self): if self.scanner_window is None or not self.scanner_window.winfo_exists(): self.scanner_window = tk.Toplevel(self.root) self.scanner_window.title("Pfand Scanner") self.scanner_window.protocol("WM_DELETE_WINDOW", self.close_scanner_window) - + # Create frames for scanner layout self.camera_frame = ttk.Frame(self.scanner_window) self.camera_frame.pack(side="left", padx=10, pady=5) - + self.scanner_control_frame = ttk.Frame(self.scanner_window) self.scanner_control_frame.pack(side="left", padx=10, pady=5, fill="y") - + # Create camera label self.camera_label = ttk.Label(self.camera_frame) self.camera_label.pack() - + # Create focus control - focus_frame = ttk.LabelFrame(self.scanner_control_frame, text="Kamera Einstellungen") + focus_frame = ttk.LabelFrame( + self.scanner_control_frame, text="Kamera Einstellungen" + ) focus_frame.pack(pady=5, padx=5, fill="x") - + ttk.Label(focus_frame, text="Fokus:").pack(pady=2) - self.focus_slider = ttk.Scale(focus_frame, from_=0, to=255, orient="horizontal") + self.focus_slider = ttk.Scale( + focus_frame, from_=0, to=255, orient="horizontal" + ) self.focus_slider.set(0) self.focus_slider.pack(pady=2, padx=5, fill="x") - + self.autofocus_var = tk.BooleanVar(value=True) self.autofocus_check = ttk.Checkbutton( focus_frame, text="Autofokus", variable=self.autofocus_var, - command=self.toggle_autofocus + command=self.toggle_autofocus, ) self.autofocus_check.pack(pady=2) - + # Create image processing controls - process_frame = ttk.LabelFrame(self.scanner_control_frame, text="Bildverarbeitung") + process_frame = ttk.LabelFrame( + self.scanner_control_frame, text="Bildverarbeitung" + ) process_frame.pack(pady=5, padx=5, fill="x") - + ttk.Label(process_frame, text="Helligkeit:").pack(pady=2) - self.brightness_slider = ttk.Scale(process_frame, from_=0, to=100, orient="horizontal") + self.brightness_slider = ttk.Scale( + process_frame, from_=0, to=100, orient="horizontal" + ) self.brightness_slider.set(50) self.brightness_slider.pack(pady=2, padx=5, fill="x") - + ttk.Label(process_frame, text="Kontrast:").pack(pady=2) - self.contrast_slider = ttk.Scale(process_frame, from_=0, to=100, orient="horizontal") + self.contrast_slider = ttk.Scale( + process_frame, from_=0, to=100, orient="horizontal" + ) self.contrast_slider.set(50) self.contrast_slider.pack(pady=2, padx=5, fill="x") - + # Start/Stop button self.scan_button = ttk.Button( self.scanner_control_frame, text="Scannen Starten", - command=self.toggle_scanning + command=self.toggle_scanning, ) self.scan_button.pack(pady=10) - + # Initialize scan counter for achievements self.daily_scans = 0 self.total_scans = 0 self.last_scan_date = None - + # Queue for thread-safe communication self.queue = queue.Queue() - + # Set window size to match camera resolution self.scanner_window.geometry("1600x800") @@ -1117,16 +1402,16 @@ class PfandCalculator: def toggle_scanning(self): if not self.scanning: self.cap = cv2.VideoCapture(0) - + # Set optimal camera properties for performance self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280) self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720) self.cap.set(cv2.CAP_PROP_FPS, 30) # Request 30 FPS self.cap.set(cv2.CAP_PROP_BUFFERSIZE, 1) # Minimize buffer delay - + self.cap.set(cv2.CAP_PROP_AUTOFOCUS, 0) self.cap.set(cv2.CAP_PROP_FOCUS, 0) - + self.scanning = True self.scan_button.configure(text="Scannen Stoppen") self.process_video() @@ -1136,68 +1421,70 @@ class PfandCalculator: self.cap.release() self.cap = None self.scan_button.configure(text="Scannen Starten") - self.camera_label.configure(image='') + self.camera_label.configure(image="") def toggle_autofocus(self): if self.cap: if self.autofocus_var.get(): self.cap.set(cv2.CAP_PROP_AUTOFOCUS, 1) - self.focus_slider.state(['disabled']) + self.focus_slider.state(["disabled"]) else: self.cap.set(cv2.CAP_PROP_AUTOFOCUS, 0) - self.focus_slider.state(['!disabled']) + self.focus_slider.state(["!disabled"]) self.cap.set(cv2.CAP_PROP_FOCUS, self.focus_slider.get()) def adjust_image(self, frame): # This method is now only used for preview adjustments brightness = self.brightness_slider.get() / 50.0 - 1.0 contrast = self.contrast_slider.get() / 50.0 - + adjusted = cv2.convertScaleAbs(frame, alpha=contrast, beta=brightness * 127) return adjusted def process_video(self): if not self.scanning: return - + try: ret, frame = self.cap.read() if ret: if not self.autofocus_var.get(): self.cap.set(cv2.CAP_PROP_FOCUS, self.focus_slider.get()) - + # Resize frame for faster processing (720p is plenty for barcode detection) frame = cv2.resize(frame, (1280, 720)) - + # Only process every 3rd frame for barcode detection - if hasattr(self, 'frame_count'): + if hasattr(self, "frame_count"): self.frame_count += 1 else: self.frame_count = 0 - + if self.frame_count % 3 == 0: # Process every 3rd frame # Process in grayscale for better performance gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) barcodes = decode(gray) - + for barcode in barcodes: points = barcode.polygon if len(points) == 4: pts = np.array([(p.x, p.y) for p in points]) cv2.polylines(frame, [pts], True, (0, 255, 0), 2) - - barcode_data = barcode.data.decode('utf-8') + + barcode_data = barcode.data.decode("utf-8") if barcode_data not in self.scanned_barcodes: self.scanned_barcodes.add(barcode_data) - self.scanner_window.after(0, lambda d=barcode_data: self.handle_barcode(d)) - + self.scanner_window.after( + 0, lambda d=barcode_data: self.handle_barcode(d) + ) + # Convert and display frame cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA) img = Image.fromarray(cv2image) imgtk = ImageTk.PhotoImage(image=img) self.camera_label.imgtk = imgtk self.camera_label.configure(image=imgtk) - + if self.scanning: # Use a shorter delay for higher frame rate self.scanner_window.after(5, self.process_video) @@ -1212,47 +1499,61 @@ class PfandCalculator: verify_dialog.title("Pfand Symbol Überprüfung") verify_dialog.transient(self.scanner_window) verify_dialog.grab_set() - - ttk.Label(verify_dialog, text="Ist ein Pfand Symbol auf dem Produkt?").pack(pady=10) - + + ttk.Label(verify_dialog, text="Ist ein Pfand Symbol auf dem Produkt?").pack( + pady=10 + ) + def handle_verification(has_pfand): verify_dialog.destroy() if has_pfand: # Add barcode to history with timestamp and Pfand status - self.barcode_history.append({ - 'timestamp': datetime.now().strftime("%d.%m.%Y %H:%M:%S"), - 'barcode': barcode_data, - 'has_pfand': True - }) + self.barcode_history.append( + { + "timestamp": datetime.now().strftime("%d.%m.%Y %H:%M:%S"), + "barcode": barcode_data, + "has_pfand": True, + } + ) self.show_product_selection_dialog(barcode_data) else: # Add barcode to history with timestamp and Pfand status - self.barcode_history.append({ - 'timestamp': datetime.now().strftime("%d.%m.%Y %H:%M:%S"), - 'barcode': barcode_data, - 'has_pfand': False - }) + self.barcode_history.append( + { + "timestamp": datetime.now().strftime("%d.%m.%Y %H:%M:%S"), + "barcode": barcode_data, + "has_pfand": False, + } + ) self.scanned_barcodes.remove(barcode_data) - messagebox.showinfo("Kein Pfand", "Dieses Produkt hat kein Pfand Symbol.") - + messagebox.showinfo( + "Kein Pfand", "Dieses Produkt hat kein Pfand Symbol." + ) + button_frame = ttk.Frame(verify_dialog) button_frame.pack(pady=10) - ttk.Button(button_frame, text="Ja", command=lambda: handle_verification(True)).pack(side=tk.LEFT, padx=5) - ttk.Button(button_frame, text="Nein", command=lambda: handle_verification(False)).pack(side=tk.LEFT, padx=5) + ttk.Button( + button_frame, text="Ja", command=lambda: handle_verification(True) + ).pack(side=tk.LEFT, padx=5) + ttk.Button( + button_frame, text="Nein", command=lambda: handle_verification(False) + ).pack(side=tk.LEFT, padx=5) def show_product_selection_dialog(self, barcode_data): dialog = tk.Toplevel(self.scanner_window) dialog.title("Barcode Erkannt") dialog.transient(self.scanner_window) dialog.grab_set() - + ttk.Label(dialog, text=f"Barcode erkannt: {barcode_data}").pack(pady=10) ttk.Label(dialog, text="Produkttyp auswählen:").pack(pady=5) - + product_var = tk.StringVar() for product in self.products: - ttk.Radiobutton(dialog, text=product, variable=product_var, value=product).pack() - + ttk.Radiobutton( + dialog, text=product, variable=product_var, value=product + ).pack() + def confirm(): selected_product = product_var.get() if selected_product: @@ -1260,11 +1561,13 @@ class PfandCalculator: # Update quantity current_qty = self.quantities.get(selected_product, 0) self.quantities[selected_product] = current_qty + 1 - print(f"Neue Menge für {selected_product}: {self.quantities[selected_product]}") # Debug print - + print( + f"Neue Menge für {selected_product}: {self.quantities[selected_product]}" + ) # Debug print + # Update scan counters and check achievements self.update_scan_achievements() - + # Force immediate UI update def do_update(): try: @@ -1272,68 +1575,75 @@ class PfandCalculator: spinbox = self.spinboxes[selected_product] spinbox.set(str(self.quantities[selected_product])) spinbox.update() # Force the spinbox to update - + # Update the total self.update_total() self.root.update_idletasks() # Force the entire UI to update - + # Save the quantities self.save_quantities() print("UI Update und Speicherung abgeschlossen") # Debug print except Exception as e: print(f"Fehler beim UI Update: {e}") - + # Schedule the update for the next event loop iteration self.root.after(1, do_update) dialog.destroy() - + def skip(): self.scanned_barcodes.remove(barcode_data) dialog.destroy() - + button_frame = ttk.Frame(dialog) button_frame.pack(pady=10) - ttk.Button(button_frame, text="Hinzufügen", command=confirm).pack(side=tk.LEFT, padx=5) - ttk.Button(button_frame, text="Überspringen", command=skip).pack(side=tk.LEFT, padx=5) + ttk.Button(button_frame, text="Hinzufügen", command=confirm).pack( + side=tk.LEFT, padx=5 + ) + ttk.Button(button_frame, text="Überspringen", command=skip).pack( + side=tk.LEFT, padx=5 + ) def update_scan_achievements(self): current_date = datetime.now().strftime("%Y-%m-%d") - + # Update daily scan counter if self.last_scan_date != current_date: self.daily_scans = 1 self.last_scan_date = current_date else: self.daily_scans += 1 - + # Update total scan counter self.total_scans += 1 - + # Check scan-related achievements achievements_to_check = { 1: "first_scan", 50: "scans_50", 100: "scans_100", - 500: "scans_500" + 500: "scans_500", } - + # Check total scans achievements for count, achievement_key in achievements_to_check.items(): - if self.total_scans == count and not self.achievements[achievement_key].unlocked: + if ( + self.total_scans == count + and not self.achievements[achievement_key].unlocked + ): self.unlock_achievement(achievement_key) self.save_achievements() - + # Check daily scan achievements - daily_achievements = { - 10: "daily_10", - 25: "daily_25" - } - + daily_achievements = {10: "daily_10", 25: "daily_25"} + for count, achievement_key in daily_achievements.items(): - if self.daily_scans == count and not self.achievements[achievement_key].unlocked: + if ( + self.daily_scans == count + and not self.achievements[achievement_key].unlocked + ): self.unlock_achievement(achievement_key) self.save_achievements() - + # Save the updated scan counts self.save_quantities() # This ensures we don't lose progress @@ -1346,8 +1656,11 @@ class PfandCalculator: if isinstance(frame, ttk.Frame): # Find the product this frame represents for widget in frame.winfo_children(): - if isinstance(widget, ttk.Label) and widget.cget('text') in self.products: - product = widget.cget('text') + if ( + isinstance(widget, ttk.Label) + and widget.cget("text") in self.products + ): + product = widget.cget("text") current_qty = self.quantities.get(product, 0) # Find and update the spinbox for w in frame.winfo_children(): @@ -1355,12 +1668,12 @@ class PfandCalculator: w.set(str(current_qty)) w.update() break - + # Update the total self.update_total() except Exception as e: print(f"Error updating UI: {e}") - + # Ensure updates happen in the main thread if threading.current_thread() is threading.main_thread(): update_spinboxes() @@ -1381,39 +1694,51 @@ class PfandCalculator: file_path = filedialog.asksaveasfilename( defaultextension=".csv", filetypes=[("CSV Dateien", "*.csv")], - initialfile="barcode_historie.csv" + initialfile="barcode_historie.csv", ) - + if not file_path: return - with open(file_path, 'w', newline='', encoding='utf-8') as csvfile: - writer = csv.writer(csvfile, delimiter=';') - + with open(file_path, "w", newline="", encoding="utf-8") as csvfile: + writer = csv.writer(csvfile, delimiter=";") + # Write header - writer.writerow(['Datum', 'Barcode', 'Hat Pfand']) - + writer.writerow(["Datum", "Barcode", "Hat Pfand"]) + # Write barcode history for entry in self.barcode_history: - writer.writerow([ - entry['timestamp'], - entry['barcode'], - 'Ja' if entry['has_pfand'] else 'Nein' - ]) - - messagebox.showinfo("Erfolg", "Barcode Historie wurde erfolgreich exportiert!") + writer.writerow( + [ + entry["timestamp"], + entry["barcode"], + "Ja" if entry["has_pfand"] else "Nein", + ] + ) + + messagebox.showinfo( + "Erfolg", "Barcode Historie wurde erfolgreich exportiert!" + ) except Exception as e: messagebox.showerror("Fehler", f"Fehler beim Exportieren: {str(e)}") def load_products(self): try: - with open('products.json', 'r') as f: + with open("products.json", "r") as f: data = json.load(f) - self.products = data.get('products', []) - self.PRICES = data.get('prices', {}) + self.products = data.get("products", []) + self.PRICES = data.get("prices", {}) except FileNotFoundError: # Default products if no JSON exists - self.products = ["Flaschen", "Bierflasche", "Kasten", "Dose", "Plastikflasche", "Monster", "Joghurt Glas"] + self.products = [ + "Flaschen", + "Bierflasche", + "Kasten", + "Dose", + "Plastikflasche", + "Monster", + "Joghurt Glas", + ] self.PRICES = { "Flaschen": 0.25, "Bierflasche": 0.20, @@ -1427,14 +1752,13 @@ class PfandCalculator: def save_products(self): try: - data = { - 'products': self.products, - 'prices': self.PRICES - } - with open('products.json', 'w') as f: + data = {"products": self.products, "prices": self.PRICES} + with open("products.json", "w") as f: json.dump(data, f) except Exception as e: - messagebox.showerror("Fehler", f"Fehler beim Speichern der Produkte: {str(e)}") + messagebox.showerror( + "Fehler", f"Fehler beim Speichern der Produkte: {str(e)}" + ) def show_add_product_window(self): dialog = tk.Toplevel(self.root) @@ -1445,57 +1769,69 @@ class PfandCalculator: # Product name name_frame = ttk.Frame(dialog) - name_frame.pack(fill='x', padx=10, pady=5) - ttk.Label(name_frame, text="Produktname:").pack(side='left') + name_frame.pack(fill="x", padx=10, pady=5) + ttk.Label(name_frame, text="Produktname:").pack(side="left") name_var = tk.StringVar() name_entry = ttk.Entry(name_frame, textvariable=name_var) - name_entry.pack(side='left', fill='x', expand=True, padx=5) + name_entry.pack(side="left", fill="x", expand=True, padx=5) # Deposit amount deposit_frame = ttk.Frame(dialog) - deposit_frame.pack(fill='x', padx=10, pady=5) - ttk.Label(deposit_frame, text="Pfandbetrag (€):").pack(side='left') + deposit_frame.pack(fill="x", padx=10, pady=5) + ttk.Label(deposit_frame, text="Pfandbetrag (€):").pack(side="left") deposit_var = tk.StringVar() deposit_entry = ttk.Entry(deposit_frame, textvariable=deposit_var) - deposit_entry.pack(side='left', fill='x', expand=True, padx=5) + deposit_entry.pack(side="left", fill="x", expand=True, padx=5) # Image selection image_frame = ttk.Frame(dialog) - image_frame.pack(fill='x', padx=10, pady=5) - ttk.Label(image_frame, text="Bild:").pack(side='left') + image_frame.pack(fill="x", padx=10, pady=5) + ttk.Label(image_frame, text="Bild:").pack(side="left") image_path_var = tk.StringVar() image_entry = ttk.Entry(image_frame, textvariable=image_path_var) - image_entry.pack(side='left', fill='x', expand=True, padx=5) - ttk.Button(image_frame, text="Durchsuchen", command=lambda: self.select_image(image_path_var)).pack(side='left') + image_entry.pack(side="left", fill="x", expand=True, padx=5) + ttk.Button( + image_frame, + text="Durchsuchen", + command=lambda: self.select_image(image_path_var), + ).pack(side="left") def add_product(): name = name_var.get().strip() try: - deposit = float(deposit_var.get().replace(',', '.')) + deposit = float(deposit_var.get().replace(",", ".")) except ValueError: - messagebox.showerror("Fehler", "Bitte geben Sie einen gültigen Pfandbetrag ein.") + messagebox.showerror( + "Fehler", "Bitte geben Sie einen gültigen Pfandbetrag ein." + ) return if not name: - messagebox.showerror("Fehler", "Bitte geben Sie einen Produktnamen ein.") + messagebox.showerror( + "Fehler", "Bitte geben Sie einen Produktnamen ein." + ) return if name in self.products: - messagebox.showerror("Fehler", "Ein Produkt mit diesem Namen existiert bereits.") + messagebox.showerror( + "Fehler", "Ein Produkt mit diesem Namen existiert bereits." + ) return image_path = image_path_var.get() if image_path: try: # Create images directory if it doesn't exist - if not os.path.exists('PfandApplication/images'): - os.makedirs('images') + if not os.path.exists("PfandApplication/images"): + os.makedirs("images") # Copy and rename the image new_image_path = f"PfandApplication/images/{name.lower()}.png" shutil.copy2(image_path, new_image_path) except Exception as e: - messagebox.showerror("Fehler", f"Fehler beim Kopieren des Bildes: {str(e)}") + messagebox.showerror( + "Fehler", f"Fehler beim Kopieren des Bildes: {str(e)}" + ) return # Add the new product @@ -1535,60 +1871,64 @@ class PfandCalculator: # Create main container with two columns main_container = ttk.Frame(dialog) - main_container.pack(fill='both', expand=True, padx=10, pady=5) + main_container.pack(fill="both", expand=True, padx=10, pady=5) # Left column for product list left_frame = ttk.Frame(main_container) - left_frame.pack(side='left', fill='both', expand=True, padx=(0, 5)) + left_frame.pack(side="left", fill="both", expand=True, padx=(0, 5)) # Right column for add/edit product right_frame = ttk.LabelFrame(main_container, text="Produkt hinzufügen") - right_frame.pack(side='right', fill='both', expand=True, padx=(5, 0)) + right_frame.pack(side="right", fill="both", expand=True, padx=(5, 0)) # Create treeview in left frame - tree = ttk.Treeview(left_frame, columns=('Name', 'Pfand'), show='headings') - tree.heading('Name', text='Name') - tree.heading('Pfand', text='Pfand (€)') - tree.pack(fill='both', expand=True) + tree = ttk.Treeview(left_frame, columns=("Name", "Pfand"), show="headings") + tree.heading("Name", text="Name") + tree.heading("Pfand", text="Pfand (€)") + tree.pack(fill="both", expand=True) # Add scrollbar for treeview - scrollbar = ttk.Scrollbar(left_frame, orient='vertical', command=tree.yview) - scrollbar.pack(side='right', fill='y') + scrollbar = ttk.Scrollbar(left_frame, orient="vertical", command=tree.yview) + scrollbar.pack(side="right", fill="y") tree.configure(yscrollcommand=scrollbar.set) # Populate treeview for product in self.products: - tree.insert('', 'end', values=(product, f"{self.PRICES[product]:.2f}")) + tree.insert("", "end", values=(product, f"{self.PRICES[product]:.2f}")) # Add product form in right frame # Product name name_frame = ttk.Frame(right_frame) - name_frame.pack(fill='x', padx=10, pady=5) - ttk.Label(name_frame, text="Produktname:").pack(side='left') + name_frame.pack(fill="x", padx=10, pady=5) + ttk.Label(name_frame, text="Produktname:").pack(side="left") name_var = tk.StringVar() name_entry = ttk.Entry(name_frame, textvariable=name_var) - name_entry.pack(side='left', fill='x', expand=True, padx=5) + name_entry.pack(side="left", fill="x", expand=True, padx=5) # Deposit amount deposit_frame = ttk.Frame(right_frame) - deposit_frame.pack(fill='x', padx=10, pady=5) - ttk.Label(deposit_frame, text="Pfandbetrag (€):").pack(side='left') + deposit_frame.pack(fill="x", padx=10, pady=5) + ttk.Label(deposit_frame, text="Pfandbetrag (€):").pack(side="left") deposit_var = tk.StringVar() deposit_entry = ttk.Entry(deposit_frame, textvariable=deposit_var) - deposit_entry.pack(side='left', fill='x', expand=True, padx=5) + deposit_entry.pack(side="left", fill="x", expand=True, padx=5) # Image selection with preview image_frame = ttk.Frame(right_frame) - image_frame.pack(fill='x', padx=10, pady=5) - ttk.Label(image_frame, text="Bild:").pack(side='left') + image_frame.pack(fill="x", padx=10, pady=5) + ttk.Label(image_frame, text="Bild:").pack(side="left") image_path_var = tk.StringVar() image_entry = ttk.Entry(image_frame, textvariable=image_path_var) - image_entry.pack(side='left', fill='x', expand=True, padx=5) - ttk.Button(image_frame, text="Durchsuchen", command=lambda: self.select_image(image_path_var, preview_label)).pack(side='left') + image_entry.pack(side="left", fill="x", expand=True, padx=5) + ttk.Button( + image_frame, + text="Durchsuchen", + command=lambda: self.select_image(image_path_var, preview_label), + ).pack(side="left") # Image preview preview_frame = ttk.Frame(right_frame) - preview_frame.pack(fill='x', padx=10, pady=5) + preview_frame.pack(fill="x", padx=10, pady=5) preview_label = ttk.Label(preview_frame) preview_label.pack() @@ -1615,31 +1955,39 @@ class PfandCalculator: def add_product(): name = name_var.get().strip() try: - deposit = float(deposit_var.get().replace(',', '.')) + deposit = float(deposit_var.get().replace(",", ".")) except ValueError: - messagebox.showerror("Fehler", "Bitte geben Sie einen gültigen Pfandbetrag ein.") + messagebox.showerror( + "Fehler", "Bitte geben Sie einen gültigen Pfandbetrag ein." + ) return if not name: - messagebox.showerror("Fehler", "Bitte geben Sie einen Produktnamen ein.") + messagebox.showerror( + "Fehler", "Bitte geben Sie einen Produktnamen ein." + ) return if name in self.products: - messagebox.showerror("Fehler", "Ein Produkt mit diesem Namen existiert bereits.") + messagebox.showerror( + "Fehler", "Ein Produkt mit diesem Namen existiert bereits." + ) return image_path = image_path_var.get() if image_path: try: # Create images directory if it doesn't exist - if not os.path.exists('PfandApplication/images'): - os.makedirs('images') + if not os.path.exists("PfandApplication/images"): + os.makedirs("images") # Copy and rename the image new_image_path = f"PfandApplication/images/{name.lower()}.png" shutil.copy2(image_path, new_image_path) except Exception as e: - messagebox.showerror("Fehler", f"Fehler beim Kopieren des Bildes: {str(e)}") + messagebox.showerror( + "Fehler", f"Fehler beim Kopieren des Bildes: {str(e)}" + ) return # Add the new product @@ -1648,14 +1996,14 @@ class PfandCalculator: self.save_products() # Update treeview - tree.insert('', 'end', values=(name, f"{deposit:.2f}")) + tree.insert("", "end", values=(name, f"{deposit:.2f}")) tree.yview_moveto(1) # Scroll to the bottom to show the new item # Clear form name_var.set("") deposit_var.set("") image_path_var.set("") - preview_label.configure(image='') + preview_label.configure(image="") # Update the main window UI self.recreate_widgets() @@ -1666,14 +2014,16 @@ class PfandCalculator: messagebox.showwarning("Warnung", "Bitte wählen Sie ein Produkt aus.") return - if messagebox.askyesno("Bestätigen", "Möchten Sie das ausgewählte Produkt wirklich löschen?"): + if messagebox.askyesno( + "Bestätigen", "Möchten Sie das ausgewählte Produkt wirklich löschen?" + ): item = tree.item(selected[0]) - product_name = item['values'][0] - + product_name = item["values"][0] + # Remove from lists self.products.remove(product_name) del self.PRICES[product_name] - + # Delete image if exists image_path = f"PfandApplication/images/{product_name.lower()}.png" if os.path.exists(image_path): @@ -1689,49 +2039,58 @@ class PfandCalculator: # Add buttons button_frame = ttk.Frame(right_frame) - button_frame.pack(fill='x', padx=10, pady=10) - ttk.Button(button_frame, text="Hinzufügen", command=add_product).pack(side='left', padx=5) - ttk.Button(button_frame, text="Löschen", command=delete_product).pack(side='left', padx=5) + button_frame.pack(fill="x", padx=10, pady=10) + ttk.Button(button_frame, text="Hinzufügen", command=add_product).pack( + side="left", padx=5 + ) + ttk.Button(button_frame, text="Löschen", command=delete_product).pack( + side="left", padx=5 + ) # Bind image selection to preview update - image_path_var.trace_add('write', lambda *args: update_preview(image_path_var.get())) + image_path_var.trace_add( + "write", lambda *args: update_preview(image_path_var.get()) + ) def recreate_widgets(self): # Clear existing widgets for widget in self.root.winfo_children(): widget.destroy() - + # Recreate menu self.create_menu() - + # Reload quantities self.load_quantities() - + # Recreate main widgets self.create_widgets() @staticmethod def launch(check_for_update) -> None: - root = tk.Tk() - app = PfandCalculator(root) + root = tk.Tk() + app = PfandCalculator(root) - #Icon (Version Pineapple | not really sure if this works yet!) - #TODO: Check if this shit works (On Windows and Linux) ; This works checked as of 10 JUN - icon_path = os.path.join(os.getcwd(), "PfandApplication", "images", "versions", "pineapple.png") - ico = Image.open(icon_path) - photo = ImageTk.PhotoImage(ico) - root.iconphoto(False, photo) + # Icon (Version Pineapple | not really sure if this works yet!) + # TODO: Check if this shit works (On Windows and Linux) ; This works checked as of 10 JUN + icon_path = os.path.join( + os.getcwd(), "PfandApplication", "images", "versions", "pineapple.png" + ) + ico = Image.open(icon_path) + photo = ImageTk.PhotoImage(ico) + root.iconphoto(False, photo) + + if check_for_update is None: # If it's None then also pass (acts like False) + pass + + elif not check_for_update: # If it isn't True pass + pass + + else: # If is True then call the silent updater + root.after(1, run_silent_update) + + root.mainloop() - if check_for_update is None: # If it's None then also pass (acts like False) - pass - - elif not check_for_update: # If it isn't True pass - pass - - else: # If is True then call the silent updater - root.after(1, run_silent_update) - - root.mainloop() - -if __name__ == "__main__": PfandCalculator.launch(True) +if __name__ == "__main__": + PfandCalculator.launch(True) diff --git a/PfandApplication/todo/main.py b/PfandApplication/todo/main.py index 4fb8104..6e1f539 100644 --- a/PfandApplication/todo/main.py +++ b/PfandApplication/todo/main.py @@ -1,17 +1,24 @@ class todo: def __init__(self): -#------------------------------------------------------------------------------------------------------------------# - self.todo : str = """ + # ------------------------------------------------------------------------------------------------------------------# + self.todo: str = """ TODO: - [] main.py@433 - fix this to actually load the Todo List cause currently its dumb as fuck. - - Do this tmrw 11.JUN.25! easy task. at least it should be. - [] main.py@GENERAL - refactor to make the ChatGPT Code actually readable. - [] @Project_Structure - Fix this shit + [X] main.py@433 - fix this to actually load the Todo List cause currently its dumb as fuck. + - Do this tmrw 11.JUN.25! easy task. at least it should be. + [] main.py@GENERAL - refactor to make the ChatGPT Code actually readable. + [] @Project_Structure - Fix this shit """ -#------------------------------------------------------------------------------------------------------------------# - self.pineapple=""" + # ------------------------------------------------------------------------------------------------------------------# + self.archived_todo: str = """ +archived_todo list: + [X] main.py@433 - fix this to actually load the Todo List cause currently its dumb as fuck. + - Do this tmrw 11.JUN.25! easy task. at least it should be. + + """ + # ------------------------------------------------------------------------------------------------------------------# + self.pineapple = """ ⠀⠀⠀⠀⠀⢀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⡿⠛⣷⡄⠀⠀⠀⠀⠀⢀⣀⣤⣤⣶⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⠀⠀⠀⠀⠀⠘⠻⣿⣿⢶⣤⣀⠀⠀⠀⢀⣾⠟⠀⠀⠘⢿⡆⠀⣠⣴⠿⣻⣿⠟⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⠀⠀⠀⠀⠀⠀⠀⠀⠻⣷⡈⠻⣷⣄⠀⣼⡟⠀⠀⠀⠀⠸⣷⣼⠟⠁⣴⠿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ @@ -51,13 +58,15 @@ TODO: ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠻⠷⣦⣄⣀⣉⣻⣶⢴⣞⣋⣠⣴⡶⠟⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠉⠛⠛⠛⠉⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ """ -#------------------------------------------------------------------------------------------------------------------# - + + # ------------------------------------------------------------------------------------------------------------------# + # This Project is certainly older than mucapy , But still i declare types now. in todo code xD # Anyways. This function maybe needs fixing. due too toodoo bug (bug1) def load_todo(self) -> str: return self.todo - + # toodoo bug may also reside here. idk -todo_instance = todo() \ No newline at end of file +todo_instance = todo() +