SXXXXXXX_GitUtility/gitutility/gui/tabs/repo_tab.py

223 lines
8.1 KiB
Python

# --- FILE: gitsync_tool/gui/tabs/repo_tab.py ---
import tkinter as tk
from tkinter import ttk
from typing import Callable, Optional
from gitutility.gui.tooltip import Tooltip
class RepoTab(ttk.Frame):
"""
The 'Repository / Bundle' tab in the main application notebook.
This tab contains widgets for managing the local repository path, bundle
operations, and basic repository initialization.
"""
# Constants for colors
GREEN: str = "#90EE90" # LightGreen
RED: str = "#F08080" # LightCoral
def __init__(self, master: tk.Misc, **kwargs):
"""
Initializes the Repository / Bundle tab.
Args:
master: The parent widget (the ttk.Notebook).
**kwargs: Dictionary of callbacks from the main controller.
"""
super().__init__(master, padding=(10, 10))
# Store callbacks by getting them from kwargs
self.update_svn_status_callback = kwargs.get("update_svn_status_cb")
self.browse_folder_callback = kwargs.get("browse_folder_cb")
self.prepare_svn_for_git_callback = kwargs.get("prepare_svn_for_git_cb")
self.create_git_bundle_callback = kwargs.get("create_git_bundle_cb")
self.fetch_from_git_bundle_callback = kwargs.get("fetch_from_git_bundle_cb")
self.open_gitignore_editor_callback = kwargs.get("open_gitignore_editor_cb")
# Configure layout
self.columnconfigure(1, weight=1)
# Create widgets
self._create_widgets()
def _create_widgets(self) -> None:
"""Creates and arranges all widgets for this tab."""
# --- Paths and Bundle Names Frame ---
paths_frame = ttk.LabelFrame(self, text="Paths & Bundle Names", padding=(10, 5))
paths_frame.pack(pady=5, fill="x")
paths_frame.columnconfigure(1, weight=1)
# Row indices for grid
cl, ce, cb, ci = 0, 1, 2, 3
# Working Directory Path
ttk.Label(paths_frame, text="Working Directory Path:").grid(
row=0, column=cl, sticky=tk.W, padx=5, pady=3
)
self.svn_path_entry = ttk.Entry(paths_frame, width=60)
self.svn_path_entry.grid(row=0, column=ce, sticky=tk.EW, padx=5, pady=3)
self.svn_path_entry.bind(
"<FocusOut>",
lambda e: self.update_svn_status_callback(self.svn_path_entry.get()),
)
self.svn_path_entry.bind(
"<Return>",
lambda e: self.update_svn_status_callback(self.svn_path_entry.get()),
)
Tooltip(
self.svn_path_entry, "Path to the local Git repository working directory."
)
self.svn_path_browse_button = ttk.Button(
paths_frame,
text="Browse...",
width=9,
command=lambda: self.browse_folder_callback(self.svn_path_entry),
)
self.svn_path_browse_button.grid(
row=0, column=cb, sticky=tk.W, padx=(0, 5), pady=3
)
self.svn_status_indicator = tk.Label(
paths_frame,
text="",
width=2,
height=1,
relief=tk.SUNKEN,
background=self.RED,
anchor=tk.CENTER,
)
self.svn_status_indicator.grid(
row=0, column=ci, sticky=tk.E, padx=(0, 5), pady=3
)
Tooltip(
self.svn_status_indicator,
"Indicates if the path points to a valid Git repository (Green=Yes, Red=No).",
)
# Bundle Target Directory
ttk.Label(paths_frame, text="Bundle Target Directory:").grid(
row=1, column=cl, sticky=tk.W, padx=5, pady=3
)
self.usb_path_entry = ttk.Entry(paths_frame, width=60)
self.usb_path_entry.grid(row=1, column=ce, sticky=tk.EW, padx=5, pady=3)
Tooltip(
self.usb_path_entry,
"Directory where bundle files will be created or read from (e.g., USB drive).",
)
self.usb_path_browse_button = ttk.Button(
paths_frame,
text="Browse...",
width=9,
command=lambda: self.browse_folder_callback(self.usb_path_entry),
)
self.usb_path_browse_button.grid(
row=1, column=cb, sticky=tk.W, padx=(0, 5), pady=3
)
# Bundle Filenames
ttk.Label(paths_frame, text="Create Bundle Filename:").grid(
row=2, column=cl, sticky=tk.W, padx=5, pady=3
)
self.bundle_name_entry = ttk.Entry(paths_frame, width=60)
self.bundle_name_entry.grid(
row=2, column=ce, columnspan=2, sticky=tk.EW, padx=5, pady=3
)
Tooltip(
self.bundle_name_entry,
"Filename to use when creating a new bundle file (e.g., my_project.bundle).",
)
ttk.Label(paths_frame, text="Fetch Bundle Filename:").grid(
row=3, column=cl, sticky=tk.W, padx=5, pady=3
)
self.bundle_updated_name_entry = ttk.Entry(paths_frame, width=60)
self.bundle_updated_name_entry.grid(
row=3, column=ce, columnspan=2, sticky=tk.EW, padx=5, pady=3
)
Tooltip(
self.bundle_updated_name_entry,
"Filename of the bundle file to fetch updates from (e.g., update.bundle).",
)
# --- Repository Actions Frame ---
actions_frame = ttk.LabelFrame(self, text="Repository Actions", padding=(10, 5))
actions_frame.pack(pady=10, fill="x")
self.prepare_svn_button = ttk.Button(
actions_frame,
text="Prepare Repository",
command=self.prepare_svn_for_git_callback,
state=tk.DISABLED,
)
self.prepare_svn_button.pack(side=tk.LEFT, padx=(0, 5), pady=5)
Tooltip(
self.prepare_svn_button,
"Initialize Git in the selected directory and configure .gitignore (if not already a Git repo).",
)
self.create_bundle_button = ttk.Button(
actions_frame,
text="Create Bundle",
command=self.create_git_bundle_callback,
state=tk.DISABLED,
)
self.create_bundle_button.pack(side=tk.LEFT, padx=5, pady=5)
Tooltip(
self.create_bundle_button,
"Create a Git bundle file containing the entire repository history and refs.",
)
self.fetch_bundle_button = ttk.Button(
actions_frame,
text="Fetch from Bundle",
command=self.fetch_from_git_bundle_callback,
state=tk.DISABLED,
)
self.fetch_bundle_button.pack(side=tk.LEFT, padx=5, pady=5)
Tooltip(
self.fetch_bundle_button,
"Fetch updates from a bundle file and merge them, or clone if the directory is empty.",
)
self.edit_gitignore_button = ttk.Button(
actions_frame,
text="Edit .gitignore",
width=12,
command=self.open_gitignore_editor_callback,
state=tk.DISABLED,
)
self.edit_gitignore_button.pack(side=tk.LEFT, padx=5, pady=5)
Tooltip(self.edit_gitignore_button, "Open an editor for the .gitignore file.")
def update_svn_indicator(self, is_prepared: bool) -> None:
"""Updates the color and tooltip of the repository status indicator."""
color = self.GREEN if is_prepared else self.RED
tip = (
"Repository is valid and prepared (found .git)."
if is_prepared
else "Directory is not a valid/prepared Git repository."
)
if (
hasattr(self, "svn_status_indicator")
and self.svn_status_indicator.winfo_exists()
):
self.svn_status_indicator.config(background=color)
Tooltip(self.svn_status_indicator, tip)
def set_action_widgets_state(self, state: str) -> None:
"""Sets the state of all action widgets in this tab."""
widgets_to_toggle = [
self.prepare_svn_button,
self.create_bundle_button,
self.fetch_bundle_button,
self.edit_gitignore_button,
]
for widget in widgets_to_toggle:
if widget and widget.winfo_exists():
widget.config(state=state)