200 lines
6.9 KiB
Python
200 lines
6.9 KiB
Python
# RepoSync/gui/profile_dialog.py
|
|
|
|
"""
|
|
A Toplevel dialog window for managing server connection profiles.
|
|
"""
|
|
|
|
import tkinter as tk
|
|
from tkinter import ttk, messagebox
|
|
from typing import Dict
|
|
|
|
from ..config.profile_manager import ProfileManager
|
|
|
|
|
|
class ProfileDialog(tk.Toplevel):
|
|
"""
|
|
A modal dialog for adding, editing, and deleting server profiles.
|
|
"""
|
|
|
|
def __init__(self, parent, profile_manager: ProfileManager):
|
|
super().__init__(parent)
|
|
self.parent = parent
|
|
self.profile_manager = profile_manager
|
|
|
|
self.title("Manage Server Profiles")
|
|
self.geometry("800x400")
|
|
|
|
# Make the window modal
|
|
self.transient(parent)
|
|
self.grab_set()
|
|
|
|
# Data variables
|
|
self.profile_name = tk.StringVar()
|
|
self.server_url = tk.StringVar()
|
|
self.token = tk.StringVar()
|
|
self.service_type = tk.StringVar()
|
|
|
|
self._create_widgets()
|
|
self._load_profiles_to_listbox()
|
|
|
|
self.protocol("WM_DELETE_WINDOW", self._on_close)
|
|
|
|
def _create_widgets(self):
|
|
main_frame = ttk.Frame(self, padding="10")
|
|
main_frame.pack(expand=True, fill="both")
|
|
main_frame.columnconfigure(0, weight=1)
|
|
main_frame.columnconfigure(1, weight=2)
|
|
main_frame.rowconfigure(0, weight=1)
|
|
|
|
# --- Left Pane: Profile List ---
|
|
list_frame = ttk.LabelFrame(main_frame, text="Profiles", padding="10")
|
|
list_frame.grid(row=0, column=0, sticky="nsew", padx=(0, 5))
|
|
list_frame.rowconfigure(0, weight=1)
|
|
list_frame.columnconfigure(0, weight=1)
|
|
|
|
self.profile_listbox = tk.Listbox(list_frame, exportselection=False)
|
|
self.profile_listbox.grid(row=0, column=0, sticky="nsew")
|
|
self.profile_listbox.bind("<<ListboxSelect>>", self._on_profile_select)
|
|
|
|
scrollbar = ttk.Scrollbar(
|
|
list_frame, orient="vertical", command=self.profile_listbox.yview
|
|
)
|
|
scrollbar.grid(row=0, column=1, sticky="ns")
|
|
self.profile_listbox.config(yscrollcommand=scrollbar.set)
|
|
|
|
# --- Right Pane: Profile Details ---
|
|
details_frame = ttk.LabelFrame(main_frame, text="Profile Details", padding="10")
|
|
details_frame.grid(row=0, column=1, sticky="nsew", padx=(5, 0))
|
|
details_frame.columnconfigure(1, weight=1)
|
|
|
|
ttk.Label(details_frame, text="Profile Name:").grid(
|
|
row=0, column=0, sticky="w", pady=2
|
|
)
|
|
ttk.Entry(details_frame, textvariable=self.profile_name).grid(
|
|
row=0, column=1, sticky="ew", pady=2
|
|
)
|
|
|
|
ttk.Label(details_frame, text="Server URL:").grid(
|
|
row=1, column=0, sticky="w", pady=2
|
|
)
|
|
ttk.Entry(details_frame, textvariable=self.server_url).grid(
|
|
row=1, column=1, sticky="ew", pady=2
|
|
)
|
|
|
|
ttk.Label(details_frame, text="Access Token:").grid(
|
|
row=2, column=0, sticky="w", pady=2
|
|
)
|
|
ttk.Entry(details_frame, textvariable=self.token, show="*").grid(
|
|
row=2, column=1, sticky="ew", pady=2
|
|
)
|
|
|
|
ttk.Label(details_frame, text="Service Type:").grid(
|
|
row=3, column=0, sticky="w", pady=2
|
|
)
|
|
ttk.Combobox(
|
|
details_frame,
|
|
textvariable=self.service_type,
|
|
values=["gitea", "github"], # Future-proof
|
|
state="readonly",
|
|
).grid(row=3, column=1, sticky="ew", pady=2)
|
|
|
|
# --- Buttons ---
|
|
button_frame = ttk.Frame(details_frame)
|
|
button_frame.grid(row=4, column=0, columnspan=2, pady=10, sticky="e")
|
|
|
|
ttk.Button(button_frame, text="New", command=self._clear_fields).pack(
|
|
side="left", padx=5
|
|
)
|
|
ttk.Button(button_frame, text="Save", command=self._save_profile).pack(
|
|
side="left", padx=5
|
|
)
|
|
ttk.Button(button_frame, text="Delete", command=self._delete_profile).pack(
|
|
side="left", padx=5
|
|
)
|
|
|
|
def _load_profiles_to_listbox(self):
|
|
"""Clears and reloads profile names into the listbox."""
|
|
self.profile_listbox.delete(0, tk.END)
|
|
for name in sorted(self.profile_manager.get_profile_names()):
|
|
self.profile_listbox.insert(tk.END, name)
|
|
|
|
def _on_profile_select(self, event=None):
|
|
"""Handles selection of a profile in the listbox."""
|
|
selected_indices = self.profile_listbox.curselection()
|
|
if not selected_indices:
|
|
return
|
|
|
|
selected_name = self.profile_listbox.get(selected_indices[0])
|
|
profile_data = self.profile_manager.get_profile(selected_name)
|
|
|
|
if profile_data:
|
|
self.profile_name.set(selected_name)
|
|
self.server_url.set(profile_data.get("url", ""))
|
|
self.token.set(profile_data.get("token", ""))
|
|
self.service_type.set(profile_data.get("type", "gitea"))
|
|
|
|
def _clear_fields(self):
|
|
"""Clears all entry fields."""
|
|
self.profile_name.set("")
|
|
self.server_url.set("")
|
|
self.token.set("")
|
|
self.service_type.set("gitea")
|
|
self.profile_listbox.selection_clear(0, tk.END)
|
|
|
|
def _save_profile(self):
|
|
"""Saves the current data as a new or updated profile."""
|
|
name = self.profile_name.get().strip()
|
|
if not name:
|
|
messagebox.showerror(
|
|
"Validation Error", "Profile Name cannot be empty.", parent=self
|
|
)
|
|
return
|
|
|
|
profile_data = {
|
|
"url": self.server_url.get().strip(),
|
|
"token": self.token.get().strip(),
|
|
"type": self.service_type.get(),
|
|
}
|
|
|
|
self.profile_manager.add_or_update_profile(name, profile_data)
|
|
|
|
self._load_profiles_to_listbox()
|
|
# Reselect the saved profile
|
|
for i, item_name in enumerate(self.profile_listbox.get(0, tk.END)):
|
|
if item_name == name:
|
|
self.profile_listbox.selection_set(i)
|
|
self.profile_listbox.see(i)
|
|
break
|
|
|
|
messagebox.showinfo(
|
|
"Success", f"Profile '{name}' saved successfully.", parent=self
|
|
)
|
|
|
|
def _delete_profile(self):
|
|
"""Deletes the selected profile."""
|
|
selected_indices = self.profile_listbox.curselection()
|
|
if not selected_indices:
|
|
messagebox.showwarning(
|
|
"No Selection", "Please select a profile to delete.", parent=self
|
|
)
|
|
return
|
|
|
|
name_to_delete = self.profile_listbox.get(selected_indices[0])
|
|
|
|
if messagebox.askyesno(
|
|
"Confirm Delete",
|
|
f"Are you sure you want to delete the profile '{name_to_delete}'?",
|
|
parent=self,
|
|
):
|
|
self.profile_manager.delete_profile(name_to_delete)
|
|
self._clear_fields()
|
|
self._load_profiles_to_listbox()
|
|
messagebox.showinfo(
|
|
"Success", f"Profile '{name_to_delete}' deleted.", parent=self
|
|
)
|
|
|
|
def _on_close(self):
|
|
"""Ensures grab_release is called when the window is closed."""
|
|
self.grab_release()
|
|
self.destroy()
|