314 Zeilen
11 KiB
Python
314 Zeilen
11 KiB
Python
"""
|
|
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
|
|
|
|
|
|
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.geometry("450x400")
|
|
self.resizable(False, False)
|
|
|
|
# Make modal
|
|
self.transient(parent)
|
|
self.grab_set()
|
|
|
|
# Load current settings
|
|
self.settings = self.load_settings()
|
|
|
|
# Setup UI
|
|
self.setup_ui()
|
|
|
|
# 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))
|
|
|
|
# Activity Server Section
|
|
activity_section = ctk.CTkFrame(main_frame, fg_color=COLORS['bg_secondary'])
|
|
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=300,
|
|
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=300,
|
|
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=300,
|
|
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_tile'],
|
|
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']
|
|
)
|
|
self.connection_status_label.pack(pady=(0, 10))
|
|
|
|
# Buttons
|
|
button_frame = ctk.CTkFrame(main_frame, fg_color="transparent")
|
|
button_frame.pack(side="bottom", fill="x", pady=(20, 0))
|
|
|
|
# Apply button
|
|
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))
|
|
|
|
# Cancel button
|
|
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="right")
|
|
|
|
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 apply_settings(self):
|
|
"""Apply the selected settings"""
|
|
import uuid
|
|
from services.activity_sync import activity_service
|
|
|
|
# Get 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()
|
|
|
|
# Update settings
|
|
self.settings["activity_server_url"] = server_url
|
|
self.settings["activity_api_key"] = api_key
|
|
self.settings["activity_user_name"] = user_name
|
|
self.save_settings()
|
|
|
|
# Update activity service
|
|
activity_service.server_url = server_url
|
|
activity_service.api_key = api_key
|
|
activity_service.user_name = 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")
|
|
|
|
# Close dialog
|
|
self.destroy()
|
|
|
|
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}") |