a0ef53922e
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
94 lines
3.5 KiB
Python
94 lines
3.5 KiB
Python
import tkinter as tk
|
|
from tkinter import simpledialog, messagebox
|
|
from typing import Callable, List
|
|
|
|
from ui import styles
|
|
|
|
|
|
class ProfileBar(tk.Frame):
|
|
"""Barra superior con dropdown de perfiles y botones New/Rename/Delete."""
|
|
|
|
def __init__(self, parent, on_change: Callable[[str], None], **kwargs):
|
|
super().__init__(parent, **kwargs)
|
|
|
|
self._on_change = on_change
|
|
|
|
tk.Label(self, text="Perfil:", font=styles.FONT_LABEL).pack(side="left", padx=(0, 4))
|
|
|
|
self._var = tk.StringVar()
|
|
self._dropdown = tk.OptionMenu(self, self._var, "")
|
|
self._dropdown.config(font=styles.FONT_LABEL, width=20)
|
|
self._dropdown.pack(side="left", padx=4)
|
|
|
|
tk.Button(self, text="New", font=styles.FONT_SMALL, command=self._new_profile).pack(side="left", padx=2)
|
|
tk.Button(self, text="Rename", font=styles.FONT_SMALL, command=self._rename_profile).pack(side="left", padx=2)
|
|
tk.Button(self, text="Delete", font=styles.FONT_SMALL, command=self._delete_profile).pack(side="left", padx=2)
|
|
|
|
# Callbacks inyectados desde app.py
|
|
self._cb_new: Callable[[str], bool] = lambda name: False
|
|
self._cb_rename: Callable[[str, str], bool] = lambda old, new: False
|
|
self._cb_delete: Callable[[str], bool] = lambda name: False
|
|
|
|
# ------------------------------------------------------------------
|
|
# API pública
|
|
# ------------------------------------------------------------------
|
|
|
|
def set_callbacks(
|
|
self,
|
|
on_new: Callable[[str], bool],
|
|
on_rename: Callable[[str, str], bool],
|
|
on_delete: Callable[[str], bool],
|
|
) -> None:
|
|
self._cb_new = on_new
|
|
self._cb_rename = on_rename
|
|
self._cb_delete = on_delete
|
|
|
|
def refresh(self, names: List[str], active: str) -> None:
|
|
"""Actualiza el dropdown con la lista de nombres de perfil."""
|
|
menu = self._dropdown["menu"]
|
|
menu.delete(0, "end")
|
|
for name in names:
|
|
menu.add_command(label=name, command=lambda n=name: self._select(n))
|
|
self._var.set(active)
|
|
|
|
def current(self) -> str:
|
|
return self._var.get()
|
|
|
|
# ------------------------------------------------------------------
|
|
# Acciones internas
|
|
# ------------------------------------------------------------------
|
|
|
|
def _select(self, name: str) -> None:
|
|
self._var.set(name)
|
|
self._on_change(name)
|
|
|
|
def _new_profile(self) -> None:
|
|
name = simpledialog.askstring("Nuevo perfil", "Nombre del perfil:", parent=self)
|
|
if not name:
|
|
return
|
|
name = name.strip()
|
|
if not name:
|
|
return
|
|
if self._cb_new(name):
|
|
self._on_change(name)
|
|
else:
|
|
messagebox.showerror("Error", f"Ya existe un perfil con el nombre '{name}'.")
|
|
|
|
def _rename_profile(self) -> None:
|
|
old = self._var.get()
|
|
new = simpledialog.askstring("Renombrar perfil", f"Nuevo nombre para '{old}':", parent=self)
|
|
if not new:
|
|
return
|
|
new = new.strip()
|
|
if not new:
|
|
return
|
|
if not self._cb_rename(old, new):
|
|
messagebox.showerror("Error", f"No se pudo renombrar el perfil.")
|
|
|
|
def _delete_profile(self) -> None:
|
|
name = self._var.get()
|
|
if not messagebox.askyesno("Eliminar perfil", f"¿Eliminar el perfil '{name}'?"):
|
|
return
|
|
if not self._cb_delete(name):
|
|
messagebox.showerror("Error", "No se puede eliminar el único perfil existente.")
|