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
# Local Dependencies
from PfandApplication.wiki import main as WIKI
from PfandApplication.wiki import main as wiki
from PfandApplication.pfand_scanner import launch_pfand_scanner
from PfandApplication.updater import open_updater as open_updater, run_silent_update
from PfandApplication.tgtg_orderchecker import main as tgtg
@@ -33,6 +33,7 @@ class Achievement:
class PfandCalculator:
def __init__(self, root):
self.achievement_image_gray = None
self.root = root
self.root.title("Österreichischer Pfandrechner")
@@ -63,7 +64,8 @@ class PfandCalculator:
self.achievement_image = self.load_achievement_image()
def load_image(self, product_name):
@staticmethod
def load_image(product_name):
try:
# Use Flaschen icon for Bierflasche
if product_name == "Bierflasche":
@@ -115,7 +117,8 @@ class PfandCalculator:
print(f"Error loading achievement image: {e}")
return None
def initialize_achievements(self):
@staticmethod
def initialize_achievements():
return {
"each_100": Achievement("Krass, Weiter So!", "Du hast bis jetzt 100 von jedem Element gesammelt!", "each_element", 100),
"each_500": Achievement("Adlersson wäre neidisch!", "Adlersson wäre neidisch auf dich! Du hast 500 von jedem Element gesammelt!", "each_element", 500),
@@ -463,7 +466,7 @@ class PfandCalculator:
file_menu.add_command(label="Neulanden der UI", command=self.recreate_widgets, accelerator="Strg+R")
file_menu.add_command(label="Updater", command=open_updater, accelerator="Strg+U") # Added this to the File Menu too!
file_menu.add_separator()
file_menu.add_command(label="Öffne PfandListe", command=WIKI.select_file, accelerator="Strg+L")
file_menu.add_command(label="Öffne PfandListe", command=wiki.select_file, accelerator="Strg+L")
file_menu.add_command(label="Beenden", command=self.root.quit, accelerator="Strg+Q")
file_menu.add_separator()
file_menu.add_command(label="Über Programm", command=self.create_credits, accelerator="Strg+F10")
@@ -538,7 +541,7 @@ class PfandCalculator:
self.root.bind('<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_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-u>', lambda e: open_updater()) # New Update Feature (Version 7.4.000 UPDATER)
@@ -741,7 +744,7 @@ class PfandCalculator:
def confirm_deposit():
date = date_picker.get_date().strftime("%d.%m.%Y")
current_total = sum(self.quantities[product] * self.PRICES[product]
current_total = sum(self.quantities[product] * self.PRICES[product]
for product in self.products)
deposit_record = {
@@ -1564,12 +1567,14 @@ class PfandCalculator:
root = tk.Tk()
app = PfandCalculator(root)
if check_for_update == True:
root.after(1, run_silent_update) # Run uc on start (1s delay) => updater.py module || UNCOMMENT IN PROD
else:
if check_for_update is None:
root.after(500, root.destroy) # We do a lil bit of Trolling here
elif not check_for_update:
pass
else:
root.after(1, run_silent_update)
root.mainloop()
if __name__ == "__main__":
PfandCalculator.launch(True)
# Run AutoUpdates by default
if __name__ == "__main__": PfandCalculator.launch(True)

View File

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

View File

View File

@@ -1,8 +1,9 @@
import tkinter as tk
from tkinter import ttk
import csv
import os
import re
import tkinter as tk
from tkinter import ttk
def select_file(callback=None):
def set_choice(choice):
@@ -15,23 +16,23 @@ def select_file(callback=None):
callback(filename)
else:
start_app(filename)
select_window = tk.Tk()
select_window.title("Wähle eine Liste")
select_window.geometry("300x200")
label = tk.Label(select_window, text="Bitte eine Liste wählen:", font=("Arial", 12))
label.pack(pady=10)
spar_button = tk.Button(select_window, text="SPAR", command=lambda: set_choice("SPAR"), width=15)
spar_button.pack(pady=5)
hofer_button = tk.Button(select_window, text="HOFER", command=lambda: set_choice("HOFER"), width=15)
hofer_button.pack(pady=5)
wiki_button = tk.Button(select_window, text="Wiki", command=lambda: set_choice("Wiki"), width=15)
wiki_button.pack(pady=5)
select_window.mainloop()
class CSVViewerApp:
@@ -39,95 +40,129 @@ class CSVViewerApp:
self.root = root
title = "PFANDLISTE - SPAR" if "SPAR" in filename else "PFANDLISTE - HOFER"
self.root.title(title)
self.root.geometry("600x400")
self.root.geometry("800x600")
self.label = tk.Label(root, text=title, font=("Arial", 16, "bold"))
self.label.pack(pady=10)
self.frame = tk.Frame(root)
self.frame.pack(fill=tk.BOTH, expand=True)
self.tree = ttk.Treeview(self.frame)
self.tree = ttk.Treeview(self.frame, show="headings")
self.tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
self.scrollbar = ttk.Scrollbar(self.frame, orient="vertical", command=self.tree.yview)
self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
self.tree.configure(yscroll=self.scrollbar.set)
# Create a frame for search functionality and style it
search_frame = tk.Frame(root, pady=10, padx=20)
search_frame.pack(fill=tk.X)
self.search_label = tk.Label(search_frame, text="Search:", font=("Arial", 12), anchor="w")
self.search_label.pack(side=tk.LEFT)
self.search_entry = tk.Entry(search_frame, font=("Arial", 12), relief="solid", borderwidth=2)
self.search_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=10)
self.search_entry.bind("<KeyRelease>", self.search)
self.load_csv(filename)
def load_csv(self, filename):
def search(self, event):
search_term = self.search_entry.get().lower()
for row in self.tree.get_children():
self.tree.delete(row)
self.load_csv(self.filename, search_term)
def load_csv(self, filename, search_term=""):
self.filename = filename
try:
with open(filename, newline='', encoding='utf-8') as file:
reader = csv.reader(file)
headers = next(reader, None)
self.tree['columns'] = headers
self.tree["columns"] = headers
self.tree.heading("#0", text="#") # First column for index
self.tree.column("#0", width=50)
self.tree.column("#0", width=50, anchor="center")
for header in headers:
self.tree.heading(header, text=header)
self.tree.column(header, anchor="center")
for i, row in enumerate(reader, start=1):
self.tree.insert("", "end", text=i, values=row)
if any(search_term.lower() in str(cell).lower() for cell in row):
self.tree.insert("", "end", text=i, values=row)
except FileNotFoundError:
print(f"Error: {filename} not found!")
except Exception as e:
print(f"Error loading CSV: {e}")
## Doesnt really work yet
## In the Future maybe
def format_markdown(text_area, text):
text_area.tag_configure("bold", font=("Arial", 10, "bold"))
text_area.tag_configure("center", justify="center")
text_area.delete("1.0", tk.END)
segments = []
last_end = 0
for match in re.finditer(r'<p align="center">(.*?)</p>|\*\*(.*?)\*\*', text, re.DOTALL):
segments.append((text[last_end:match.start()], None))
if match.group(1): # Centered text
segments.append((match.group(1), "center"))
elif match.group(2): # Bold text
segments.append((match.group(2), "bold"))
last_end = match.end()
segments.append((text[last_end:], None))
for segment, tag in segments:
text_area.insert(tk.END, segment, tag if tag else "")
def sort_column(self, col):
data = [(self.tree.item(item)["values"], item) for item in self.tree.get_children("")]
data.sort(key=lambda x: x[0][col])
for idx, item in enumerate(data):
self.tree.move(item[1], '', idx)
def right_click_menu(self, event):
selected_item = self.tree.selection()
menu = tk.Menu(self.root, tearoff=0)
menu.add_command(label="Copy", command=lambda: self.copy_cell(selected_item))
menu.post(event.x_root, event.y_root)
def copy_cell(self, selected_item):
# Copy data from the selected row to clipboard
if selected_item:
row_values = self.tree.item(selected_item[0])["values"]
self.root.clipboard_clear()
self.root.clipboard_append(' | '.join(row_values))
def open_wiki():
wiki_window = tk.Tk()
wiki_window.title("Wiki")
wiki_window.geometry("500x400")
text_area = tk.Text(wiki_window, wrap=tk.WORD)
text_area.pack(expand=True, fill=tk.BOTH)
filename = os.path.join("PfandApplication/wiki", "wiki.md")
try:
with open(filename, "r", encoding="utf-8") as file:
content = file.read()
format_markdown(text_area, content)
except FileNotFoundError:
text_area.insert(tk.END, f"Fehler: '{filename}' nicht gefunden!")
wiki_window.mainloop()
def format_markdown(text_area, text):
text_area.tag_configure("bold", font=("Arial", 10, "bold"))
text_area.tag_configure("center", justify="center")
text_area.delete("1.0", tk.END)
segments = []
last_end = 0
for match in re.finditer(r'<p align="center">(.*?)</p>|\*\*(.*?)\*\*', text, re.DOTALL):
segments.append((text[last_end:match.start()], None))
if match.group(1): # Centered text
segments.append((match.group(1), "center"))
elif match.group(2): # Bold text
segments.append((match.group(2), "bold"))
last_end = match.end()
segments.append((text[last_end:], None))
for segment, tag in segments:
text_area.insert(tk.END, segment, tag if tag else "")
def start_app(filename):
root = tk.Tk()
app = CSVViewerApp(root, filename)
root.mainloop()
if __name__ == "__main__":
select_file()
if __name__ == "__main__": select_file()