SXXXXXXX_GitUtility/gitutility/logic/window_handler.py

201 lines
7.2 KiB
Python

# --- 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()