🚫 COPIA BLOCCATA
# src/gui/main_window.py
import tkinter as tk
from tkinter import ttk, messagebox, font
from typing import Optional, Callable
import webbrowser
from ..database.manager import DatabaseManager
class MainWindow:
"""
Finestra principale dell'applicazione di gestione biblioteca.
Implementa un'interfaccia moderna con menu, toolbar e area di lavoro.
"""
def __init__(self, db_manager: DatabaseManager):
"""
Inizializza la finestra principale.
Args:
db_manager: Istanza del DatabaseManager
"""
self.db = db_manager
# Creazione finestra principale
self.root = tk.Tk()
self.root.title("Biblioteca Manager Pro v1.0")
self.root.geometry("1200x700")
self.root.minsize(1000, 600)
# Icona dell'applicazione (se disponibile)
try:
self.root.iconbitmap("icon.ico")
except:
pass
# Stili personalizzati
self.setup_styles()
# Variabili di stato
self.current_view = "libri" # Vista attuale: libri, utenti, prestiti
self.search_term = tk.StringVar()
# Costruzione interfaccia
self.setup_ui()
# Carica dati iniziali
self.refresh_current_view()
def setup_styles(self):
"""Configura stili moderni per l'applicazione"""
style = ttk.Style()
# Usa tema moderno
style.theme_use('clam')
# Stili personalizzati
style.configure('Title.TLabel',
font=('Arial', 16, 'bold'),
foreground='#2c3e50')
style.configure('Header.TLabel',
font=('Arial', 12, 'bold'),
foreground='#34495e')
style.configure('Success.TButton',
font=('Arial', 10, 'bold'),
background='#27ae60',
foreground='white')
style.configure('Primary.TButton',
font=('Arial', 10, 'bold'),
background='#3498db',
foreground='white')
style.configure('Danger.TButton',
font=('Arial', 10, 'bold'),
background='#e74c3c',
foreground='white')
style.configure('Accent.TButton',
font=('Arial', 10, 'bold'),
background='#9b59b6',
foreground='white')
style.configure('Modern.TFrame',
background='#ecf0f1')
# Configura Treeview
style.configure('Treeview',
font=('Arial', 10),
rowheight=25)
style.configure('Treeview.Heading',
font=('Arial', 11, 'bold'),
background='#34495e',
foreground='white')
style.map('Treeview.Heading',
background=[('active', '#2c3e50')])
def setup_ui(self):
"""Costruisce l'interfaccia utente completa"""
# Configura grid principale
self.root.grid_rowconfigure(1, weight=1)
self.root.grid_columnconfigure(0, weight=1)
# 1. BARRA DEL MENU
self.setup_menu_bar()
# 2. BARRA DEGLI STRUMENTI (TOOLBAR)
self.setup_toolbar()
# 3. BARRA DI STATO (STATUSBAR)
self.setup_statusbar()
# 4. AREA DI LAVORO PRINCIPALE
self.setup_main_area()
# 5. BARRA LATERALE
self.setup_sidebar()
def setup_menu_bar(self):
"""Crea la barra del menu principale"""
menubar = tk.Menu(self.root)
self.root.config(menu=menubar)
# Menu File
file_menu = tk.Menu(menubar, tearoff=0)
menubar.add_cascade(label="File", menu=file_menu)
file_menu.add_command(label="Nuovo Libro",
accelerator="Ctrl+N",
command=self.nuovo_libro)
file_menu.add_command(label="Nuovo Utente",
command=self.nuovo_utente)
file_menu.add_separator()
file_menu.add_command(label="Importa CSV...",
command=self.importa_csv)
file_menu.add_command(label="Esporta CSV...",
command=self.esporta_csv)
file_menu.add_separator()
file_menu.add_command(label="Backup Dati",
command=self.backup_dati)
file_menu.add_separator()
file_menu.add_command(label="Esci",
accelerator="Ctrl+Q",
command=self.root.quit)
# Menu Modifica
edit_menu = tk.Menu(menubar, tearoff=0)
menubar.add_cascade(label="Modifica", menu=edit_menu)
edit_menu.add_command(label="Copia",
accelerator="Ctrl+C",
command=self.copia)
edit_menu.add_command(label="Incolla",
accelerator="Ctrl+V",
command=self.incolla)
edit_menu.add_separator()
edit_menu.add_command(label="Preferenze...",
command=self.apri_preferenze)
# Menu Visualizza
view_menu = tk.Menu(menubar, tearoff=0)
menubar.add_cascade(label="Visualizza", menu=view_menu)
view_menu.add_command(label="Libri",
command=lambda: self.cambia_vista("libri"))
view_menu.add_command(label="Utenti",
command=lambda: self.cambia_vista("utenti"))
view_menu.add_command(label="Prestiti",
command=lambda: self.cambia_vista("prestiti"))
view_menu.add_separator()
view_menu.add_command(label="Statistiche",
command=self.mostra_statistiche)
view_menu.add_command(label="Dashboard",
command=self.mostra_dashboard)
# Menu Aiuto
help_menu = tk.Menu(menubar, tearoff=0)
menubar.add_cascade(label="Aiuto", menu=help_menu)
help_menu.add_command(label="Guida",
command=self.apri_guida)
help_menu.add_command(label="Tutorial",
command=self.apri_tutorial)
help_menu.add_separator()
help_menu.add_command(label="Informazioni",
command=self.mostra_info)
# Bind tastiera
self.root.bind("", lambda e: self.nuovo_libro())
self.root.bind("", lambda e: self.root.quit())
def setup_toolbar(self):
"""Crea la barra degli strumenti"""
toolbar = ttk.Frame(self.root, relief="raised", borderwidth=1)
toolbar.grid(row=0, column=0, sticky="ew", padx=2, pady=2)
# Bottoni toolbar
ttk.Button(toolbar, text="📚 Libri",
command=lambda: self.cambia_vista("libri"),
style='Primary.TButton').pack(side="left", padx=2, pady=2)
ttk.Button(toolbar, text="👥 Utenti",
command=lambda: self.cambia_vista("utenti"),
style='Primary.TButton').pack(side="left", padx=2, pady=2)
ttk.Button(toolbar, text="🔄 Prestiti",
command=lambda: self.cambia_vista("prestiti"),
style='Primary.TButton').pack(side="left", padx=2, pady=2)
ttk.Button(toolbar, text="➕ Nuovo",
command=self.nuovo_elemento,
style='Success.TButton').pack(side="left", padx=2, pady=2)
ttk.Button(toolbar, text="✏️ Modifica",
command=self.modifica_elemento,
style='Accent.TButton').pack(side="left", padx=2, pady=2)
ttk.Button(toolbar, text="🗑️ Elimina",
command=self.elimina_elemento,
style='Danger.TButton').pack(side="left", padx=2, pady=2)
ttk.Button(toolbar, text="📊 Report",
command=self.genera_report,
style='Accent.TButton').pack(side="left", padx=2, pady=2)
# Separatore
ttk.Separator(toolbar, orient="vertical").pack(side="left", fill="y", padx=5)
# Barra di ricerca
ttk.Label(toolbar, text="🔍 Cerca:").pack(side="left", padx=(10, 2))
search_entry = ttk.Entry(toolbar, textvariable=self.search_term, width=30)
search_entry.pack(side="left", padx=2, pady=2)
ttk.Button(toolbar, text="Cerca",
command=self.cerca).pack(side="left", padx=2, pady=2)
ttk.Button(toolbar, text="Pulisci",
command=self.pulisci_ricerca).pack(side="left", padx=2, pady=2)
# Bind ricerca con Enter
search_entry.bind("", lambda e: self.cerca())
def setup_statusbar(self):
"""Crea la barra di stato"""
self.statusbar = ttk.Frame(self.root, relief="sunken")
self.statusbar.grid(row=2, column=0, sticky="ew", padx=2, pady=(0, 2))
# Contatori
self.status_libri = ttk.Label(self.statusbar, text="Libri: 0")
self.status_libri.pack(side="left", padx=10)
self.status_utenti = ttk.Label(self.statusbar, text="Utenti: 0")
self.status_utenti.pack(side="left", padx=10)
self.status_prestiti = ttk.Label(self.statusbar, text="Prestiti attivi: 0")
self.status_prestiti.pack(side="left", padx=10)
# Separatore
ttk.Separator(self.statusbar, orient="vertical").pack(side="left", fill="y", padx=5)
# Messaggio di stato
self.status_message = ttk.Label(self.statusbar, text="Pronto")
self.status_message.pack(side="left", padx=10)
# Versione
ttk.Label(self.statusbar, text="v1.0").pack(side="right", padx=10)
# Aggiorna contatori
self.update_status_counters()
def setup_main_area(self):
"""Crea l'area di lavoro principale"""
# Notebook per schede multiple
self.notebook = ttk.Notebook(self.root)
self.notebook.grid(row=1, column=0, sticky="nsew", padx=2, pady=2)
# Scheda Libri
self.frame_libri = ttk.Frame(self.notebook)
self.notebook.add(self.frame_libri, text="📚 Libri")
self.setup_libri_view()
# Scheda Utenti
self.frame_utenti = ttk.Frame(self.notebook)
self.notebook.add(self.frame_utenti, text="👥 Utenti")
self.setup_utenti_view()
# Scheda Prestiti
self.frame_prestiti = ttk.Frame(self.notebook)
self.notebook.add(self.frame_prestiti, text="🔄 Prestiti")
self.setup_prestiti_view()
# Scheda Dashboard
self.frame_dashboard = ttk.Frame(self.notebook)
self.notebook.add(self.frame_dashboard, text="📊 Dashboard")
self.setup_dashboard_view()
def setup_libri_view(self):
"""Configura la vista libri"""
# Frame principale libri
self.frame_libri.grid_rowconfigure(0, weight=1)
self.frame_libri.grid_columnconfigure(0, weight=1)
# Treeview per lista libri
columns = ("ISBN", "Titolo", "Autore", "Genere", "Disponibili", "Totali", "Posizione")
self.tree_libri = ttk.Treeview(self.frame_libri, columns=columns, show="headings", height=20)
# Configura intestazioni
for col in columns:
self.tree_libri.heading(col, text=col)
self.tree_libri.column(col, width=100, minwidth=50)
# Imposta larghezze specifiche
self.tree_libri.column("ISBN", width=120)
self.tree_libri.column("Titolo", width=250)
self.tree_libri.column("Autore", width=150)
# Scrollbar
scrollbar = ttk.Scrollbar(self.frame_libri, orient="vertical", command=self.tree_libri.yview)
self.tree_libri.configure(yscrollcommand=scrollbar.set)
# Posiziona
self.tree_libri.grid(row=0, column=0, sticky="nsew")
scrollbar.grid(row=0, column=1, sticky="ns")
# Frame per dettagli libro
self.frame_dettagli_libro = ttk.LabelFrame(self.frame_libri, text="Dettagli Libro", padding=10)
self.frame_dettagli_libro.grid(row=0, column=2, sticky="nsew", padx=(10, 0))
# Dettagli libro (saranno popolati dinamicamente)
self.dettagli_text = tk.Text(self.frame_dettagli_libro, height=20, width=40, state="disabled")
self.dettagli_text.pack(fill="both", expand=True)
# Bind selezione
self.tree_libri.bind('<>', self.on_libro_selected)
self.tree_libri.bind('', lambda e: self.modifica_libro())
def setup_utenti_view(self):
"""Configura la vista utenti (simile a libri)"""
self.frame_utenti.grid_rowconfigure(0, weight=1)
self.frame_utenti.grid_columnconfigure(0, weight=1)
columns = ("ID", "Nome", "Cognome", "Email", "Telefono", "Tipo", "Iscrizione")
self.tree_utenti = ttk.Treeview(self.frame_utenti, columns=columns, show="headings", height=20)
for col in columns:
self.tree_utenti.heading(col, text=col)
self.tree_utenti.column(col, width=100)
scrollbar = ttk.Scrollbar(self.frame_utenti, orient="vertical", command=self.tree_utenti.yview)
self.tree_utenti.configure(yscrollcommand=scrollbar.set)
self.tree_utenti.grid(row=0, column=0, sticky="nsew")
scrollbar.grid(row=0, column=1, sticky="ns")
self.tree_utenti.bind('<>', self.on_utente_selected)
def setup_prestiti_view(self):
"""Configura la vista prestiti"""
# Creazione frame con due subframe
paned = ttk.PanedWindow(self.frame_prestiti, orient="horizontal")
paned.grid(row=0, column=0, sticky="nsew")
self.frame_prestiti.grid_rowconfigure(0, weight=1)
self.frame_prestiti.grid_columnconfigure(0, weight=1)
# Frame prestiti attivi
frame_attivi = ttk.LabelFrame(paned, text="Prestiti Attivi", padding=10)
paned.add(frame_attivi, weight=1)
columns_attivi = ("ID", "Utente", "Libro", "Data Prestito", "Scadenza", "Giorni Rimasti")
self.tree_prestiti_attivi = ttk.Treeview(frame_attivi, columns=columns_attivi, show="headings", height=15)
for col in columns_attivi:
self.tree_prestiti_attivi.heading(col, text=col)
self.tree_prestiti_attivi.column(col, width=100)
scrollbar_attivi = ttk.Scrollbar(frame_attivi, orient="vertical", command=self.tree_prestiti_attivi.yview)
self.tree_prestiti_attivi.configure(yscrollcommand=scrollbar_attivi.set)
self.tree_prestiti_attivi.pack(side="left", fill="both", expand=True)
scrollbar_attivi.pack(side="right", fill="y")
# Frame prestiti conclusi
frame_conclusi = ttk.LabelFrame(paned, text="Prestiti Conclusi", padding=10)
paned.add(frame_conclusi, weight=1)
columns_conclusi = ("ID", "Utente", "Libro", "Data Prestito", "Data Restituzione", "Stato")
self.tree_prestiti_conclusi = ttk.Treeview(frame_conclusi, columns=columns_conclusi, show="headings", height=15)
for col in columns_conclusi:
self.tree_prestiti_conclusi.heading(col, text=col)
self.tree_prestiti_conclusi.column(col, width=100)
scrollbar_conclusi = ttk.Scrollbar(frame_conclusi, orient="vertical", command=self.tree_prestiti_conclusi.yview)
self.tree_prestiti_conclusi.configure(yscrollcommand=scrollbar_conclusi.set)
self.tree_prestiti_conclusi.pack(side="left", fill="both", expand=True)
scrollbar_conclusi.pack(side="right", fill="y")
def setup_dashboard_view(self):
"""Configura la vista dashboard con statistiche"""
# Questo sarà implementato nella Milestone 5 con Matplotlib
label = ttk.Label(self.frame_dashboard,
text="📊 Dashboard in costruzione...\n\n"
"Questa sezione conterrà grafici e statistiche avanzate.",
font=("Arial", 14),
justify="center")
label.pack(expand=True)
def setup_sidebar(self):
"""Crea la barra laterale (opzionale)"""
# Implementazione facoltativa per esercizio
pass
# ============ METODI DI BUSINESS LOGIC ============
def refresh_current_view(self):
"""Aggiorna la vista corrente"""
if self.current_view == "libri":
self.refresh_libri_view()
elif self.current_view == "utenti":
self.refresh_utenti_view()
elif self.current_view == "prestiti":
self.refresh_prestiti_view()
self.update_status_counters()
def refresh_libri_view(self):
"""Aggiorna la lista libri nel Treeview"""
# Pulisci treeview
for item in self.tree_libri.get_children():
self.tree_libri.delete(item)
# Ottieni tutti i libri
libri = self.db.tutti_libri()
# Aggiungi al treeview
for libro in libri:
disponibile_str = "✅" if libro.disponibile else "❌"
self.tree_libri.insert("", "end", values=(
libro.isbn,
libro.titolo,
libro.autore,
libro.genere,
f"{libro.copie_disponibili}/{libro.copie_totali}",
libro.copie_totali,
libro.posizione
))
def refresh_utenti_view(self):
"""Aggiorna la lista utenti"""
for item in self.tree_utenti.get_children():
self.tree_utenti.delete(item)
# Implementazione simile a refresh_libri_view
# Per esercizio
def refresh_prestiti_view(self):
"""Aggiorna le liste prestiti"""
# Implementazione per esercizio
def update_status_counters(self):
"""Aggiorna i contatori nella statusbar"""
libri_count = len(self.db.tutti_libri())
# utenti_count = ... (implementare)
# prestiti_attivi_count = ... (implementare)
self.status_libri.config(text=f"Libri: {libri_count}")
# self.status_utenti.config(text=f"Utenti: {utenti_count}")
# self.status_prestiti.config(text=f"Prestiti attivi: {prestiti_attivi_count}")
def on_libro_selected(self, event):
"""Gestisce la selezione di un libro"""
selection = self.tree_libri.selection()
if not selection:
return
# Ottieni ISBN dalla riga selezionata
item = self.tree_libri.item(selection[0])
isbn = item['values'][0]
# Recupera libro dal database
libro = self.db.ottieni_libro(isbn)
if not libro:
return
# Mostra dettagli
self.mostra_dettagli_libro(libro)
def mostra_dettagli_libro(self, libro):
"""Mostra i dettagli di un libro nel pannello laterale"""
self.dettagli_text.config(state="normal")
self.dettagli_text.delete(1.0, tk.END)
dettagli = f"""
{'='*40}
DETTAGLI LIBRO
{'='*40}
📚 TITOLO: {libro.titolo}
👤 AUTORE: {libro.autore}
🏷️ ISBN: {libro.isbn}
🏢 EDITORE: {libro.editore}
📅 ANNO: {libro.anno_pubblicazione}
🏷️ GENERE: {libro.genere}
📏 PAGINE: {libro.pagine}
📍 POSIZIONE: {libro.posizione}
🌐 LINGUA: {libro.lingua}
💰 PREZZO: €{libro.prezzo:.2f}
{'='*40}
DISPONIBILITÀ
{'='*40}
📊 Copie totali: {libro.copie_totali}
✅ Copie disponibili: {libro.copie_disponibili}
📈 Percentuale disponibile: {libro.percentuale_disponibile:.1f}%
{'='*40}
STATO: {"✅ DISPONIBILE" if libro.disponibile else "❌ NON DISPONIBILE"}
{'='*40}
📝 NOTE:
{libro.note if libro.note else "Nessuna nota"}
"""
self.dettagli_text.insert(1.0, dettagli)
self.dettagli_text.config(state="disabled")
# ============ METODI DI AZIONE ============
def nuovo_libro(self):
"""Apre la finestra per aggiungere un nuovo libro"""
from .dialogs import LibroDialog
dialog = LibroDialog(self.root, self.db)
self.root.wait_window(dialog.top)
if dialog.result:
self.refresh_libri_view()
self.update_status_counters()
self.set_status_message("Libro aggiunto con successo!")
def modifica_libro(self):
"""Apre la finestra per modificare il libro selezionato"""
selection = self.tree_libri.selection()
if not selection:
messagebox.showwarning("Attenzione", "Seleziona un libro da modificare")
return
item = self.tree_libri.item(selection[0])
isbn = item['values'][0]
libro = self.db.ottieni_libro(isbn)
if not libro:
return
from .dialogs import LibroDialog
dialog = LibroDialog(self.root, self.db, libro=libro)
self.root.wait_window(dialog.top)
if dialog.result:
self.refresh_libri_view()
self.set_status_message("Libro modificato con successo!")
def elimina_libro(self):
"""Elimina il libro selezionato dopo conferma"""
selection = self.tree_libri.selection()
if not selection:
messagebox.showwarning("Attenzione", "Seleziona un libro da eliminare")
return
item = self.tree_libri.item(selection[0])
isbn = item['values'][0]
titolo = item['values'][1]
# Conferma
if not messagebox.askyesno("Conferma eliminazione",
f"Sei sicuro di voler eliminare il libro:\n\n"
f"'{titolo}'\n\n"
f"Questa azione non può essere annullata."):
return
# Elimina
success = self.db.elimina_libro(isbn)
if success:
self.refresh_libri_view()
self.update_status_counters()
self.set_status_message(f"Libro '{titolo}' eliminato con successo!")
else:
messagebox.showerror("Errore",
"Impossibile eliminare il libro.\n"
"Potrebbe avere prestiti attivi.")
def nuovo_utente(self):
"""Apre finestra per nuovo utente"""
from .dialogs import UtenteDialog
dialog = UtenteDialog(self.root, self.db)
self.root.wait_window(dialog.top)
if dialog.result:
self.refresh_utenti_view()
self.set_status_message("Utente aggiunto con successo!")
def cambia_vista(self, vista: str):
"""Cambia la vista corrente"""
self.current_view = vista
# Seleziona la scheda corrispondente nel notebook
if vista == "libri":
self.notebook.select(self.frame_libri)
elif vista == "utenti":
self.notebook.select(self.frame_utenti)
elif vista == "prestiti":
self.notebook.select(self.frame_prestiti)
elif vista == "dashboard":
self.notebook.select(self.frame_dashboard)
self.refresh_current_view()
def cerca(self):
"""Esegue la ricerca in base al termine inserito"""
term = self.search_term.get().strip()
if not term:
self.refresh_current_view()
return
# Implementazione ricerca per esercizio
self.set_status_message(f"Risultati ricerca per: '{term}'")
def pulisci_ricerca(self):
"""Pulisce il campo di ricerca"""
self.search_term.set("")
self.refresh_current_view()
self.set_status_message("Ricerca pulita")
def nuovo_elemento(self):
"""Crea un nuovo elemento in base alla vista corrente"""
if self.current_view == "libri":
self.nuovo_libro()
elif self.current_view == "utenti":
self.nuovo_utente()
elif self.current_view == "prestiti":
# Nuovo prestito
pass
def modifica_elemento(self):
"""Modifica l'elemento selezionato"""
if self.current_view == "libri":
self.modifica_libro()
elif self.current_view == "utenti":
# Modifica utente
pass
elif self.current_view == "prestiti":
# Modifica prestito
pass
def elimina_elemento(self):
"""Elimina l'elemento selezionato"""
if self.current_view == "libri":
self.elimina_libro()
elif self.current_view == "utenti":
# Elimina utente
pass
elif self.current_view == "prestiti":
# Elimina prestito
pass
def genera_report(self):
"""Genera un report PDF/CSV"""
# Implementazione per esercizio
self.set_status_message("Generazione report in corso...")
def mostra_statistiche(self):
"""Mostra le statistiche generali"""
stats = self.db.statistiche_libri()
if not stats:
messagebox.showinfo("Statistiche", "Nessun dato disponibile")
return
message = f"""
📊 STATISTICHE BIBLIOTECA
{'='*30}
📚 Totale libri: {stats.get('totali', 0)}
✅ Disponibili: {stats.get('disponibili', 0)}
❌ In prestito: {stats.get('non_disponibili', 0)}
📈 Percentuale disponibili: {stats.get('percentuale_disponibili', 0):.1f}%
📖 Copie totali: {stats.get('copie_totali', 0)}
📗 Copie disponibili: {stats.get('copie_disponibili', 0)}
🏷️ Generi principali:
"""
for genere, count in list(stats.get('generi', {}).items())[:5]:
message += f" • {genere}: {count} libri\n"
messagebox.showinfo("Statistiche Biblioteca", message)
def mostra_dashboard(self):
"""Mostra la dashboard con grafici"""
self.cambia_vista("dashboard")
# Qui si integrerà Matplotlib nella Milestone 5
def backup_dati(self):
"""Esegue il backup dei dati"""
success = self.db.backup_dati()
if success:
self.set_status_message("Backup completato con successo!")
messagebox.showinfo("Backup", "Backup dei dati completato con successo.")
else:
messagebox.showerror("Errore", "Impossibile completare il backup.")
def importa_csv(self):
"""Importa dati da CSV"""
# Implementazione per esercizio
pass
def esporta_csv(self):
"""Esporta dati in CSV"""
if self.current_view == "libri":
path = self.db.esporta_csv("libri")
if path:
self.set_status_message(f"Dati esportati in: {path}")
messagebox.showinfo("Esportazione", f"Libri esportati in:\n{path}")
else:
messagebox.showerror("Errore", "Impossibile esportare i dati.")
# Implementa per altre viste
def apri_preferenze(self):
"""Apre la finestra delle preferenze"""
# Implementazione per esercizio
pass
def apri_guida(self):
"""Apre la guida in linea"""
webbrowser.open("https://github.com/biblioteca-manager/guida")
def apri_tutorial(self):
"""Apre il tutorial"""
messagebox.showinfo("Tutorial",
"Tutorial in costruzione...\n\n"
"Usa i menu e i pulsanti per esplorare l'applicazione.")
def mostra_info(self):
"""Mostra informazioni sull'applicazione"""
info = f"""
📚 BIBLIOTECA MANAGER PRO
Versione 1.0
Un sistema completo per la gestione di biblioteche
e librerie personali.
Sviluppato con:
• Python 3.8+
• Tkinter per l'interfaccia grafica
• JSON per la persistenza dati
• Matplotlib per le visualizzazioni
Autore: Classe Terza - Indirizzo Informatica
Anno Scolastico: 2024-2025
Licenza: Educativa - Solo per scopi didattici
"""
messagebox.showinfo("Informazioni", info)
def copia(self):
"""Copia il testo selezionato"""
# Implementazione base
try:
self.root.clipboard_clear()
self.root.clipboard_append("Copia non implementata")
except:
pass
def incolla(self):
"""Incolla dalla clipboard"""
# Implementazione base
pass
def set_status_message(self, message: str):
"""Imposta il messaggio nella statusbar"""
self.status_message.config(text=message)
def run(self):
"""Avvia l'applicazione"""
self.set_status_message("Applicazione avviata - Pronto")
self.root.mainloop()