Spaces:
Sleeping
Sleeping
| 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() | |