updated some stuff (not worthy of a vb!)

This commit is contained in:
rattatwinko
2025-04-17 18:49:33 +02:00
parent e3e581ccd8
commit 7a531dc92a
5 changed files with 179 additions and 146 deletions

View File

@@ -16,7 +16,7 @@ import numpy as np
import shutil import shutil
# Local Dependencies # 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.pfand_scanner import launch_pfand_scanner
from PfandApplication.updater import open_updater as open_updater, run_silent_update from PfandApplication.updater import open_updater as open_updater, run_silent_update
from PfandApplication.tgtg_orderchecker import main as tgtg from PfandApplication.tgtg_orderchecker import main as tgtg
@@ -33,6 +33,7 @@ class Achievement:
class PfandCalculator: class PfandCalculator:
def __init__(self, root): def __init__(self, root):
self.achievement_image_gray = None
self.root = root self.root = root
self.root.title("Österreichischer Pfandrechner") self.root.title("Österreichischer Pfandrechner")
@@ -63,7 +64,8 @@ class PfandCalculator:
self.achievement_image = self.load_achievement_image() self.achievement_image = self.load_achievement_image()
def load_image(self, product_name): @staticmethod
def load_image(product_name):
try: try:
# Use Flaschen icon for Bierflasche # Use Flaschen icon for Bierflasche
if product_name == "Bierflasche": if product_name == "Bierflasche":
@@ -115,7 +117,8 @@ class PfandCalculator:
print(f"Error loading achievement image: {e}") print(f"Error loading achievement image: {e}")
return None return None
def initialize_achievements(self): @staticmethod
def initialize_achievements():
return { return {
"each_100": Achievement("Krass, Weiter So!", "Du hast bis jetzt 100 von jedem Element gesammelt!", "each_element", 100), "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_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="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="Updater", command=open_updater, accelerator="Strg+U") # Added this to the File Menu too!
file_menu.add_separator() 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_command(label="Beenden", command=self.root.quit, accelerator="Strg+Q")
file_menu.add_separator() file_menu.add_separator()
file_menu.add_command(label="Über Programm", command=self.create_credits, accelerator="Strg+F10") file_menu.add_command(label="Über Programm", command=self.create_credits, accelerator="Strg+F10")
@@ -538,7 +541,7 @@ class PfandCalculator:
self.root.bind('<Control-E>', lambda e: self.export_barcodes_csv() if e.state & 0x1 else self.export_history_csv()) self.root.bind('<Control-E>', lambda e: self.export_barcodes_csv() if e.state & 0x1 else self.export_history_csv())
self.root.bind('<Control-p>', lambda e: self.show_add_product_window()) self.root.bind('<Control-p>', lambda e: self.show_add_product_window())
self.root.bind('<Control-P>', lambda e: self.show_manage_products_window() if e.state & 0x1 else self.show_add_product_window()) self.root.bind('<Control-P>', lambda e: self.show_manage_products_window() if e.state & 0x1 else self.show_add_product_window())
self.root.bind('<Control-l>', lambda e: WIKI.select_file()) self.root.bind('<Control-l>', lambda e: wiki.select_file())
self.root.bind('<Control-r>', lambda e: self.recreate_widgets()) self.root.bind('<Control-r>', lambda e: self.recreate_widgets())
self.root.bind('<Control-u>', lambda e: open_updater()) # New Update Feature (Version 7.4.000 UPDATER) self.root.bind('<Control-u>', lambda e: open_updater()) # New Update Feature (Version 7.4.000 UPDATER)
@@ -1564,12 +1567,14 @@ class PfandCalculator:
root = tk.Tk() root = tk.Tk()
app = PfandCalculator(root) app = PfandCalculator(root)
if check_for_update == True: if check_for_update is None:
root.after(1, run_silent_update) # Run uc on start (1s delay) => updater.py module || UNCOMMENT IN PROD root.after(500, root.destroy) # We do a lil bit of Trolling here
else: elif not check_for_update:
pass pass
else:
root.after(1, run_silent_update)
root.mainloop() root.mainloop()
if __name__ == "__main__": # Run AutoUpdates by default
PfandCalculator.launch(True) if __name__ == "__main__": PfandCalculator.launch(True)

View File

@@ -16,10 +16,10 @@ class TGTGOrdersApp:
self.notebook.pack(fill="both", expand=True) self.notebook.pack(fill="both", expand=True)
self.orders_tab = tk.Frame(self.notebook, bg="#ffffff") 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.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 = 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.log_text.pack(fill="both", expand=True, padx=10, pady=10)
@@ -30,12 +30,12 @@ class TGTGOrdersApp:
self.menu = Menu(self.parent) self.menu = Menu(self.parent)
self.parent.config(menu=self.menu) self.parent.config(menu=self.menu)
self.filemenu = Menu(self.menu) self.filemenu = Menu(self.menu)
self.menu.add_cascade(label="File", menu=self.filemenu) self.menu.add_cascade(label="Datei", menu=self.filemenu)
self.filemenu.add_command(label="Exit", command=self.exit_applet) self.filemenu.add_command(label="Beenden", command=self.exit_applet)
self.filemenu.add_command(label="Refetch", command=self.display_orders) self.filemenu.add_command(label="Aktualisieren", command=self.display_orders)
self.filemenu.add_command(label="Save Log", command=self.save_log) self.filemenu.add_command(label="Protokoll speichern", command=self.save_log)
self.filemenu.add_separator() 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) self.parent.after(1000, self.on_startup)
@@ -44,62 +44,60 @@ class TGTGOrdersApp:
self.log_text.insert(tk.END, f"{timestamp} - {message}\n") self.log_text.insert(tk.END, f"{timestamp} - {message}\n")
self.log_text.yview(tk.END) self.log_text.yview(tk.END)
def format_time(self, iso_time): @staticmethod
def format_time(iso_time):
try: try:
dt = datetime.fromisoformat(iso_time.replace("Z", "+00:00")) dt = datetime.fromisoformat(iso_time.replace("Z", "+00:00"))
local_time = dt.astimezone() local_time = dt.astimezone()
return local_time.strftime("%H:%M") return local_time.strftime("%H:%M")
except ValueError: except ValueError:
return "Unknown Error!" return "Unbekannter Fehler!"
def fetch_orders(self): def fetch_orders(self):
self.log_message("[ INFO ]: Fetching orders...") self.log_message("[ INFO ]: Bestellungen werden abgerufen...")
try: try:
active_orders = client.get_active() active_orders = client.get_active()
if not isinstance(active_orders, dict) or "orders" not in active_orders: 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", []) orders_list = active_orders.get("orders", [])
except Exception as e: except Exception as e:
self.log_message(f"[ ERROR ]: Error fetching active orders: {e}") self.log_message(f"[ FEHLER ]: Fehler beim Abrufen aktiver Bestellungen: {e}")
messagebox.showerror("Error", f"Error fetching active orders: {e}") messagebox.showerror("Fehler", f"Fehler beim Abrufen aktiver Bestellungen: {e}")
return [] return []
orders_data = [] orders_data = []
for order in orders_list: for order in orders_list:
try: try:
order_info = { order_info = {
"name": order.get("item_name", "Unknown"), "name": order.get("item_name", "Unbekannt"),
"store_name": order.get("store_name", "Unknown"), "store_name": order.get("store_name", "Unbekannt"),
"address": order.get("pickup_location", {}).get("address", {}).get("address_line", "Unknown"), "address": order.get("pickup_location", {}).get("address", {}).get("address_line", "Unbekannt"),
"quantity": order.get("quantity", 1), "quantity": order.get("quantity", 1),
"price": order.get("total_price", {}).get("minor_units", 0) / (10 ** order.get("total_price", {}).get("decimals", 2)), "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"), "currency": order.get("total_price", {}).get("code", "Unbekannt"),
"payment_method": order.get("payment_method_display_name", "Unknown"), "payment_method": order.get("payment_method_display_name", "Unbekannt"),
"pickup_window": { "pickup_window": {
"start": self.format_time(order.get("pickup_interval", {}).get("start", "Unknown")), "start": self.format_time(order.get("pickup_interval", {}).get("start", "Unbekannt")),
"end": self.format_time(order.get("pickup_interval", {}).get("end", "Unknown")) "end": self.format_time(order.get("pickup_interval", {}).get("end", "Unbekannt"))
}, },
"image_url": order.get("item_cover_image", {}).get("current_url", "") "image_url": order.get("item_cover_image", {}).get("current_url", "")
} }
orders_data.append(order_info) orders_data.append(order_info)
except Exception as e: 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 return orders_data
def display_orders(self): def display_orders(self):
self.log_message("[ INFO ]: Displaying orders...") self.log_message("[ INFO ]: Bestellungen werden angezeigt...")
orders = self.fetch_orders() orders = self.fetch_orders()
if not orders: if not orders:
messagebox.showinfo("Info", "No active orders found.") messagebox.showinfo("Info", "Keine aktiven Bestellungen gefunden.")
self.log_message("[ ERROR ]: No active orders found.") self.log_message("[ FEHLER ]: Keine aktiven Bestellungen gefunden.")
return return
# Clear existing widgets
for widget in self.order_frame.winfo_children(): for widget in self.order_frame.winfo_children():
widget.destroy() widget.destroy()
# Create a scrollable frame inside a Canvas
canvas = tk.Canvas(self.order_frame, bg="#ffffff") canvas = tk.Canvas(self.order_frame, bg="#ffffff")
scroll_frame = tk.Frame(canvas, bg="#ffffff") scroll_frame = tk.Frame(canvas, bg="#ffffff")
scrollbar = tk.Scrollbar(self.order_frame, orient="vertical", command=canvas.yview) scrollbar = tk.Scrollbar(self.order_frame, orient="vertical", command=canvas.yview)
@@ -110,16 +108,15 @@ class TGTGOrdersApp:
canvas.pack(side="left", fill="both", expand=True) canvas.pack(side="left", fill="both", expand=True)
canvas.create_window((0, 0), window=scroll_frame, anchor="nw") canvas.create_window((0, 0), window=scroll_frame, anchor="nw")
# Store image references to prevent garbage collection
image_refs = [] image_refs = []
for order in orders: for order in orders:
text = (f"{order['name']} - {order['store_name']}\n" text = (f"{order['name']} - {order['store_name']}\n"
f"Address: {order['address']}\n" f"Adresse: {order['address']}\n"
f"Quantity: {order['quantity']}\n" f"Menge: {order['quantity']}\n"
f"Price: {order['price']} {order['currency']}\n" f"Preis: {order['price']} {order['currency']}\n"
f"Payment: {order['payment_method']}\n" f"Zahlung: {order['payment_method']}\n"
f"Pickup: {order['pickup_window']['start']} to {order['pickup_window']['end']}\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), label = tk.Label(scroll_frame, text=text, justify="left", padx=10, pady=5, anchor="w", font=("Arial", 10),
bg="#f0f0f0", relief="ridge") bg="#f0f0f0", relief="ridge")
@@ -134,50 +131,47 @@ class TGTGOrdersApp:
img_tk = ImageTk.PhotoImage(img) img_tk = ImageTk.PhotoImage(img)
img_label = tk.Label(scroll_frame, image=img_tk) img_label = tk.Label(scroll_frame, image=img_tk)
img_label.image = img_tk # Store reference img_label.image = img_tk
image_refs.append(img_tk) # Prevent garbage collection image_refs.append(img_tk)
img_label.pack(pady=5) img_label.pack(pady=5)
except Exception as e: 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() scroll_frame.update_idletasks()
canvas.config(scrollregion=canvas.bbox("all")) canvas.config(scrollregion=canvas.bbox("all"))
# Enable scrolling with the mouse wheel
def on_mouse_wheel(event): def on_mouse_wheel(event):
canvas.yview_scroll(-1 * (event.delta // 120), "units") canvas.yview_scroll(-1 * (event.delta // 120), "units")
canvas.bind_all("<MouseWheel>", on_mouse_wheel) # Windows & MacOS canvas.bind_all("<MouseWheel>", on_mouse_wheel)
canvas.bind_all("<Button-4>", lambda e: canvas.yview_scroll(-1, "units")) # Linux Scroll Up canvas.bind_all("<Button-4>", lambda e: canvas.yview_scroll(-1, "units"))
canvas.bind_all("<Button-5>", lambda e: canvas.yview_scroll(1, "units")) # Linux Scroll Down canvas.bind_all("<Button-5>", lambda e: canvas.yview_scroll(1, "units"))
def on_startup(self): def on_startup(self):
self.log_message("[ INFO ]: Application started.") self.log_message("[ INFO ]: Anwendung gestartet.")
self.display_orders() self.display_orders()
def exit_applet(self): def exit_applet(self):
self.log_message("[ INFO ]: Exiting Applet") self.log_message("[ INFO ]: Anwendung wird beendet.")
self.parent.quit() self.parent.quit()
def about(self): @staticmethod
messagebox.showinfo("About", "PythonTGTG Script for fetching Orders on Desktop") def about():
messagebox.showinfo("Über", "TGTG OrderChecker PV2-PKG1\n PfandApplication ©")
def save_log(self): def save_log(self):
try: try:
log_content = self.log_text.get("1.0", tk.END) 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) log_file.write(log_content)
self.log_message("[ INFO ]: Log file saved successfully.") self.log_message("[ INFO ]: Protokolldatei erfolgreich gespeichert.")
except Exception as e: except Exception as e:
self.log_message(f"[ ERROR ]: Error saving log file: {e}") self.log_message(f"[ FEHLER ]: Fehler beim Speichern des Protokolls: {e}")
messagebox.showerror("Error", f"Error saving log file: {e}") messagebox.showerror("Fehler", f"Fehler beim Speichern des Protokolls: {e}")
def start_tgtg(parent=None): def start_tgtg(parent=None):
new_window = tk.Toplevel(parent) # Create a new window new_window = tk.Toplevel(parent)
new_window.title("TGTG Bestellungen") new_window.title("TGTG Orders")
new_window.geometry("500x600") new_window.geometry("500x600")
# Start the TGTGOrdersApp inside this new window
app = TGTGOrdersApp(new_window) app = TGTGOrdersApp(new_window)

View File

View File

@@ -1,8 +1,9 @@
import tkinter as tk
from tkinter import ttk
import csv import csv
import os import os
import re import re
import tkinter as tk
from tkinter import ttk
def select_file(callback=None): def select_file(callback=None):
def set_choice(choice): def set_choice(choice):
@@ -39,7 +40,7 @@ class CSVViewerApp:
self.root = root self.root = root
title = "PFANDLISTE - SPAR" if "SPAR" in filename else "PFANDLISTE - HOFER" title = "PFANDLISTE - SPAR" if "SPAR" in filename else "PFANDLISTE - HOFER"
self.root.title(title) 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 = tk.Label(root, text=title, font=("Arial", 16, "bold"))
self.label.pack(pady=10) self.label.pack(pady=10)
@@ -47,7 +48,7 @@ class CSVViewerApp:
self.frame = tk.Frame(root) self.frame = tk.Frame(root)
self.frame.pack(fill=tk.BOTH, expand=True) 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.tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
self.scrollbar = ttk.Scrollbar(self.frame, orient="vertical", command=self.tree.yview) self.scrollbar = ttk.Scrollbar(self.frame, orient="vertical", command=self.tree.yview)
@@ -55,31 +56,86 @@ class CSVViewerApp:
self.tree.configure(yscroll=self.scrollbar.set) 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("<KeyRelease>", self.search)
self.load_csv(filename) 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: try:
with open(filename, newline='', encoding='utf-8') as file: with open(filename, newline='', encoding='utf-8') as file:
reader = csv.reader(file) reader = csv.reader(file)
headers = next(reader, None) headers = next(reader, None)
self.tree['columns'] = headers self.tree["columns"] = headers
self.tree.heading("#0", text="#") # First column for index 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: for header in headers:
self.tree.heading(header, text=header) self.tree.heading(header, text=header)
self.tree.column(header, anchor="center") self.tree.column(header, anchor="center")
for i, row in enumerate(reader, start=1): 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: except FileNotFoundError:
print(f"Error: {filename} not found!") print(f"Error: {filename} not found!")
except Exception as e: except Exception as e:
print(f"Error loading CSV: {e}") print(f"Error loading CSV: {e}")
## Doesnt really work yet def sort_column(self, col):
## In the Future maybe 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): def format_markdown(text_area, text):
text_area.tag_configure("bold", font=("Arial", 10, "bold")) text_area.tag_configure("bold", font=("Arial", 10, "bold"))
text_area.tag_configure("center", justify="center") text_area.tag_configure("center", justify="center")
@@ -104,30 +160,9 @@ def format_markdown(text_area, text):
for segment, tag in segments: for segment, tag in segments:
text_area.insert(tk.END, segment, tag if tag else "") text_area.insert(tk.END, segment, tag if tag else "")
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 start_app(filename): def start_app(filename):
root = tk.Tk() root = tk.Tk()
app = CSVViewerApp(root, filename) app = CSVViewerApp(root, filename)
root.mainloop() root.mainloop()
if __name__ == "__main__": if __name__ == "__main__": select_file()
select_file()

17
run.py
View File

@@ -1,15 +1,14 @@
from PfandApplication import main from PfandApplication import main
if __name__ == "__main__": main.PfandCalculator.launch(False)
""" """
If the function launch gets called with /********************************************
* Launch Function Parameters *
False -> No autoupdates will be run || Best for Debugging! * *
* True -> Auto-Update *
True -> Autoupdates will be run * False -> Dont Auto-Update *
* None -> Idk check it :3 *
********************************************/
""" """
if __name__ == "__main__":
main.PfandCalculator.launch(False)