""" Export Window for TheChart Application Provides a GUI interface for exporting data and graphs to various formats. """ import tkinter as tk from pathlib import Path from tkinter import filedialog, messagebox, ttk from export_manager import ExportManager class ExportWindow: """Export window for data and graph export functionality.""" def __init__(self, parent: tk.Tk, export_manager: ExportManager) -> None: self.parent = parent self.export_manager = export_manager # Create the export window self.window = tk.Toplevel(parent) self.window.title("Export Data") self.window.geometry("500x450") # Made taller to ensure buttons are visible self.window.resizable(False, False) # Center the window self._center_window() # Make window modal self.window.transient(parent) self.window.grab_set() # Setup the UI self._setup_ui() def _center_window(self) -> None: """Center the export window on the parent window.""" self.window.update_idletasks() # Get window dimensions width = self.window.winfo_width() height = self.window.winfo_height() # Get parent window position and size parent_x = self.parent.winfo_rootx() parent_y = self.parent.winfo_rooty() parent_width = self.parent.winfo_width() parent_height = self.parent.winfo_height() # Calculate position to center on parent x = parent_x + (parent_width // 2) - (width // 2) y = parent_y + (parent_height // 2) - (height // 2) self.window.geometry(f"{width}x{height}+{x}+{y}") def _setup_ui(self) -> None: """Setup the export window UI.""" # Main frame main_frame = ttk.Frame(self.window, padding="15") main_frame.pack(fill=tk.BOTH, expand=True) # Title title_label = ttk.Label( main_frame, text="Export Data & Graphs", font=("Arial", 14, "bold") ) title_label.pack(pady=(0, 15)) # Create scrollable content area for the main content content_frame = ttk.Frame(main_frame) content_frame.pack(fill=tk.BOTH, expand=True) # Export info section self._create_info_section(content_frame) # Export options section self._create_options_section(content_frame) # Buttons section - always at the bottom self._create_buttons_section(main_frame) def _create_info_section(self, parent: ttk.Frame) -> None: """Create the data information section.""" info_frame = ttk.LabelFrame(parent, text="Data Summary", padding="10") info_frame.pack(fill=tk.X, pady=(0, 20)) # Get export info export_info = self.export_manager.get_export_info() # Display information if export_info["has_data"]: info_text = f"""Total Entries: {export_info["total_entries"]} Date Range: {export_info["date_range"]["start"]} to {export_info["date_range"]["end"]} Pathologies: {", ".join(export_info["pathologies"])} Medicines: {", ".join(export_info["medicines"])}""" else: info_text = "No data available for export." info_label = ttk.Label(info_frame, text=info_text, justify=tk.LEFT) info_label.pack(anchor=tk.W) def _create_options_section(self, parent: ttk.Frame) -> None: """Create the export options section.""" options_frame = ttk.LabelFrame(parent, text="Export Options", padding="10") options_frame.pack(fill=tk.X, pady=(0, 20)) # Include graph option (for PDF export) self.include_graph_var = tk.BooleanVar(value=True) graph_check = ttk.Checkbutton( options_frame, text="Include graph in PDF export", variable=self.include_graph_var, ) graph_check.pack(anchor=tk.W, pady=(0, 10)) # Format selection format_label = ttk.Label(options_frame, text="Export Format:") format_label.pack(anchor=tk.W) self.format_var = tk.StringVar(value="JSON") formats = ["JSON", "XML", "PDF"] for fmt in formats: radio = ttk.Radiobutton( options_frame, text=fmt, variable=self.format_var, value=fmt ) radio.pack(anchor=tk.W, padx=(20, 0)) def _create_buttons_section(self, parent: ttk.Frame) -> None: """Create the buttons section.""" # Add a separator for visual clarity separator = ttk.Separator(parent, orient="horizontal") separator.pack(fill=tk.X, pady=(10, 10)) button_frame = ttk.Frame(parent) button_frame.pack(fill=tk.X, pady=(0, 10)) # Export button with more prominent styling export_btn = ttk.Button( button_frame, text="Export...", command=self._handle_export ) export_btn.pack(side=tk.LEFT, padx=(10, 10), pady=5) # Cancel button cancel_btn = ttk.Button( button_frame, text="Cancel", command=self.window.destroy ) cancel_btn.pack(side=tk.RIGHT, padx=(10, 10), pady=5) def _handle_export(self) -> None: """Handle the export button click.""" # Check if we have data to export export_info = self.export_manager.get_export_info() if not export_info["has_data"]: messagebox.showwarning( "No Data", "There is no data available to export.", parent=self.window ) return # Get selected format selected_format = self.format_var.get() # Define file types for dialog file_types = { "JSON": [("JSON files", "*.json"), ("All files", "*.*")], "XML": [("XML files", "*.xml"), ("All files", "*.*")], "PDF": [("PDF files", "*.pdf"), ("All files", "*.*")], } # Default filename default_name = f"thechart_export.{selected_format.lower()}" # Show save dialog filename = filedialog.asksaveasfilename( parent=self.window, title=f"Export as {selected_format}", defaultextension=f".{selected_format.lower()}", filetypes=file_types[selected_format], initialfile=default_name, ) if not filename: return # Perform export based on selected format success = False try: if selected_format == "JSON": success = self.export_manager.export_data_to_json(filename) elif selected_format == "XML": success = self.export_manager.export_data_to_xml(filename) elif selected_format == "PDF": include_graph = self.include_graph_var.get() success = self.export_manager.export_to_pdf( filename, include_graph=include_graph ) if success: messagebox.showinfo( "Export Successful", f"Data exported successfully to:\n{filename}", parent=self.window, ) # Ask if user wants to open the file location if messagebox.askyesno( "Open Location", "Would you like to open the file location?", parent=self.window, ): self._open_file_location(filename) self.window.destroy() else: messagebox.showerror( "Export Failed", f"Failed to export data as {selected_format}. " "Please check the logs for more details.", parent=self.window, ) except Exception as e: messagebox.showerror( "Export Error", f"An error occurred during export:\n{str(e)}", parent=self.window, ) def _open_file_location(self, filepath: str) -> None: """Open the file location in the system file manager.""" try: file_path = Path(filepath) directory = file_path.parent # Use system-specific command to open file manager import subprocess import sys if sys.platform == "win32": subprocess.run(["explorer", str(directory)], check=False) elif sys.platform == "darwin": subprocess.run(["open", str(directory)], check=False) else: # Linux and other Unix-like systems subprocess.run(["xdg-open", str(directory)], check=False) except Exception: # If opening file location fails, just ignore silently pass