201 lines
7.2 KiB
Python
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()
|