import os import threading import queue import webbrowser from pathlib import Path import tkinter as tk from tkinter import ttk, scrolledtext, messagebox, filedialog from bot import BotRunner from config import DEFAULT_TARGET_URL LOG_POLL_MS = 200 class GUI: def __init__(self, root: tk.Tk): self.root = root root.title("ADM PURCHASING TOOLS") root.geometry("760x620") self.log_queue = queue.Queue() self.stop_event = threading.Event() self.worker_thread = None frm = ttk.Frame(root, padding=12) frm.pack(fill=tk.BOTH, expand=True) # Inputs inputs = ttk.Frame(frm) inputs.pack(fill=tk.X) ttk.Label(inputs, text="Target URL:").grid(row=0, column=0, sticky=tk.W, pady=4) self.url_var = tk.StringVar(value=DEFAULT_TARGET_URL) ttk.Entry(inputs, textvariable=self.url_var, width=80).grid(row=0, column=1, sticky=tk.W) # Buttons btns = ttk.Frame(frm, padding=(0, 8, 0, 8)) btns.pack(fill=tk.X) self.start_btn = ttk.Button(btns, text="Start", command=self.start) self.start_btn.pack(side=tk.LEFT, padx=6) self.stop_btn = ttk.Button(btns, text="Stop", command=self.stop, state=tk.DISABLED) self.stop_btn.pack(side=tk.LEFT, padx=6) # Status / Progress status_frame = ttk.Frame(frm) status_frame.pack(fill=tk.X) self.status_var = tk.StringVar(value="Ready") ttk.Label(status_frame, textvariable=self.status_var).pack(side=tk.LEFT) self.progress = ttk.Progressbar(status_frame, mode="indeterminate") self.progress.pack(fill=tk.X, padx=8, pady=6) # Log panel ttk.Label(frm, text="Logs:").pack(anchor=tk.W) self.log_widget = scrolledtext.ScrolledText(frm, height=20, state=tk.DISABLED) self.log_widget.pack(fill=tk.BOTH, expand=True) # Poll logs root.after(LOG_POLL_MS, self._poll_log) def append_log(self, text: str): self.log_widget.configure(state=tk.NORMAL) self.log_widget.insert(tk.END, text + "\n") self.log_widget.see(tk.END) self.log_widget.configure(state=tk.DISABLED) def _poll_log(self): try: while True: item = self.log_queue.get_nowait() if isinstance(item, dict) and item.get("type") == "status": self.status_var.set(item.get("text", "")) else: self.append_log(str(item)) except queue.Empty: pass finally: self.root.after(LOG_POLL_MS, self._poll_log) def start(self): url = self.url_var.get().strip() if not url: messagebox.showerror("Missing field", "Please enter a target URL") return self.stop_event.clear() self.start_btn.config(state=tk.DISABLED) self.stop_btn.config(state=tk.NORMAL) self.progress.start(10) self.status_var.set("Starting...") runner = BotRunner( target_url=url, log_queue=self.log_queue, stop_event=self.stop_event, ) def worker(): try: runner.run() self.log_queue.put({"type": "status", "text": "Completed"}) except Exception as e: self.log_queue.put(f"Error: {e}") finally: self.progress.stop() self.start_btn.config(state=tk.NORMAL) self.stop_btn.config(state=tk.DISABLED) self.worker_thread = threading.Thread(target=worker, daemon=True) self.worker_thread.start() def stop(self): if messagebox.askyesno("Stop", "Stop the running job?"): self.stop_event.set() self.status_var.set("Stopping...") def open_exports(self): p = Path.cwd() webbrowser.open(p.as_uri()) def run_gui(): root = tk.Tk() gui = GUI(root) root.mainloop()