# 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()