# --- FILE: gitsync_tool/logic/window_handler.py --- import os from typing import TYPE_CHECKING, Optional, List, Dict, Any from gitutility.gui.editors import GitignoreEditorWindow from gitutility.gui.diff_viewer import DiffViewerWindow from gitutility.gui.commit_detail_window import CommitDetailWindow from gitutility.gui.diff_summary_viewer import DiffSummaryWindow from gitutility.logging_setup import log_handler # Forward reference for type hinting to avoid circular imports if TYPE_CHECKING: from ..app import GitSvnSyncApp class WindowHandler: """ Handles the creation and logic for all secondary windows, dialogs, and editors within the application. """ def __init__(self, app: "GitSvnSyncApp"): """ Initializes the WindowHandler. Args: app: The main application instance. """ self.app = app self.master = app.master self.main_frame = app.main_frame self.git_commands = app.git_commands log_handler.log_debug("WindowHandler initialized.", func_name="__init__") def handle_open_gitignore_editor(self): """Opens the .gitignore editor window.""" func_name = "handle_open_gitignore_editor" svn_path = self.app._get_and_validate_svn_path("Edit .gitignore") if not svn_path or not self.app._is_repo_ready(svn_path): self.main_frame.show_error("Action Failed", "Select a valid and prepared repository first.") return gitignore_path = os.path.join(svn_path, ".gitignore") try: # The on_save_success_callback points to a method in the repository_handler GitignoreEditorWindow( master=self.master, gitignore_path=gitignore_path, on_save_success_callback=self.app.repository_handler.handle_gitignore_save ) except Exception as e: log_handler.log_exception(f"Error opening .gitignore editor: {e}", func_name=func_name) self.main_frame.show_error("Editor Error", f"Could not open editor:\n{e}") def handle_open_diff_viewer(self, file_status_line: str): """Opens the Diff Viewer for a file from the 'changed files' list.""" func_name = "handle_open_diff_viewer" svn_path = self.app._get_and_validate_svn_path("Open Diff Viewer") if not svn_path: return relative_path = self.app._extract_path_from_status_line(file_status_line) if not relative_path: log_handler.log_error(f"Could not extract path from: {file_status_line}", func_name=func_name) self.main_frame.show_error("Path Error", f"Could not parse file path from line:\n{file_status_line}") return status_code = file_status_line.strip('\x00').strip()[:2].strip() if status_code == 'D': self.main_frame.show_info("Diff Not Applicable", "Cannot diff a deleted file against the working directory.") return if status_code in ['??', '!!']: self.main_frame.show_info("Diff Not Applicable", "Cannot diff an untracked or ignored file.") return try: DiffViewerWindow( master=self.master, git_commands=self.git_commands, repo_path=svn_path, relative_file_path=relative_path, ref1='WORKING_DIR', ref2='HEAD' ) except Exception as e: log_handler.log_exception(f"Error opening diff viewer: {e}", func_name=func_name) self.main_frame.show_error("Diff Viewer Error", f"Could not display diff:\n{e}") def handle_show_commit_details(self, commit_details: Dict[str, Any]): """Opens the CommitDetailWindow to display commit details.""" func_name = "handle_show_commit_details" if not isinstance(commit_details, dict) or not commit_details.get('hash_full'): log_handler.log_error("Invalid commit details received.", func_name=func_name) self.main_frame.show_error("Display Error", "Internal error: Invalid commit data.") self.app._reenable_widgets_if_ready() return try: CommitDetailWindow( master=self.master, commit_data=commit_details, open_diff_callback=self._handle_open_commit_file_diff ) self.main_frame.update_status_bar("Ready.") except Exception as e: log_handler.log_exception(f"Error opening commit detail window: {e}", func_name=func_name) self.main_frame.show_error("Display Error", f"Could not display commit details:\n{e}") finally: self.app._reenable_widgets_if_ready() def _handle_open_commit_file_diff(self, commit_hash: str, file_status: str, file_path: str, old_file_path: Optional[str] = None): """Callback to open diff for a file from the commit detail view.""" func_name = "_handle_open_commit_file_diff" svn_path = self.app._get_and_validate_svn_path("Open Commit File Diff") if not svn_path: return ref1, ref2 = f"{commit_hash}^", commit_hash if file_status == 'D': self.main_frame.show_info("Diff Not Applicable", "Diff for deleted files in this view is not supported.") return try: DiffViewerWindow( master=self.master, git_commands=self.git_commands, repo_path=svn_path, relative_file_path=file_path, ref1=ref1, ref2=ref2 ) except Exception as e: log_handler.log_exception(f"Error opening commit file diff: {e}", func_name=func_name) self.main_frame.show_error("Diff Viewer Error", f"Could not display file changes:\n{e}") def handle_show_comparison_summary(self, ref1: str, ref2: str, repo_path: str, changed_files: List[str]): """Opens the comparison summary window.""" func_name = "handle_show_comparison_summary" try: DiffSummaryWindow( master=self.master, git_commands=self.git_commands, repo_path=repo_path, ref1=ref1, ref2=ref2, changed_files_status=changed_files, ) self.main_frame.update_status_bar("Ready.") except Exception as e: log_handler.log_exception(f"Error opening diff summary: {e}", func_name=func_name) self.main_frame.show_error("Display Error", f"Could not display comparison results:\n{e}") finally: self.app._reenable_widgets_if_ready()