SXXXXXXX_CppPythonDebug/cpp_python_debug/__main__.py
2025-06-09 10:52:43 +02:00

199 lines
8.0 KiB
Python

# File: cpp_python_debug/__main__.py
# Main entry point for the Cpp-Python Debug Helper application.
# This script initializes logging and starts the Tkinter GUI.
import logging
import sys
import os
# import pathlib # pathlib non è strettamente necessario qui se usiamo os.path per coerenza
# Import assoluti
from cpp_python_debug.gui.main_window import GDBGui
from cpp_python_debug.core.frozen_utils import get_app_base_path
# AppSettings non è più importato qui direttamente, GDBGui lo istanzierà.
# --- Application Constants ---
# Questi potrebbero essere definiti in un _version.py del pacchetto cpp_python_debug
# o essere statici qui.
APP_INTERNAL_NAME_FOR_PATHS = "CppPythonDebugHelper" # Nome breve per directory, ecc.
APP_DISPLAY_NAME = "Cpp-Python GDB Debug Helper"
APP_VERSION_FROM_MAIN = "1.0.1" # Versione gestita qui o da _version.py
# --- Percorsi Base e Log ---
APP_BASE_PATH = get_app_base_path() # Determina il percorso base dell'applicazione
LOG_DIR_NAME = "logs" # Nome della sottocartella per tutti i log
# Path assoluto alla directory dei log dell'applicazione
# Viene creato se non esiste.
LOG_DIRECTORY_PATH: str
try:
_potential_log_dir = os.path.join(APP_BASE_PATH, LOG_DIR_NAME)
os.makedirs(_potential_log_dir, exist_ok=True)
LOG_DIRECTORY_PATH = _potential_log_dir
except OSError as e:
# Fallback critico se non possiamo creare la directory di log primaria
print(
f"ERROR: Could not create primary log directory '{_potential_log_dir}': {e}",
file=sys.stderr,
)
user_home = os.path.expanduser("~")
fallback_log_dir = os.path.join(user_home, f".{APP_INTERNAL_NAME_FOR_PATHS}_logs")
try:
os.makedirs(fallback_log_dir, exist_ok=True)
print(
f"WARNING: Using fallback log directory: {fallback_log_dir}",
file=sys.stderr,
)
LOG_DIRECTORY_PATH = fallback_log_dir
except Exception as e_fb:
print(
f"CRITICAL ERROR: Could not create any log directory. Primary failed, Fallback failed: {e_fb}. Logging to CWD.",
file=sys.stderr,
)
LOG_DIRECTORY_PATH = os.getcwd() # Ultima risorsa disperata
# Percorso per il log specifico del dumper GDB (quello che __main__ cancella all'avvio)
# Questo è il log prodotto dallo *script precedente* gdb_dumper.py, non il suo log interno.
# Il *nuovo* gdb_dumper.py scriverà il suo log interno (gdb_dumper_script_internal.log)
# in LOG_DIRECTORY_PATH se gli viene detto dalla GDBSession.
GDB_DUMPER_LEGACY_LOG_FILENAME = (
"gdb_dumper_debug.log" # Nome del vecchio file di log del dumper
)
GDB_DUMPER_LOG_TO_DELETE = os.path.join(
LOG_DIRECTORY_PATH, GDB_DUMPER_LEGACY_LOG_FILENAME
)
def setup_global_logging():
"""
Configures basic logging for the application.
Logs to a file in LOG_DIRECTORY_PATH and to console.
"""
log_level = logging.DEBUG # Configura il livello di log desiderato
# Nome del file di log principale della GUI
main_gui_log_filename = f"{APP_INTERNAL_NAME_FOR_PATHS.lower()}_gui.log"
main_app_log_filepath = os.path.join(LOG_DIRECTORY_PATH, main_gui_log_filename)
# Configurazione base del logging
logging.basicConfig(
level=log_level,
format="%(asctime)s - %(name)-35s - %(levelname)-8s - %(message)s", # Aumentato padding per nome modulo
datefmt="%Y-%m-%d %H:%M:%S",
handlers=[
logging.FileHandler(main_app_log_filepath, mode="a", encoding="utf-8"),
logging.StreamHandler(sys.stdout), # Output anche su console
],
)
# Ottieni un logger per questo modulo (__main__) per i log iniziali
logger = logging.getLogger(
__name__
) # Equivalente a logging.getLogger("cpp_python_debug.__main__")
logger.info(
f"Global logging initialized. Log level set to: {logging.getLevelName(log_level)}."
)
logger.info(f"Application Base Path determined as: {APP_BASE_PATH}")
logger.info(f"Logging directory for all logs: {LOG_DIRECTORY_PATH}")
logger.info(f"Main GUI application log file: {main_app_log_filepath}")
# Tentativo di cancellare il vecchio log del dumper (se esiste)
# Questo si riferisce al file gdb_dumper_debug.log che il vecchio dumper scriveva.
# Il nuovo dumper scriverà gdb_dumper_script_internal.log nella stessa LOG_DIRECTORY_PATH.
if GDB_DUMPER_LOG_TO_DELETE and os.path.exists(GDB_DUMPER_LOG_TO_DELETE):
try:
os.remove(GDB_DUMPER_LOG_TO_DELETE)
logger.info(
f"Attempted to delete legacy GDB dumper log: {GDB_DUMPER_LOG_TO_DELETE} - Success."
)
except OSError as e_remove: # Più specifico di Exception
logger.warning(
f"Could not delete legacy GDB dumper log '{GDB_DUMPER_LOG_TO_DELETE}': {e_remove}"
)
else:
logger.info(
f"Legacy GDB dumper log not found (no previous log to delete): {GDB_DUMPER_LOG_TO_DELETE}"
)
logger.info(f"Starting {APP_DISPLAY_NAME} v{APP_VERSION_FROM_MAIN}")
def main():
"""
Main function to set up logging and launch the GDB GUI.
"""
# setup_global_logging() deve essere chiamato prima di qualsiasi altro log
# ma dopo che LOG_DIRECTORY_PATH è stato determinato.
# LOG_DIRECTORY_PATH è ora determinato a livello di modulo.
setup_global_logging()
app_instance_logger = logging.getLogger(
APP_INTERNAL_NAME_FOR_PATHS
) # Logger generico per l'app
if getattr(sys, "frozen", False):
app_instance_logger.info(
f"Application is running in a 'frozen' (compiled) environment."
)
app_instance_logger.info(f"Executable path: {sys.executable}")
if hasattr(sys, "_MEIPASS"): # Solo per one-file mode
app_instance_logger.info(
f"_MEIPASS temporary bundle directory: {sys._MEIPASS}"
)
else:
app_instance_logger.info(
f"Application is running in development mode (not frozen)."
)
# __file__ per __main__ quando eseguito con -m è il percorso di __main__.py
# Se eseguito come script diretto, è il percorso dello script.
app_instance_logger.info(
f"Main script __file__ location: {globals().get('__file__', 'N/A')}"
)
try:
app_instance_logger.info("Creating GDBGui instance...")
# --- MODIFICA: Passa APP_BASE_PATH e LOG_DIRECTORY_PATH a GDBGui ---
app = GDBGui(app_base_path=APP_BASE_PATH, log_directory_path=LOG_DIRECTORY_PATH)
# --- FINE MODIFICA ---
app_instance_logger.info("Starting Tkinter main event loop.")
app.mainloop()
app_instance_logger.info("Tkinter main event loop finished.")
except Exception as e:
app_instance_logger.critical(
f"An unhandled critical error occurred in main: {e}", exc_info=True
)
try:
# Tenta di mostrare un messagebox di errore
import tkinter as tk
from tkinter import messagebox
root_for_error = None
if not tk._default_root: # type: ignore # Evita di creare un root se uno esiste già da un'eccezione in Tk
root_for_error = tk.Tk()
root_for_error.withdraw() # Nascondi la finestra root extra
messagebox.showerror(
"Critical Application Error",
f"A critical error occurred:\n{e}\n\nPlease check logs in '{LOG_DIRECTORY_PATH}' for details.",
)
if root_for_error:
root_for_error.destroy()
except Exception as e_tk_critical:
# Se anche Tkinter fallisce, logga sulla console di emergenza (stderr)
print(
f"CRITICAL_TKINTER_ERROR: Could not display error messagebox: {e_tk_critical}",
file=sys.stderr,
)
print(f"Original critical error was: {e}", file=sys.stderr)
finally:
app_instance_logger.info(f"{APP_DISPLAY_NAME} is shutting down.")
logging.shutdown() # Chiude tutti gli handler di logging in modo pulito
if __name__ == "__main__":
main()