add db size e map tile size on mantainance dialog

This commit is contained in:
VALLONGOL 2025-06-17 08:29:04 +02:00
parent 95d74ceb6b
commit 9851a5bd0b
4 changed files with 121 additions and 9 deletions

View File

@ -1051,6 +1051,48 @@ class AppController:
if self.aircraft_db_manager: if self.aircraft_db_manager:
return self.aircraft_db_manager.delete_scan_session(scan_id) return self.aircraft_db_manager.delete_scan_session(scan_id)
return False return False
def get_aircraft_database_size_info(self) -> str:
"""
Retrieves the size of the aircraft database as a formatted string.
Returns:
A string representing the size (e.g., "15.2 MB") or "N/A".
"""
if self.aircraft_db_manager:
size_bytes = self.aircraft_db_manager.get_database_size_bytes()
if size_bytes < 1024:
return f"{size_bytes} Bytes"
elif size_bytes < 1024**2:
return f"{size_bytes / 1024:.2f} KB"
elif size_bytes < 1024**3:
return f"{size_bytes / 1024**2:.2f} MB"
else:
return f"{size_bytes / 1024**3:.2f} GB"
return "N/A"
def get_map_tile_cache_size_info(self) -> str:
"""
Retrieves the size of the map tile cache as a formatted string.
Returns:
A string representing the size (e.g., "50.7 MB") or "N/A".
"""
if (
self.main_window
and self.main_window.map_manager_instance
and self.main_window.map_manager_instance.tile_manager
):
size_bytes = self.main_window.map_manager_instance.tile_manager.get_cache_size_bytes()
if size_bytes < 1024:
return f"{size_bytes} Bytes"
elif size_bytes < 1024**2:
return f"{size_bytes / 1024:.2f} KB"
elif size_bytes < 1024**3:
return f"{size_bytes / 1024**2:.2f} MB"
else:
return f"{size_bytes / 1024**3:.2f} GB"
return "N/A"
def clear_aircraft_database(self) -> bool: def clear_aircraft_database(self) -> bool:
"""Clears the aircraft details table.""" """Clears the aircraft details table."""

View File

@ -720,4 +720,19 @@ class AircraftDatabaseManager:
elif self.conn and threading.get_ident() != self._main_thread_id: elif self.conn and threading.get_ident() != self._main_thread_id:
logger.warning( logger.warning(
f"Attempt to close main connection from non-main thread ({threading.get_ident()}). Ignored." f"Attempt to close main connection from non-main thread ({threading.get_ident()}). Ignored."
) )
def get_database_size_bytes(self) -> int:
"""
Calculates and returns the size of the main aircraft database file in bytes.
Returns:
int: The size of the database file in bytes. Returns 0 if it doesn't exist.
"""
try:
if os.path.exists(self.db_path):
return os.path.getsize(self.db_path)
except OSError as e:
logger.error(f"Could not get size of database file {self.db_path}: {e}")
return 0

View File

@ -33,7 +33,11 @@ class MaintenanceWindow(tk.Toplevel):
self.geometry("800x600") self.geometry("800x600")
self.minsize(700, 500) self.minsize(700, 500)
# Widget references # --- Tkinter Variables for dynamic labels ---
self.db_size_var = tk.StringVar(value="Calculating...")
self.cache_size_var = tk.StringVar(value="Calculating...")
# --- Widget References ---
self.recordings_tree: Optional[ttk.Treeview] = None self.recordings_tree: Optional[ttk.Treeview] = None
self.sessions_tree: Optional[ttk.Treeview] = None self.sessions_tree: Optional[ttk.Treeview] = None
@ -56,6 +60,7 @@ class MaintenanceWindow(tk.Toplevel):
"""Initial population of all data tabs.""" """Initial population of all data tabs."""
self._populate_recordings_tab() self._populate_recordings_tab()
self._populate_sessions_tab() self._populate_sessions_tab()
self._populate_general_tab()
def _create_recordings_tab(self, notebook: ttk.Notebook): def _create_recordings_tab(self, notebook: ttk.Notebook):
"""Creates the tab for managing daily recording database files.""" """Creates the tab for managing daily recording database files."""
@ -238,19 +243,43 @@ class MaintenanceWindow(tk.Toplevel):
container = ttk.Frame(notebook, padding="10") container = ttk.Frame(notebook, padding="10")
notebook.add(container, text="General Maintenance") notebook.add(container, text="General Maintenance")
ac_db_frame = ttk.LabelFrame(container, text="Aircraft Database", padding=10) status_frame = ttk.LabelFrame(container, text="Storage & Cache Status", padding=10)
ac_db_frame.pack(fill=tk.X, pady=(0, 10)) status_frame.pack(fill=tk.X, pady=(0, 10))
ttk.Button(ac_db_frame, text="Clear Entire Aircraft Database...", command=self._clear_aircraft_db).pack(pady=5) status_frame.columnconfigure(1, weight=1)
ttk.Button(ac_db_frame, text="Clear Scan History...", command=self._clear_scan_history).pack(pady=5)
ttk.Label(status_frame, text="Aircraft DB Size:").grid(row=0, column=0, sticky="w", padx=(0, 5))
ttk.Label(status_frame, textvariable=self.db_size_var).grid(row=0, column=1, sticky="w")
ttk.Label(status_frame, text="Map Cache Size:").grid(row=1, column=0, sticky="w", padx=(0, 5), pady=(5,0))
ttk.Label(status_frame, textvariable=self.cache_size_var).grid(row=1, column=1, sticky="w", pady=(5,0))
ttk.Button(status_frame, text="Refresh Sizes", command=self._populate_general_tab).grid(row=0, column=2, rowspan=2, padx=(20,0))
map_cache_frame = ttk.LabelFrame(container, text="Map Tile Cache", padding=10) ac_db_frame = ttk.LabelFrame(container, text="Aircraft Database Actions", padding=10)
ac_db_frame.pack(fill=tk.X, pady=(0, 10))
ttk.Button(ac_db_frame, text="Clear Entire Aircraft Database...", command=self._clear_aircraft_db).pack(pady=5, anchor="w")
ttk.Button(ac_db_frame, text="Clear Scan History...", command=self._clear_scan_history).pack(pady=5, anchor="w")
map_cache_frame = ttk.LabelFrame(container, text="Map Cache Actions", padding=10)
map_cache_frame.pack(fill=tk.X, pady=(0, 10)) map_cache_frame.pack(fill=tk.X, pady=(0, 10))
ttk.Button(map_cache_frame, text="Clear Map Tile Cache...", command=self._clear_map_cache).pack(pady=5) ttk.Button(map_cache_frame, text="Clear Map Tile Cache...", command=self._clear_map_cache).pack(pady=5, anchor="w")
def _populate_general_tab(self):
"""Fetches and displays the storage and cache sizes."""
if not self.controller:
return
db_size_str = self.controller.get_aircraft_database_size_info()
self.db_size_var.set(db_size_str)
cache_size_str = self.controller.get_map_tile_cache_size_info()
self.cache_size_var.set(cache_size_str)
def _clear_aircraft_db(self): def _clear_aircraft_db(self):
if messagebox.askyesno("Confirm Action", "Are you sure you want to delete ALL records from the aircraft database? This action cannot be undone.", parent=self): if messagebox.askyesno("Confirm Action", "Are you sure you want to delete ALL records from the aircraft database? This action cannot be undone.", parent=self):
if self.controller and self.controller.clear_aircraft_database(): if self.controller and self.controller.clear_aircraft_database():
messagebox.showinfo("Success", "Aircraft database has been cleared.", parent=self) messagebox.showinfo("Success", "Aircraft database has been cleared.", parent=self)
self._populate_general_tab() # Refresh size display
else: else:
messagebox.showerror("Error", "Failed to clear the aircraft database.", parent=self) messagebox.showerror("Error", "Failed to clear the aircraft database.", parent=self)
@ -265,6 +294,7 @@ class MaintenanceWindow(tk.Toplevel):
if messagebox.askyesno("Confirm Action", "Are you sure you want to delete all cached map tiles? They will be re-downloaded as needed.", parent=self): if messagebox.askyesno("Confirm Action", "Are you sure you want to delete all cached map tiles? They will be re-downloaded as needed.", parent=self):
if self.controller and self.controller.clear_map_tile_cache(): if self.controller and self.controller.clear_map_tile_cache():
messagebox.showinfo("Success", "Map tile cache has been cleared.", parent=self) messagebox.showinfo("Success", "Map tile cache has been cleared.", parent=self)
self._populate_general_tab() # Refresh size display
else: else:
messagebox.showerror("Error", "Failed to clear the map tile cache.", parent=self) messagebox.showerror("Error", "Failed to clear the map tile cache.", parent=self)

View File

@ -954,3 +954,28 @@ class MapTileManager:
logger.exception( logger.exception(
f"Unexpected error clearing cache '{self.service_specific_cache_dir}': {e_clear_unexpected}" f"Unexpected error clearing cache '{self.service_specific_cache_dir}': {e_clear_unexpected}"
) )
def get_cache_size_bytes(self) -> int:
"""
Calculates and returns the total size of the cache directory for this service in bytes.
Returns:
int: The total size of the cache in bytes. Returns 0 if cache does not exist or is empty.
"""
total_size = 0
cache_dir = self.service_specific_cache_dir
if not cache_dir.exists():
return 0
try:
for dirpath, dirnames, filenames in os.walk(cache_dir):
for f in filenames:
fp = os.path.join(dirpath, f)
# skip if it is symbolic link
if not os.path.islink(fp):
total_size += os.path.getsize(fp)
except OSError as e:
logger.error(f"Could not calculate size of cache directory {cache_dir}: {e}")
return 0
return total_size