155 lines
7.3 KiB
Python
155 lines
7.3 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 .app_controller import AppController
|
|
from ..data.storage import DataStorage
|
|
from ..data.aircraft_database_manager import AircraftDatabaseManager
|
|
from ..gui.main_window import MainWindow
|
|
from ..gui.dialogs.full_flight_details_window import FullFlightDetailsWindow
|
|
from ..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) ---
|
|
# Access active_detail_window_ref and active_detail_window_icao via app_controller
|
|
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:
|
|
# Clear references in AppController directly or via a method
|
|
self.app_controller.active_detail_window_ref = None
|
|
self.app_controller.active_detail_window_icao = None
|
|
|
|
# --- Shutdown MapCanvasManager worker (if active) ---
|
|
# Access map_manager_instance via app_controller.main_window
|
|
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) ---
|
|
# Access live_adapter_thread, is_live_monitoring_active via app_controller
|
|
# Access stop_live_monitoring via app_controller
|
|
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 ---
|
|
# Access data_storage via app_controller
|
|
if self.app_controller.data_storage:
|
|
try:
|
|
self.app_controller.data_storage.close_connection()
|
|
module_logger.info("CleanupManager: DataStorage connection closed.")
|
|
except Exception as e_db_close:
|
|
module_logger.error(
|
|
f"CleanupManager: Error closing DataStorage: {e_db_close}", exc_info=True
|
|
)
|
|
finally:
|
|
self.app_controller.data_storage = None # Clear reference in AppController
|
|
|
|
# --- Close AircraftDatabaseManager connection ---
|
|
# Access aircraft_db_manager via app_controller
|
|
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 # Clear reference in AppController
|
|
|
|
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()
|
|
|
|
# Access active_detail_window_icao and active_detail_window_ref via app_controller
|
|
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
|
|
# Also clear MainWindow's convenience reference if it matches (accessed via app_controller)
|
|
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()
|
|
): # Check if already destroyed by Tkinter
|
|
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."
|
|
) |