136 lines
6.0 KiB
Python
136 lines
6.0 KiB
Python
import tkinter as tk
|
|
from tkinter import ttk, messagebox, filedialog
|
|
import sys
|
|
import os
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '.core'))
|
|
from settings import load_settings, save_settings
|
|
from config import DEFAULT_TEMPERATURE, DEFAULT_PROVIDER_NAME
|
|
from providers import list_provider_names
|
|
|
|
class SettingsDialog(tk.Toplevel):
|
|
def __init__(self, parent):
|
|
super().__init__(parent)
|
|
self.title("Settings")
|
|
self.geometry("500x400")
|
|
self.transient(parent)
|
|
self.grab_set()
|
|
self.settings = load_settings()
|
|
|
|
notebook = ttk.Notebook(self)
|
|
notebook.pack(fill="both", expand=True, padx=10, pady=10)
|
|
|
|
# General tab
|
|
general_frame = ttk.Frame(notebook)
|
|
notebook.add(general_frame, text="General")
|
|
|
|
ttk.Label(general_frame, text="Default Provider:").grid(row=0, column=0, sticky="w", pady=6)
|
|
self.provider_var = tk.StringVar(value=self.settings.get("default_provider", DEFAULT_PROVIDER_NAME))
|
|
self.provider_combo = ttk.Combobox(general_frame, textvariable=self.provider_var, values=list_provider_names(), state="readonly", width=32)
|
|
self.provider_combo.grid(row=0, column=1, sticky="ew", padx=8)
|
|
|
|
ttk.Label(general_frame, text="Default Temperature:").grid(row=1, column=0, sticky="w", pady=6)
|
|
self.temp_var = tk.DoubleVar(value=self.settings.get("default_temperature", DEFAULT_TEMPERATURE))
|
|
self.temp_entry = ttk.Entry(general_frame, textvariable=self.temp_var, width=8)
|
|
self.temp_entry.grid(row=1, column=1, sticky="w", padx=8)
|
|
|
|
# Model paths tab
|
|
paths_frame = ttk.Frame(notebook)
|
|
notebook.add(paths_frame, text="Model Paths")
|
|
# Model paths now as list of dicts: {"nickname": str, "path": str}
|
|
self.paths = self.settings.get("local_model_paths", [])
|
|
if self.paths and isinstance(self.paths[0], str):
|
|
# Migrate from old format
|
|
self.paths = [{"nickname": os.path.basename(p.rstrip("/")), "path": p} for p in self.paths]
|
|
self.paths_list = tk.Listbox(paths_frame, selectmode=tk.SINGLE, width=60, height=8)
|
|
self.paths_list.pack(fill="x", padx=8, pady=(8,4))
|
|
self.refresh_paths_list()
|
|
|
|
btn_frame = ttk.Frame(paths_frame)
|
|
btn_frame.pack(fill="x", padx=8, pady=4)
|
|
ttk.Button(btn_frame, text="Add Path", command=self.add_path).pack(side="left")
|
|
ttk.Button(btn_frame, text="Edit Selected", command=self.edit_path).pack(side="left", padx=(8,0))
|
|
ttk.Button(btn_frame, text="Remove Selected", command=self.remove_path).pack(side="left", padx=(8,0))
|
|
|
|
# Key/legend for nicknames
|
|
key_frame = ttk.Frame(paths_frame)
|
|
key_frame.pack(fill="x", padx=8, pady=(8, 4))
|
|
key_text = (
|
|
"Nickname: A short label for this model path. "
|
|
"You can use nicknames to quickly identify or group model folders. "
|
|
"For example, use 'Main', 'Backup', or 'Experimental'. "
|
|
"Nicknames are for your reference only and do not affect model loading."
|
|
)
|
|
ttk.Label(key_frame, text=key_text, wraplength=420, foreground="#878787").pack(anchor="w")
|
|
|
|
def refresh_paths_list(self):
|
|
self.paths_list.delete(0, "end")
|
|
for entry in self.paths:
|
|
display = f"{entry.get('nickname','')} — {entry.get('path','')}"
|
|
self.paths_list.insert("end", display)
|
|
|
|
def add_path(self):
|
|
self.edit_path(new=True)
|
|
|
|
def edit_path(self, new=False):
|
|
idx = None
|
|
if not new:
|
|
sel = self.paths_list.curselection()
|
|
if not sel:
|
|
return
|
|
idx = sel[0]
|
|
entry = self.paths[idx]
|
|
else:
|
|
entry = {"nickname": "", "path": ""}
|
|
popup = tk.Toplevel(self)
|
|
popup.title("Edit Model Path")
|
|
popup.geometry("400x140")
|
|
tk.Label(popup, text="Nickname:").pack(anchor="w", padx=12, pady=(12,0))
|
|
nick_var = tk.StringVar(value=entry.get("nickname", ""))
|
|
nick_entry = ttk.Entry(popup, textvariable=nick_var, width=40)
|
|
nick_entry.pack(fill="x", padx=12)
|
|
tk.Label(popup, text="Path:").pack(anchor="w", padx=12, pady=(8,0))
|
|
path_var = tk.StringVar(value=entry.get("path", ""))
|
|
path_entry = ttk.Entry(popup, textvariable=path_var, width=40)
|
|
path_entry.pack(fill="x", padx=12)
|
|
def save_edit():
|
|
new_entry = {"nickname": nick_var.get().strip(), "path": path_var.get().strip()}
|
|
if not new_entry["path"]:
|
|
messagebox.showerror("Error", "Path cannot be empty.", parent=popup)
|
|
return
|
|
if new:
|
|
self.paths.append(new_entry)
|
|
else:
|
|
self.paths[idx] = new_entry
|
|
self.refresh_paths_list()
|
|
popup.destroy()
|
|
btns = ttk.Frame(popup)
|
|
btns.pack(fill="x", pady=10)
|
|
ttk.Button(btns, text="Save", command=save_edit).pack(side="right", padx=12)
|
|
ttk.Button(btns, text="Cancel", command=popup.destroy).pack(side="right")
|
|
|
|
# Save/Cancel
|
|
save_btn = ttk.Button(self, text="Save", command=self.save)
|
|
save_btn.pack(side="right", padx=10, pady=10)
|
|
cancel_btn = ttk.Button(self, text="Cancel", command=self.destroy)
|
|
cancel_btn.pack(side="right", pady=10)
|
|
|
|
def add_path(self):
|
|
selection = filedialog.askdirectory(parent=self)
|
|
if selection and selection not in self.paths_list.get(0, "end"):
|
|
self.paths_list.insert("end", selection)
|
|
|
|
def remove_path(self):
|
|
sel = self.paths_list.curselection()
|
|
if sel:
|
|
idx = sel[0]
|
|
del self.paths[idx]
|
|
self.refresh_paths_list()
|
|
|
|
def save(self):
|
|
self.settings["default_provider"] = self.provider_var.get().strip()
|
|
self.settings["default_temperature"] = self.temp_var.get()
|
|
self.settings["local_model_paths"] = self.paths
|
|
save_settings(self.settings)
|
|
messagebox.showinfo("Settings", "Settings saved.")
|
|
self.destroy()
|