proyecto-global-psp/vista/central_panel/view_alarmas.py

169 lines
6.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Módulo: vista/central_panel/view_alarmas.py
import tkinter as tk
from tkinter import ttk
from vista.config import *
# AlarmManager se importa en PanelCentral y se pasa como argumento
class AlarmaPanel(ttk.Frame):
"""
Panel de la pestaña Alarmas (T4).
Interfaz para programar y visualizar el tiempo restante de las alarmas.
"""
def __init__(self, parent_notebook, root, alarm_manager, *args, **kwargs):
super().__init__(parent_notebook, *args, **kwargs)
self.root = root
# Lógica de alarmas pasada desde el controlador
self.alarm_manager = alarm_manager
self.after_alarm_id = None
self.alarm_hours_entry = None
self.alarm_minutes_entry = None
self.alarm_seconds_entry = None
self.scrollable_frame = None
self.crear_interfaz_alarmas(self)
self.iniciar_actualizacion_alarmas()
# -------------------------------------------------------------
# 🔔 VISTA Y LÓGICA DE ALARMAS
# -------------------------------------------------------------
def crear_interfaz_alarmas(self, parent_frame):
"""Crea la interfaz para programar y visualizar alarmas (H:M:S)."""
frame = ttk.Frame(parent_frame, padding=10, style='TFrame')
frame.pack(expand=True, fill="both")
ttk.Label(frame, text="Programar Nuevo Temporizador (H:M:S)", font=FUENTE_NEGOCIOS).pack(pady=(0, 10))
# --- Controles de Nueva Alarma (H:M:S) ---
frame_input = ttk.Frame(frame, style='TFrame')
frame_input.pack(fill='x', pady=5)
ttk.Label(frame_input, text="Horas:").pack(side='left', padx=(0, 2))
self.alarm_hours_entry = ttk.Entry(frame_input, width=3);
self.alarm_hours_entry.pack(side='left', padx=(0, 10))
self.alarm_hours_entry.insert(0, "0")
ttk.Label(frame_input, text="Minutos:").pack(side='left', padx=(0, 2))
self.alarm_minutes_entry = ttk.Entry(frame_input, width=3);
self.alarm_minutes_entry.pack(side='left', padx=(0, 10))
self.alarm_minutes_entry.insert(0, "1")
ttk.Label(frame_input, text="Segundos:").pack(side='left', padx=(0, 2))
self.alarm_seconds_entry = ttk.Entry(frame_input, width=3);
self.alarm_seconds_entry.pack(side='left', padx=(0, 15))
self.alarm_seconds_entry.insert(0, "0")
ttk.Button(frame_input, text=" Crear Alarma", command=self.manejar_nueva_alarma,
style='Action.TButton').pack(side='left')
ttk.Separator(frame, orient='horizontal').pack(fill='x', pady=15)
# --- Listado de Alarmas Activas ---
ttk.Label(frame, text="Alarmas Activas (Tiempo Restante)", font=FUENTE_NEGOCIOS).pack(pady=(0, 5))
self.alarm_list_frame = ttk.Frame(frame)
self.alarm_list_frame.pack(fill="both", expand=True)
canvas = tk.Canvas(self.alarm_list_frame, borderwidth=0, background=COLOR_BLANCO)
vscroll = ttk.Scrollbar(self.alarm_list_frame, orient="vertical", command=canvas.yview)
self.scrollable_frame = ttk.Frame(canvas)
self.scrollable_frame.bind("<Configure>", lambda e: canvas.configure(scrollregion=canvas.bbox("all")))
canvas.create_window((0, 0), window=self.scrollable_frame, anchor="nw")
canvas.configure(yscrollcommand=vscroll.set)
canvas.pack(side="left", fill="both", expand=True)
vscroll.pack(side="right", fill="y")
def add_alarm_row(self, parent, alarm_data):
"""Añade una fila con la info de la alarma y su botón de cancelación."""
row_frame = ttk.Frame(parent, padding=5, style='Note.TFrame')
row_frame.pack(fill='x', padx=5, pady=2)
total_s = alarm_data['total_seconds']
h = total_s // 3600
m = (total_s % 3600) // 60
s = total_s % 60
total_time_str = f"{h:02d}h:{m:02d}m:{s:02d}s"
info_text = (f"[ID{alarm_data['id']}] {alarm_data['restante']} -> {alarm_data['nombre']} "
f"({total_time_str} total)")
ttk.Label(row_frame, text=info_text, font=('Consolas', 10), style='Note.TLabel').pack(side='left', fill='x',
expand=True)
ttk.Button(row_frame, text="❌ Cancelar", style='Danger.TButton', width=10,
command=lambda id=alarm_data['id']: self.manejar_cancelar_alarma(id)).pack(side='right')
def manejar_nueva_alarma(self):
"""Captura los datos del formulario (H:M:S) y llama al AlarmManager."""
try:
hours = int(self.alarm_hours_entry.get() or 0)
minutes = int(self.alarm_minutes_entry.get() or 0)
seconds = int(self.alarm_seconds_entry.get() or 0)
total_seconds = (hours * 3600) + (minutes * 60) + seconds
if total_seconds <= 0:
print("⚠️ El tiempo de alarma debe ser un número positivo (H:M:S > 0).")
return
self.alarm_manager.set_alarm(total_seconds)
# Limpiar campos
self.alarm_hours_entry.delete(0, tk.END);
self.alarm_hours_entry.insert(0, "0")
self.alarm_minutes_entry.delete(0, tk.END);
self.alarm_minutes_entry.insert(0, "1")
self.alarm_seconds_entry.delete(0, tk.END);
self.alarm_seconds_entry.insert(0, "0")
self.actualizar_lista_alarmas()
except ValueError:
print("⚠️ Por favor, introduce números enteros válidos para el tiempo.")
def manejar_cancelar_alarma(self, alarm_id):
"""Cancela la alarma usando su ID."""
if self.alarm_manager.cancel_alarm(alarm_id):
self.actualizar_lista_alarmas()
def actualizar_lista_alarmas(self):
"""Actualiza la visualización de las alarmas activas."""
if not self.scrollable_frame:
self.after_alarm_id = self.after(1000, self.actualizar_lista_alarmas)
return
for widget in self.scrollable_frame.winfo_children():
widget.destroy()
active_alarms = self.alarm_manager.get_active_alarms()
if not active_alarms:
ttk.Label(self.scrollable_frame, text="--- No hay alarmas activas ---", font=('Consolas', 10),
foreground=COLOR_TEXTO).pack(padx=10, pady=10)
for alarm in active_alarms:
self.add_alarm_row(self.scrollable_frame, alarm)
self.after_alarm_id = self.after(1000, self.actualizar_lista_alarmas)
def iniciar_actualizacion_alarmas(self):
"""Inicia el ciclo de actualización de la lista de alarmas."""
self.after_alarm_id = self.after(0, self.actualizar_lista_alarmas)
def detener_actualizacion(self):
"""Detiene el ciclo de actualización."""
if self.after_alarm_id:
self.after_cancel(self.after_alarm_id)
self.after_alarm_id = None
print("Ciclo de actualización de alarmas detenido.")