SXXXXXXX_FlightMonitor/flightmonitor/controller/cleanup_manager.py

160 lines
6.9 KiB
Python

# FlightMonitor/controller/cleanup_manager.py
"""
Manages the orderly shutdown and cleanup of application resources,
including closing database connections, stopping background threads,
and destroying secondary GUI windows upon application exit or specific events.
"""
from typing import Any, Optional, TYPE_CHECKING
from ..utils.logger import get_logger
# Type checking imports to avoid circular dependencies at runtime
if TYPE_CHECKING:
from flightmonitor.controller.app_controller import AppController
from flightmonitor.data.storage import DataStorage
from flightmonitor.data.aircraft_database_manager import AircraftDatabaseManager
from flightmonitor.gui.main_window import MainWindow
from flightmonitor.gui.dialogs.full_flight_details_window import (
FullFlightDetailsWindow,
)
from flightmonitor.map.map_canvas_manager import MapCanvasManager
module_logger = get_logger(__name__)
class CleanupManager:
"""
Handles all application shutdown and resource cleanup operations.
It orchestrates the closing of various modules and components.
"""
def __init__(self, app_controller: "AppController"):
"""
Initializes the CleanupManager.
Args:
app_controller: The main AppController instance, providing access
to all application components that need cleanup.
"""
self.app_controller = app_controller
module_logger.debug("CleanupManager initialized.")
def on_application_exit(self):
"""
Performs a coordinated shutdown of all application resources.
This method is called when the main application window is closing.
"""
module_logger.info(
"CleanupManager: Application exit requested. Cleaning up resources."
)
# --- Close active Full Flight Details window (if any) ---
if (
self.app_controller.active_detail_window_ref
and self.app_controller.active_detail_window_ref.winfo_exists()
):
try:
module_logger.info(
f"CleanupManager: Closing active detail window for {self.app_controller.active_detail_window_icao} on app exit."
)
self.app_controller.active_detail_window_ref.destroy()
except Exception as e_close_detail:
module_logger.error(
f"CleanupManager: Error closing detail window on app exit: {e_close_detail}"
)
finally:
self.app_controller.active_detail_window_ref = None
self.app_controller.active_detail_window_icao = None
# --- Shutdown MapCanvasManager worker (if active) ---
main_window = self.app_controller.main_window
if (
main_window
and hasattr(main_window, "map_manager_instance")
and main_window.map_manager_instance is not None
):
map_manager: "MapCanvasManager" = main_window.map_manager_instance
if hasattr(map_manager, "shutdown_worker") and callable(
map_manager.shutdown_worker
):
try:
map_manager.shutdown_worker()
module_logger.info(
"CleanupManager: Main MapCanvasManager worker shutdown requested."
)
except Exception as e_map_shutdown:
module_logger.error(
f"CleanupManager: Error during Main MapCanvasManager worker shutdown: {e_map_shutdown}",
exc_info=True,
)
# --- Stop live monitoring (adapter thread and data processor) ---
is_adapter_considered_running = (
self.app_controller.live_adapter_thread
and self.app_controller.live_adapter_thread.is_alive()
) or self.app_controller.is_live_monitoring_active
if is_adapter_considered_running:
module_logger.info(
"CleanupManager: Live monitoring is active, requesting AppController to stop it."
)
self.app_controller.stop_live_monitoring(from_error=False)
# --- Close DataStorage connection pool ---
if self.app_controller.data_storage:
try:
self.app_controller.data_storage.close_all_connections()
module_logger.info("CleanupManager: DataStorage connection pool closed.")
except Exception as e_db_close:
module_logger.error(
f"CleanupManager: Error closing DataStorage pool: {e_db_close}",
exc_info=True,
)
finally:
self.app_controller.data_storage = None
# --- Close AircraftDatabaseManager connection ---
if self.app_controller.aircraft_db_manager:
try:
self.app_controller.aircraft_db_manager.close_connection()
module_logger.info(
"CleanupManager: AircraftDatabaseManager connection closed."
)
except Exception as e_ac_db_close:
module_logger.error(
f"CleanupManager: Error closing AircraftDatabaseManager: {e_ac_db_close}",
exc_info=True,
)
finally:
self.app_controller.aircraft_db_manager = None
module_logger.info("CleanupManager: Cleanup on application exit finished.")
def details_window_closed(self, closed_icao24: str):
"""
Handles the event when a full flight details window is closed.
Clears the AppController's references to the closed window if it was the active one.
Args:
closed_icao24: The ICAO24 of the flight whose details window was closed.
"""
normalized_closed_icao24 = closed_icao24.lower().strip()
if self.app_controller.active_detail_window_icao == normalized_closed_icao24:
module_logger.info(
f"CleanupManager: Detail window for {normalized_closed_icao24} reported closed. Clearing references in AppController."
)
self.app_controller.active_detail_window_ref = None
self.app_controller.active_detail_window_icao = None
main_window = self.app_controller.main_window
if (
main_window
and hasattr(main_window, "full_flight_details_window")
and main_window.full_flight_details_window
and not main_window.full_flight_details_window.winfo_exists()
):
main_window.full_flight_details_window = None
else:
module_logger.debug(
f"CleanupManager: A detail window for {normalized_closed_icao24} closed, but it was not the currently tracked active one ({self.app_controller.active_detail_window_icao}). No action on active_detail references."
)