Initial commit
Dieser Commit ist enthalten in:
696
gui/settings_dialog.py
Normale Datei
696
gui/settings_dialog.py
Normale Datei
@ -0,0 +1,696 @@
|
||||
"""
|
||||
Settings Dialog for the application
|
||||
Allows users to configure various settings including view modes
|
||||
"""
|
||||
|
||||
import customtkinter as ctk
|
||||
from gui.styles import COLORS, FONTS
|
||||
from utils.logger import logger
|
||||
import json
|
||||
from pathlib import Path
|
||||
from tkinter import filedialog
|
||||
import os
|
||||
|
||||
|
||||
class SettingsDialog(ctk.CTkToplevel):
|
||||
def __init__(self, parent, sidebar_view):
|
||||
super().__init__(parent)
|
||||
|
||||
self.sidebar_view = sidebar_view
|
||||
self.settings_file = Path.home() / ".claude_project_manager" / "ui_settings.json"
|
||||
|
||||
# Window setup
|
||||
self.title("Einstellungen")
|
||||
self.minsize(650, 550)
|
||||
self.resizable(True, True)
|
||||
|
||||
# Make modal
|
||||
self.transient(parent)
|
||||
self.grab_set()
|
||||
|
||||
# Load current settings
|
||||
self.settings = self.load_settings()
|
||||
|
||||
# Setup UI
|
||||
self.setup_ui()
|
||||
|
||||
# Update window size to fit content
|
||||
self.update_idletasks()
|
||||
|
||||
# Center window
|
||||
self.center_window()
|
||||
|
||||
# Focus
|
||||
self.focus()
|
||||
|
||||
def setup_ui(self):
|
||||
"""Setup the settings UI"""
|
||||
# Main container
|
||||
main_frame = ctk.CTkFrame(self, fg_color=COLORS['bg_primary'])
|
||||
main_frame.pack(fill="both", expand=True, padx=20, pady=20)
|
||||
|
||||
# Title
|
||||
title_label = ctk.CTkLabel(
|
||||
main_frame,
|
||||
text="⚙️ Einstellungen",
|
||||
font=FONTS['subtitle'],
|
||||
text_color=COLORS['text_primary']
|
||||
)
|
||||
title_label.pack(pady=(0, 20))
|
||||
|
||||
# Tab view
|
||||
self.tabview = ctk.CTkTabview(
|
||||
main_frame,
|
||||
fg_color=COLORS['bg_secondary'],
|
||||
segmented_button_fg_color=COLORS['bg_tile'],
|
||||
segmented_button_selected_color=COLORS['accent_primary'],
|
||||
segmented_button_selected_hover_color=COLORS['accent_hover'],
|
||||
segmented_button_unselected_color=COLORS['bg_tile'],
|
||||
segmented_button_unselected_hover_color=COLORS['bg_tile_hover'],
|
||||
text_color=COLORS['text_primary'],
|
||||
text_color_disabled=COLORS['text_dim']
|
||||
)
|
||||
self.tabview.pack(fill="both", expand=True)
|
||||
|
||||
# Add tabs
|
||||
self.tabview.add("Allgemein")
|
||||
self.tabview.add("Gitea")
|
||||
self.tabview.add("Team-Aktivität")
|
||||
|
||||
# Setup each tab
|
||||
self.setup_general_tab()
|
||||
self.setup_gitea_tab()
|
||||
self.setup_activity_tab()
|
||||
|
||||
# Buttons (at bottom of main frame)
|
||||
button_frame = ctk.CTkFrame(main_frame, fg_color="transparent")
|
||||
button_frame.pack(fill="x", pady=(20, 0))
|
||||
|
||||
# Cancel button (left side)
|
||||
cancel_btn = ctk.CTkButton(
|
||||
button_frame,
|
||||
text="Abbrechen",
|
||||
command=self.destroy,
|
||||
fg_color=COLORS['bg_tile'],
|
||||
hover_color=COLORS['bg_tile_hover'],
|
||||
text_color=COLORS['text_primary'],
|
||||
width=100
|
||||
)
|
||||
cancel_btn.pack(side="left", padx=(0, 5))
|
||||
|
||||
# Apply button (right side)
|
||||
apply_btn = ctk.CTkButton(
|
||||
button_frame,
|
||||
text="Anwenden",
|
||||
command=self.apply_settings,
|
||||
fg_color=COLORS['accent_primary'],
|
||||
hover_color=COLORS['accent_hover'],
|
||||
width=100
|
||||
)
|
||||
apply_btn.pack(side="right", padx=(5, 0))
|
||||
|
||||
# Save button (right side, before Apply)
|
||||
save_btn = ctk.CTkButton(
|
||||
button_frame,
|
||||
text="Speichern",
|
||||
command=self.save_settings_only,
|
||||
fg_color=COLORS['accent_secondary'],
|
||||
hover_color=COLORS['accent_hover'],
|
||||
text_color=COLORS['text_primary'],
|
||||
width=100
|
||||
)
|
||||
save_btn.pack(side="right", padx=(5, 0))
|
||||
|
||||
def setup_general_tab(self):
|
||||
"""Setup general settings tab"""
|
||||
tab = self.tabview.tab("Allgemein")
|
||||
|
||||
# Container with padding
|
||||
container = ctk.CTkFrame(tab, fg_color="transparent")
|
||||
container.pack(fill="both", expand=True, padx=20, pady=20)
|
||||
|
||||
# Placeholder for future general settings
|
||||
info_label = ctk.CTkLabel(
|
||||
container,
|
||||
text="Allgemeine Einstellungen werden hier angezeigt.\n(Aktuell keine verfügbar)",
|
||||
font=FONTS['body'],
|
||||
text_color=COLORS['text_dim']
|
||||
)
|
||||
info_label.pack(pady=50)
|
||||
|
||||
def setup_gitea_tab(self):
|
||||
"""Setup Gitea settings tab"""
|
||||
tab = self.tabview.tab("Gitea")
|
||||
|
||||
# Scrollable container
|
||||
container = ctk.CTkScrollableFrame(tab, fg_color="transparent")
|
||||
container.pack(fill="both", expand=True, padx=20, pady=20)
|
||||
|
||||
# Clone Directory Section
|
||||
clone_section = ctk.CTkFrame(container, fg_color=COLORS['bg_tile'])
|
||||
clone_section.pack(fill="x", pady=(0, 15))
|
||||
|
||||
clone_header = ctk.CTkLabel(
|
||||
clone_section,
|
||||
text="📁 Clone-Verzeichnis",
|
||||
font=FONTS['body'],
|
||||
text_color=COLORS['text_primary']
|
||||
)
|
||||
clone_header.pack(anchor="w", padx=15, pady=(10, 5))
|
||||
|
||||
# Clone directory path
|
||||
clone_path_frame = ctk.CTkFrame(clone_section, fg_color="transparent")
|
||||
clone_path_frame.pack(fill="x", padx=30, pady=(5, 10))
|
||||
|
||||
default_clone_dir = str(Path.home() / "GiteaRepos")
|
||||
self.clone_dir_var = ctk.StringVar(value=self.settings.get("gitea_clone_directory", default_clone_dir))
|
||||
|
||||
self.clone_dir_entry = ctk.CTkEntry(
|
||||
clone_path_frame,
|
||||
textvariable=self.clone_dir_var,
|
||||
width=350,
|
||||
fg_color=COLORS['bg_primary']
|
||||
)
|
||||
self.clone_dir_entry.pack(side="left", padx=(0, 10))
|
||||
|
||||
browse_btn = ctk.CTkButton(
|
||||
clone_path_frame,
|
||||
text="Durchsuchen...",
|
||||
command=self.browse_clone_directory,
|
||||
fg_color=COLORS['bg_secondary'],
|
||||
hover_color=COLORS['bg_tile_hover'],
|
||||
text_color=COLORS['text_primary'],
|
||||
width=100
|
||||
)
|
||||
browse_btn.pack(side="left")
|
||||
|
||||
# Info label
|
||||
info_label = ctk.CTkLabel(
|
||||
clone_section,
|
||||
text="Standardverzeichnis für geklonte Repositories",
|
||||
font=FONTS['small'],
|
||||
text_color=COLORS['text_dim']
|
||||
)
|
||||
info_label.pack(anchor="w", padx=30, pady=(0, 10))
|
||||
|
||||
# Server Configuration Section
|
||||
server_section = ctk.CTkFrame(container, fg_color=COLORS['bg_tile'])
|
||||
server_section.pack(fill="x", pady=(0, 15))
|
||||
|
||||
server_header = ctk.CTkLabel(
|
||||
server_section,
|
||||
text="🌐 Gitea Server",
|
||||
font=FONTS['body'],
|
||||
text_color=COLORS['text_primary']
|
||||
)
|
||||
server_header.pack(anchor="w", padx=15, pady=(10, 5))
|
||||
|
||||
# Server URL
|
||||
url_label = ctk.CTkLabel(
|
||||
server_section,
|
||||
text="Server URL:",
|
||||
font=FONTS['small'],
|
||||
text_color=COLORS['text_secondary']
|
||||
)
|
||||
url_label.pack(anchor="w", padx=30, pady=(5, 0))
|
||||
|
||||
self.gitea_url_var = ctk.StringVar(value=self.settings.get("gitea_server_url", "https://gitea-undso.intelsight.de"))
|
||||
self.gitea_url_entry = ctk.CTkEntry(
|
||||
server_section,
|
||||
textvariable=self.gitea_url_var,
|
||||
width=350,
|
||||
fg_color=COLORS['bg_primary']
|
||||
)
|
||||
self.gitea_url_entry.pack(padx=30, pady=(0, 5))
|
||||
|
||||
# API Token
|
||||
token_label = ctk.CTkLabel(
|
||||
server_section,
|
||||
text="API Token:",
|
||||
font=FONTS['small'],
|
||||
text_color=COLORS['text_secondary']
|
||||
)
|
||||
token_label.pack(anchor="w", padx=30, pady=(5, 0))
|
||||
|
||||
self.gitea_token_var = ctk.StringVar(value=self.settings.get("gitea_api_token", ""))
|
||||
self.gitea_token_entry = ctk.CTkEntry(
|
||||
server_section,
|
||||
textvariable=self.gitea_token_var,
|
||||
width=350,
|
||||
fg_color=COLORS['bg_primary'],
|
||||
show="*"
|
||||
)
|
||||
self.gitea_token_entry.pack(padx=30, pady=(0, 5))
|
||||
|
||||
# Username
|
||||
user_label = ctk.CTkLabel(
|
||||
server_section,
|
||||
text="Benutzername:",
|
||||
font=FONTS['small'],
|
||||
text_color=COLORS['text_secondary']
|
||||
)
|
||||
user_label.pack(anchor="w", padx=30, pady=(5, 0))
|
||||
|
||||
self.gitea_user_var = ctk.StringVar(value=self.settings.get("gitea_username", ""))
|
||||
self.gitea_user_entry = ctk.CTkEntry(
|
||||
server_section,
|
||||
textvariable=self.gitea_user_var,
|
||||
width=350,
|
||||
fg_color=COLORS['bg_primary']
|
||||
)
|
||||
self.gitea_user_entry.pack(padx=30, pady=(0, 10))
|
||||
|
||||
# Test connection button
|
||||
test_btn = ctk.CTkButton(
|
||||
server_section,
|
||||
text="Verbindung testen",
|
||||
command=self.test_gitea_connection,
|
||||
fg_color=COLORS['bg_secondary'],
|
||||
hover_color=COLORS['bg_tile_hover'],
|
||||
text_color=COLORS['text_primary'],
|
||||
width=150
|
||||
)
|
||||
test_btn.pack(pady=(5, 10))
|
||||
|
||||
# Status label
|
||||
self.gitea_status_label = ctk.CTkLabel(
|
||||
server_section,
|
||||
text="",
|
||||
font=FONTS['small'],
|
||||
text_color=COLORS['text_secondary'],
|
||||
height=20
|
||||
)
|
||||
self.gitea_status_label.pack(pady=(0, 10))
|
||||
|
||||
def setup_activity_tab(self):
|
||||
"""Setup activity server settings tab"""
|
||||
tab = self.tabview.tab("Team-Aktivität")
|
||||
|
||||
# Container with padding
|
||||
container = ctk.CTkFrame(tab, fg_color="transparent")
|
||||
container.pack(fill="both", expand=True, padx=20, pady=20)
|
||||
|
||||
# Activity Server Section
|
||||
activity_section = ctk.CTkFrame(container, fg_color=COLORS['bg_tile'])
|
||||
activity_section.pack(fill="x", pady=(0, 15))
|
||||
|
||||
activity_header = ctk.CTkLabel(
|
||||
activity_section,
|
||||
text="👥 Team-Aktivität Server",
|
||||
font=FONTS['body'],
|
||||
text_color=COLORS['text_primary']
|
||||
)
|
||||
activity_header.pack(anchor="w", padx=15, pady=(10, 5))
|
||||
|
||||
# Server URL
|
||||
url_label = ctk.CTkLabel(
|
||||
activity_section,
|
||||
text="Server URL:",
|
||||
font=FONTS['small'],
|
||||
text_color=COLORS['text_secondary']
|
||||
)
|
||||
url_label.pack(anchor="w", padx=30, pady=(5, 0))
|
||||
|
||||
self.server_url_var = ctk.StringVar(value=self.settings.get("activity_server_url", "http://91.99.192.14:3001"))
|
||||
self.server_url_entry = ctk.CTkEntry(
|
||||
activity_section,
|
||||
textvariable=self.server_url_var,
|
||||
width=350,
|
||||
fg_color=COLORS['bg_primary']
|
||||
)
|
||||
self.server_url_entry.pack(padx=30, pady=(0, 5))
|
||||
|
||||
# API Key
|
||||
api_label = ctk.CTkLabel(
|
||||
activity_section,
|
||||
text="API Key:",
|
||||
font=FONTS['small'],
|
||||
text_color=COLORS['text_secondary']
|
||||
)
|
||||
api_label.pack(anchor="w", padx=30, pady=(5, 0))
|
||||
|
||||
self.api_key_var = ctk.StringVar(value=self.settings.get("activity_api_key", ""))
|
||||
self.api_key_entry = ctk.CTkEntry(
|
||||
activity_section,
|
||||
textvariable=self.api_key_var,
|
||||
width=350,
|
||||
fg_color=COLORS['bg_primary'],
|
||||
show="*"
|
||||
)
|
||||
self.api_key_entry.pack(padx=30, pady=(0, 5))
|
||||
|
||||
# User Name
|
||||
user_label = ctk.CTkLabel(
|
||||
activity_section,
|
||||
text="Benutzername:",
|
||||
font=FONTS['small'],
|
||||
text_color=COLORS['text_secondary']
|
||||
)
|
||||
user_label.pack(anchor="w", padx=30, pady=(5, 0))
|
||||
|
||||
self.user_name_var = ctk.StringVar(value=self.settings.get("activity_user_name", ""))
|
||||
self.user_name_entry = ctk.CTkEntry(
|
||||
activity_section,
|
||||
textvariable=self.user_name_var,
|
||||
width=350,
|
||||
fg_color=COLORS['bg_primary']
|
||||
)
|
||||
self.user_name_entry.pack(padx=30, pady=(0, 5))
|
||||
|
||||
# Test connection button
|
||||
test_btn = ctk.CTkButton(
|
||||
activity_section,
|
||||
text="Verbindung testen",
|
||||
command=self.test_activity_connection,
|
||||
fg_color=COLORS['bg_secondary'],
|
||||
hover_color=COLORS['bg_tile_hover'],
|
||||
text_color=COLORS['text_primary'],
|
||||
width=150
|
||||
)
|
||||
test_btn.pack(pady=(5, 10))
|
||||
|
||||
# Status label
|
||||
self.connection_status_label = ctk.CTkLabel(
|
||||
activity_section,
|
||||
text="",
|
||||
font=FONTS['small'],
|
||||
text_color=COLORS['text_secondary'],
|
||||
height=20
|
||||
)
|
||||
self.connection_status_label.pack(pady=(0, 10))
|
||||
|
||||
def load_settings(self):
|
||||
"""Load settings from file"""
|
||||
try:
|
||||
if self.settings_file.exists():
|
||||
with open(self.settings_file, 'r') as f:
|
||||
return json.load(f)
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to load UI settings: {e}")
|
||||
|
||||
return {} # No settings currently
|
||||
|
||||
def save_settings(self):
|
||||
"""Save settings to file"""
|
||||
try:
|
||||
self.settings_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
with open(self.settings_file, 'w') as f:
|
||||
json.dump(self.settings, f, indent=2)
|
||||
logger.info(f"Saved UI settings: {self.settings}")
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to save UI settings: {e}")
|
||||
|
||||
def browse_clone_directory(self):
|
||||
"""Browse for clone directory"""
|
||||
current_dir = self.clone_dir_var.get()
|
||||
if not os.path.exists(current_dir):
|
||||
current_dir = str(Path.home())
|
||||
|
||||
directory = filedialog.askdirectory(
|
||||
title="Clone-Verzeichnis auswählen",
|
||||
initialdir=current_dir,
|
||||
parent=self
|
||||
)
|
||||
|
||||
if directory:
|
||||
self.clone_dir_var.set(directory)
|
||||
logger.info(f"Selected clone directory: {directory}")
|
||||
|
||||
def test_gitea_connection(self):
|
||||
"""Test connection to Gitea server"""
|
||||
import requests
|
||||
|
||||
server_url = self.gitea_url_var.get().strip()
|
||||
api_token = self.gitea_token_var.get().strip()
|
||||
|
||||
if not server_url:
|
||||
self.gitea_status_label.configure(
|
||||
text="⚠️ Bitte Server URL eingeben",
|
||||
text_color=COLORS['accent_warning']
|
||||
)
|
||||
return
|
||||
|
||||
self.gitea_status_label.configure(
|
||||
text="🔄 Teste Verbindung...",
|
||||
text_color=COLORS['text_secondary']
|
||||
)
|
||||
self.update()
|
||||
|
||||
try:
|
||||
# Try to connect to the Gitea API
|
||||
headers = {}
|
||||
if api_token:
|
||||
headers["Authorization"] = f"token {api_token}"
|
||||
|
||||
response = requests.get(
|
||||
f"{server_url}/api/v1/version",
|
||||
timeout=5,
|
||||
headers=headers
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
version = response.json().get('version', 'Unknown')
|
||||
self.gitea_status_label.configure(
|
||||
text=f"✅ Verbindung erfolgreich! (Gitea {version})",
|
||||
text_color=COLORS['accent_success']
|
||||
)
|
||||
logger.info(f"Gitea connection successful: {server_url}, version: {version}")
|
||||
else:
|
||||
self.gitea_status_label.configure(
|
||||
text=f"❌ Server antwortet mit Status {response.status_code}",
|
||||
text_color=COLORS['accent_error']
|
||||
)
|
||||
logger.warning(f"Gitea server returned status {response.status_code}")
|
||||
|
||||
except requests.exceptions.ConnectionError:
|
||||
self.gitea_status_label.configure(
|
||||
text="❌ Server nicht erreichbar",
|
||||
text_color=COLORS['accent_error']
|
||||
)
|
||||
logger.error(f"Gitea server not reachable: {server_url}")
|
||||
except requests.exceptions.Timeout:
|
||||
self.gitea_status_label.configure(
|
||||
text="❌ Verbindung Timeout",
|
||||
text_color=COLORS['accent_error']
|
||||
)
|
||||
logger.error(f"Gitea server connection timeout: {server_url}")
|
||||
except Exception as e:
|
||||
self.gitea_status_label.configure(
|
||||
text=f"❌ Fehler: {str(e)}",
|
||||
text_color=COLORS['accent_error']
|
||||
)
|
||||
logger.error(f"Gitea server connection error: {e}")
|
||||
|
||||
def save_settings_only(self):
|
||||
"""Save settings without applying to service or closing dialog"""
|
||||
# Get activity values
|
||||
server_url = self.server_url_var.get().strip()
|
||||
api_key = self.api_key_var.get().strip()
|
||||
user_name = self.user_name_var.get().strip()
|
||||
|
||||
# Get Gitea values
|
||||
gitea_url = self.gitea_url_var.get().strip()
|
||||
gitea_token = self.gitea_token_var.get().strip()
|
||||
gitea_user = self.gitea_user_var.get().strip()
|
||||
clone_dir = self.clone_dir_var.get().strip()
|
||||
|
||||
# Update settings
|
||||
self.settings["activity_server_url"] = server_url
|
||||
self.settings["activity_api_key"] = api_key
|
||||
self.settings["activity_user_name"] = user_name
|
||||
|
||||
self.settings["gitea_server_url"] = gitea_url
|
||||
self.settings["gitea_api_token"] = gitea_token
|
||||
self.settings["gitea_username"] = gitea_user
|
||||
self.settings["gitea_clone_directory"] = clone_dir
|
||||
|
||||
self.save_settings()
|
||||
|
||||
# Show confirmation on the active tab
|
||||
current_tab = self.tabview.get()
|
||||
if current_tab == "Team-Aktivität":
|
||||
self.connection_status_label.configure(
|
||||
text="✅ Einstellungen gespeichert!",
|
||||
text_color=COLORS['accent_success']
|
||||
)
|
||||
self.after(2000, lambda: self.connection_status_label.configure(text=""))
|
||||
elif current_tab == "Gitea":
|
||||
self.gitea_status_label.configure(
|
||||
text="✅ Einstellungen gespeichert!",
|
||||
text_color=COLORS['accent_success']
|
||||
)
|
||||
self.after(2000, lambda: self.gitea_status_label.configure(text=""))
|
||||
|
||||
logger.info("Settings saved successfully")
|
||||
|
||||
def apply_settings(self):
|
||||
"""Apply the selected settings"""
|
||||
import uuid
|
||||
from services.activity_sync import activity_service
|
||||
|
||||
# Save all settings first
|
||||
self.save_settings_only()
|
||||
|
||||
# Apply activity service settings
|
||||
activity_service.server_url = self.settings.get("activity_server_url", "")
|
||||
activity_service.api_key = self.settings.get("activity_api_key", "")
|
||||
activity_service.user_name = self.settings.get("activity_user_name", "")
|
||||
activity_service.user_id = self.settings.get("activity_user_id", str(uuid.uuid4()))
|
||||
|
||||
# Save user ID if newly generated
|
||||
if "activity_user_id" not in self.settings:
|
||||
self.settings["activity_user_id"] = activity_service.user_id
|
||||
self.save_settings()
|
||||
|
||||
# Save activity settings
|
||||
activity_service.save_settings()
|
||||
|
||||
# Reconnect if settings changed
|
||||
if activity_service.connected:
|
||||
activity_service.disconnect()
|
||||
|
||||
if activity_service.is_configured():
|
||||
activity_service.connect()
|
||||
|
||||
logger.info("Activity server settings applied")
|
||||
|
||||
# Apply Gitea settings to config
|
||||
self.update_gitea_config()
|
||||
|
||||
# Close dialog
|
||||
self.destroy()
|
||||
|
||||
def update_gitea_config(self):
|
||||
"""Update Gitea configuration in the application"""
|
||||
try:
|
||||
# Import here to avoid circular imports
|
||||
from src.gitea.gitea_client import gitea_config
|
||||
from src.gitea.git_operations import git_ops
|
||||
|
||||
# Update Gitea config
|
||||
if hasattr(gitea_config, 'base_url'):
|
||||
gitea_config.base_url = self.settings.get("gitea_server_url", gitea_config.base_url)
|
||||
if hasattr(gitea_config, 'api_token'):
|
||||
gitea_config.api_token = self.settings.get("gitea_api_token", gitea_config.api_token)
|
||||
if hasattr(gitea_config, 'username'):
|
||||
gitea_config.username = self.settings.get("gitea_username", gitea_config.username)
|
||||
|
||||
# Update clone directory
|
||||
clone_dir = self.settings.get("gitea_clone_directory")
|
||||
if clone_dir:
|
||||
# Re-initialize git_ops to use new settings
|
||||
from src.gitea.git_operations import init_git_ops
|
||||
init_git_ops()
|
||||
|
||||
# Now update the clone directory
|
||||
if hasattr(git_ops, 'default_clone_dir'):
|
||||
git_ops.default_clone_dir = Path(clone_dir)
|
||||
logger.info(f"Updated git_ops clone directory to: {clone_dir}")
|
||||
|
||||
# Update all existing RepositoryManager instances
|
||||
# This ensures that any git_ops instances in the application get the new directory
|
||||
try:
|
||||
# Update in main window if it exists
|
||||
parent = self.master
|
||||
if hasattr(parent, 'gitea_handler') and hasattr(parent.gitea_handler, 'repo_manager'):
|
||||
if hasattr(parent.gitea_handler.repo_manager, 'git_ops'):
|
||||
parent.gitea_handler.repo_manager.git_ops.default_clone_dir = Path(clone_dir)
|
||||
logger.info("Updated main window's git_ops clone directory")
|
||||
|
||||
# Update in sidebar gitea explorer if it exists
|
||||
if hasattr(parent, 'sidebar') and hasattr(parent.sidebar, 'gitea_explorer'):
|
||||
if hasattr(parent.sidebar.gitea_explorer, 'repo_manager'):
|
||||
if hasattr(parent.sidebar.gitea_explorer.repo_manager, 'git_ops'):
|
||||
parent.sidebar.gitea_explorer.repo_manager.git_ops.default_clone_dir = Path(clone_dir)
|
||||
logger.info("Updated sidebar's git_ops clone directory")
|
||||
except Exception as e:
|
||||
logger.warning(f"Could not update all git_ops instances: {e}")
|
||||
|
||||
logger.info("Gitea configuration updated")
|
||||
|
||||
except ImportError as e:
|
||||
logger.warning(f"Could not update Gitea config: {e}")
|
||||
except Exception as e:
|
||||
logger.error(f"Error updating Gitea config: {e}")
|
||||
|
||||
def test_activity_connection(self):
|
||||
"""Test connection to activity server"""
|
||||
import requests
|
||||
from tkinter import messagebox
|
||||
|
||||
server_url = self.server_url_var.get().strip()
|
||||
api_key = self.api_key_var.get().strip()
|
||||
|
||||
if not server_url:
|
||||
self.connection_status_label.configure(
|
||||
text="⚠️ Bitte Server URL eingeben",
|
||||
text_color=COLORS['accent_warning']
|
||||
)
|
||||
return
|
||||
|
||||
self.connection_status_label.configure(
|
||||
text="🔄 Teste Verbindung...",
|
||||
text_color=COLORS['text_secondary']
|
||||
)
|
||||
self.update()
|
||||
|
||||
try:
|
||||
# Try to connect to the server
|
||||
response = requests.get(
|
||||
f"{server_url}/health",
|
||||
timeout=5,
|
||||
headers={"Authorization": f"Bearer {api_key}"} if api_key else {}
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
self.connection_status_label.configure(
|
||||
text="✅ Verbindung erfolgreich!",
|
||||
text_color=COLORS['accent_success']
|
||||
)
|
||||
logger.info(f"Activity server connection successful: {server_url}")
|
||||
else:
|
||||
self.connection_status_label.configure(
|
||||
text=f"❌ Server antwortet mit Status {response.status_code}",
|
||||
text_color=COLORS['accent_error']
|
||||
)
|
||||
logger.warning(f"Activity server returned status {response.status_code}")
|
||||
|
||||
except requests.exceptions.ConnectionError:
|
||||
self.connection_status_label.configure(
|
||||
text="❌ Server nicht erreichbar",
|
||||
text_color=COLORS['accent_error']
|
||||
)
|
||||
logger.error(f"Activity server not reachable: {server_url}")
|
||||
except requests.exceptions.Timeout:
|
||||
self.connection_status_label.configure(
|
||||
text="❌ Verbindung Timeout",
|
||||
text_color=COLORS['accent_error']
|
||||
)
|
||||
logger.error(f"Activity server connection timeout: {server_url}")
|
||||
except Exception as e:
|
||||
self.connection_status_label.configure(
|
||||
text=f"❌ Fehler: {str(e)}",
|
||||
text_color=COLORS['accent_error']
|
||||
)
|
||||
logger.error(f"Activity server connection error: {e}")
|
||||
|
||||
def center_window(self):
|
||||
"""Center the dialog on parent window"""
|
||||
self.update_idletasks()
|
||||
|
||||
# Get parent window position
|
||||
parent = self.master
|
||||
parent_x = parent.winfo_x()
|
||||
parent_y = parent.winfo_y()
|
||||
parent_width = parent.winfo_width()
|
||||
parent_height = parent.winfo_height()
|
||||
|
||||
# Get dialog size
|
||||
dialog_width = self.winfo_width()
|
||||
dialog_height = self.winfo_height()
|
||||
|
||||
# Calculate position
|
||||
x = parent_x + (parent_width - dialog_width) // 2
|
||||
y = parent_y + (parent_height - dialog_height) // 2
|
||||
|
||||
self.geometry(f"+{x}+{y}")
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren