Refactor SettingsDialog for improved readability and maintainability
- Cleaned up whitespace and formatting throughout the settings_dialog.py file. - Enhanced type hints for better clarity and type checking. - Consolidated URL mapping handling in get_config_data method. - Improved error handling and logging for configuration operations. - Added comments for better understanding of the code structure and functionality.
This commit is contained in:
parent
03991fdea5
commit
986793632e
4 changed files with 468 additions and 480 deletions
|
|
@ -2,10 +2,11 @@
|
|||
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import List, Optional
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
from PySide6.QtCore import Qt
|
||||
from PySide6.QtWidgets import (
|
||||
QComboBox,
|
||||
QDialog,
|
||||
QDialogButtonBox,
|
||||
QFileDialog,
|
||||
|
|
@ -32,7 +33,7 @@ logger = logging.getLogger(__name__)
|
|||
|
||||
class SettingsDialog(QDialog):
|
||||
"""Dialog for managing application settings and configuration.
|
||||
|
||||
|
||||
Provides tabs for:
|
||||
- Paths: Manage allowed root directories
|
||||
- URLs: Manage allowed web URLs
|
||||
|
|
@ -41,9 +42,9 @@ class SettingsDialog(QDialog):
|
|||
- Profiles: Save/load/delete configuration profiles
|
||||
"""
|
||||
|
||||
def __init__(self, config: Config, parent=None):
|
||||
def __init__(self, config: Config, parent: Optional[QWidget] = None):
|
||||
"""Initialize the settings dialog.
|
||||
|
||||
|
||||
Args:
|
||||
config: Current application configuration
|
||||
parent: Parent widget
|
||||
|
|
@ -53,16 +54,16 @@ class SettingsDialog(QDialog):
|
|||
self.profile_manager = ConfigProfile()
|
||||
self.setWindowTitle("Settings")
|
||||
self.setGeometry(100, 100, 600, 500)
|
||||
|
||||
|
||||
self.setup_ui()
|
||||
|
||||
def setup_ui(self) -> None:
|
||||
"""Set up the dialog UI with tabs."""
|
||||
layout = QVBoxLayout()
|
||||
|
||||
|
||||
# Create tab widget
|
||||
self.tabs = QTabWidget()
|
||||
|
||||
|
||||
# Add tabs
|
||||
self.tabs.addTab(self._create_web_source_tab(), "Web Source")
|
||||
self.tabs.addTab(self._create_paths_tab(), "Paths")
|
||||
|
|
@ -70,9 +71,9 @@ class SettingsDialog(QDialog):
|
|||
self.tabs.addTab(self._create_logging_tab(), "Logging")
|
||||
self.tabs.addTab(self._create_window_tab(), "Window")
|
||||
self.tabs.addTab(self._create_profiles_tab(), "Profiles")
|
||||
|
||||
|
||||
layout.addWidget(self.tabs)
|
||||
|
||||
|
||||
# Add buttons
|
||||
button_box = QDialogButtonBox(
|
||||
QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel
|
||||
|
|
@ -80,12 +81,12 @@ class SettingsDialog(QDialog):
|
|||
button_box.accepted.connect(self.accept)
|
||||
button_box.rejected.connect(self.reject)
|
||||
layout.addWidget(button_box)
|
||||
|
||||
|
||||
self.setLayout(layout)
|
||||
|
||||
def accept(self) -> None:
|
||||
"""Handle OK button - save configuration changes to file.
|
||||
|
||||
|
||||
Validates configuration and saves to the default config path.
|
||||
Applies log level changes immediately in the running application.
|
||||
If validation or save fails, shows error and stays in dialog.
|
||||
|
|
@ -93,50 +94,49 @@ class SettingsDialog(QDialog):
|
|||
try:
|
||||
# Get updated configuration data from UI
|
||||
config_data = self.get_config_data()
|
||||
|
||||
|
||||
# Convert URL mappings from dict to URLMapping objects
|
||||
from webdrop_bridge.config import URLMapping
|
||||
|
||||
|
||||
url_mappings = [
|
||||
URLMapping(
|
||||
url_prefix=m["url_prefix"],
|
||||
local_path=m["local_path"]
|
||||
)
|
||||
URLMapping(url_prefix=m["url_prefix"], local_path=m["local_path"])
|
||||
for m in config_data["url_mappings"]
|
||||
]
|
||||
|
||||
|
||||
# Update the config object with new values
|
||||
old_log_level = self.config.log_level
|
||||
self.config.log_level = config_data["log_level"]
|
||||
self.config.log_file = Path(config_data["log_file"]) if config_data["log_file"] else None
|
||||
self.config.log_file = (
|
||||
Path(config_data["log_file"]) if config_data["log_file"] else None
|
||||
)
|
||||
self.config.allowed_roots = [Path(r).resolve() for r in config_data["allowed_roots"]]
|
||||
self.config.allowed_urls = config_data["allowed_urls"]
|
||||
self.config.webapp_url = config_data["webapp_url"]
|
||||
self.config.url_mappings = url_mappings
|
||||
self.config.window_width = config_data["window_width"]
|
||||
self.config.window_height = config_data["window_height"]
|
||||
|
||||
|
||||
# Save to file (creates parent dirs if needed)
|
||||
config_path = Config.get_default_config_path()
|
||||
self.config.to_file(config_path)
|
||||
|
||||
|
||||
logger.info(f"Configuration saved to {config_path}")
|
||||
logger.info(f" Log level: {self.config.log_level} (was: {old_log_level})")
|
||||
logger.info(f" Window size: {self.config.window_width}x{self.config.window_height}")
|
||||
|
||||
|
||||
# Apply log level change immediately to running application
|
||||
if old_log_level != self.config.log_level:
|
||||
logger.info(f"🔄 Updating log level: {old_log_level} → {self.config.log_level}")
|
||||
reconfigure_logging(
|
||||
logger_name="webdrop_bridge",
|
||||
level=self.config.log_level,
|
||||
log_file=self.config.log_file
|
||||
log_file=self.config.log_file,
|
||||
)
|
||||
logger.info(f"✅ Log level updated to {self.config.log_level}")
|
||||
|
||||
|
||||
# Call parent accept to close dialog
|
||||
super().accept()
|
||||
|
||||
|
||||
except ConfigurationError as e:
|
||||
logger.error(f"Configuration error: {e}")
|
||||
self._show_error(f"Configuration Error:\n\n{e}")
|
||||
|
|
@ -147,67 +147,70 @@ class SettingsDialog(QDialog):
|
|||
def _create_web_source_tab(self) -> QWidget:
|
||||
"""Create web source configuration tab."""
|
||||
from PySide6.QtWidgets import QTableWidget, QTableWidgetItem
|
||||
|
||||
|
||||
widget = QWidget()
|
||||
layout = QVBoxLayout()
|
||||
|
||||
|
||||
# Webapp URL configuration
|
||||
layout.addWidget(QLabel("Web Application URL:"))
|
||||
url_layout = QHBoxLayout()
|
||||
|
||||
|
||||
self.webapp_url_input = QLineEdit()
|
||||
self.webapp_url_input.setText(self.config.webapp_url)
|
||||
self.webapp_url_input.setPlaceholderText("e.g., http://localhost:8080 or file:///./webapp/index.html")
|
||||
self.webapp_url_input.setPlaceholderText(
|
||||
"e.g., http://localhost:8080 or file:///./webapp/index.html"
|
||||
)
|
||||
url_layout.addWidget(self.webapp_url_input)
|
||||
|
||||
|
||||
open_btn = QPushButton("Open")
|
||||
open_btn.clicked.connect(self._open_webapp_url)
|
||||
url_layout.addWidget(open_btn)
|
||||
|
||||
|
||||
layout.addLayout(url_layout)
|
||||
|
||||
|
||||
# URL Mappings (Azure Blob URL → Local Path)
|
||||
layout.addWidget(QLabel("URL Mappings (Azure Blob Storage → Local Paths):"))
|
||||
|
||||
|
||||
# Create table for URL mappings
|
||||
self.url_mappings_table = QTableWidget()
|
||||
self.url_mappings_table.setColumnCount(2)
|
||||
self.url_mappings_table.setHorizontalHeaderLabels(["URL Prefix", "Local Path"])
|
||||
self.url_mappings_table.horizontalHeader().setStretchLastSection(True)
|
||||
|
||||
|
||||
# Populate from config
|
||||
for mapping in self.config.url_mappings:
|
||||
row = self.url_mappings_table.rowCount()
|
||||
self.url_mappings_table.insertRow(row)
|
||||
self.url_mappings_table.setItem(row, 0, QTableWidgetItem(mapping.url_prefix))
|
||||
self.url_mappings_table.setItem(row, 1, QTableWidgetItem(mapping.local_path))
|
||||
|
||||
|
||||
layout.addWidget(self.url_mappings_table)
|
||||
|
||||
|
||||
# Buttons for URL mapping management
|
||||
button_layout = QHBoxLayout()
|
||||
|
||||
|
||||
add_mapping_btn = QPushButton("Add Mapping")
|
||||
add_mapping_btn.clicked.connect(self._add_url_mapping)
|
||||
button_layout.addWidget(add_mapping_btn)
|
||||
|
||||
|
||||
edit_mapping_btn = QPushButton("Edit Selected")
|
||||
edit_mapping_btn.clicked.connect(self._edit_url_mapping)
|
||||
button_layout.addWidget(edit_mapping_btn)
|
||||
|
||||
|
||||
remove_mapping_btn = QPushButton("Remove Selected")
|
||||
remove_mapping_btn.clicked.connect(self._remove_url_mapping)
|
||||
button_layout.addWidget(remove_mapping_btn)
|
||||
|
||||
|
||||
layout.addLayout(button_layout)
|
||||
layout.addStretch()
|
||||
|
||||
|
||||
widget.setLayout(layout)
|
||||
return widget
|
||||
|
||||
|
||||
def _open_webapp_url(self) -> None:
|
||||
"""Open the webapp URL in the default browser."""
|
||||
import webbrowser
|
||||
|
||||
url = self.webapp_url_input.text().strip()
|
||||
if url:
|
||||
# Handle file:// URLs
|
||||
|
|
@ -216,61 +219,55 @@ class SettingsDialog(QDialog):
|
|||
except Exception as e:
|
||||
logger.error(f"Failed to open URL: {e}")
|
||||
self._show_error(f"Failed to open URL:\n\n{e}")
|
||||
|
||||
|
||||
def _add_url_mapping(self) -> None:
|
||||
"""Add new URL mapping."""
|
||||
from PySide6.QtWidgets import QInputDialog
|
||||
|
||||
|
||||
url_prefix, ok1 = QInputDialog.getText(
|
||||
self,
|
||||
"Add URL Mapping",
|
||||
"Enter Azure Blob Storage URL prefix:\n(e.g., https://myblob.blob.core.windows.net/container/)"
|
||||
"Enter Azure Blob Storage URL prefix:\n(e.g., https://myblob.blob.core.windows.net/container/)",
|
||||
)
|
||||
|
||||
|
||||
if ok1 and url_prefix:
|
||||
local_path, ok2 = QInputDialog.getText(
|
||||
self,
|
||||
"Add URL Mapping",
|
||||
"Enter local file system path:\n(e.g., C:\\Share or /mnt/share)"
|
||||
"Enter local file system path:\n(e.g., C:\\Share or /mnt/share)",
|
||||
)
|
||||
|
||||
|
||||
if ok2 and local_path:
|
||||
row = self.url_mappings_table.rowCount()
|
||||
self.url_mappings_table.insertRow(row)
|
||||
self.url_mappings_table.setItem(row, 0, QTableWidgetItem(url_prefix))
|
||||
self.url_mappings_table.setItem(row, 1, QTableWidgetItem(local_path))
|
||||
|
||||
|
||||
def _edit_url_mapping(self) -> None:
|
||||
"""Edit selected URL mapping."""
|
||||
from PySide6.QtWidgets import QInputDialog
|
||||
|
||||
|
||||
current_row = self.url_mappings_table.currentRow()
|
||||
if current_row < 0:
|
||||
self._show_error("Please select a mapping to edit")
|
||||
return
|
||||
|
||||
url_prefix = self.url_mappings_table.item(current_row, 0).text()
|
||||
local_path = self.url_mappings_table.item(current_row, 1).text()
|
||||
|
||||
|
||||
url_prefix = self.url_mappings_table.item(current_row, 0).text() # type: ignore
|
||||
local_path = self.url_mappings_table.item(current_row, 1).text() # type: ignore
|
||||
|
||||
new_url_prefix, ok1 = QInputDialog.getText(
|
||||
self,
|
||||
"Edit URL Mapping",
|
||||
"Enter Azure Blob Storage URL prefix:",
|
||||
text=url_prefix
|
||||
self, "Edit URL Mapping", "Enter Azure Blob Storage URL prefix:", text=url_prefix
|
||||
)
|
||||
|
||||
|
||||
if ok1 and new_url_prefix:
|
||||
new_local_path, ok2 = QInputDialog.getText(
|
||||
self,
|
||||
"Edit URL Mapping",
|
||||
"Enter local file system path:",
|
||||
text=local_path
|
||||
self, "Edit URL Mapping", "Enter local file system path:", text=local_path
|
||||
)
|
||||
|
||||
|
||||
if ok2 and new_local_path:
|
||||
self.url_mappings_table.setItem(current_row, 0, QTableWidgetItem(new_url_prefix))
|
||||
self.url_mappings_table.setItem(current_row, 1, QTableWidgetItem(new_local_path))
|
||||
|
||||
|
||||
def _remove_url_mapping(self) -> None:
|
||||
"""Remove selected URL mapping."""
|
||||
current_row = self.url_mappings_table.currentRow()
|
||||
|
|
@ -281,29 +278,29 @@ class SettingsDialog(QDialog):
|
|||
"""Create paths configuration tab."""
|
||||
widget = QWidget()
|
||||
layout = QVBoxLayout()
|
||||
|
||||
|
||||
layout.addWidget(QLabel("Allowed root directories for file access:"))
|
||||
|
||||
|
||||
# List widget for paths
|
||||
self.paths_list = QListWidget()
|
||||
for path in self.config.allowed_roots:
|
||||
self.paths_list.addItem(str(path))
|
||||
layout.addWidget(self.paths_list)
|
||||
|
||||
|
||||
# Buttons for path management
|
||||
button_layout = QHBoxLayout()
|
||||
|
||||
|
||||
add_path_btn = QPushButton("Add Path")
|
||||
add_path_btn.clicked.connect(self._add_path)
|
||||
button_layout.addWidget(add_path_btn)
|
||||
|
||||
|
||||
remove_path_btn = QPushButton("Remove Selected")
|
||||
remove_path_btn.clicked.connect(self._remove_path)
|
||||
button_layout.addWidget(remove_path_btn)
|
||||
|
||||
|
||||
layout.addLayout(button_layout)
|
||||
layout.addStretch()
|
||||
|
||||
|
||||
widget.setLayout(layout)
|
||||
return widget
|
||||
|
||||
|
|
@ -311,29 +308,29 @@ class SettingsDialog(QDialog):
|
|||
"""Create URLs configuration tab."""
|
||||
widget = QWidget()
|
||||
layout = QVBoxLayout()
|
||||
|
||||
|
||||
layout.addWidget(QLabel("Allowed web URLs (supports wildcards like http://*.example.com):"))
|
||||
|
||||
|
||||
# List widget for URLs
|
||||
self.urls_list = QListWidget()
|
||||
for url in self.config.allowed_urls:
|
||||
self.urls_list.addItem(url)
|
||||
layout.addWidget(self.urls_list)
|
||||
|
||||
|
||||
# Buttons for URL management
|
||||
button_layout = QHBoxLayout()
|
||||
|
||||
|
||||
add_url_btn = QPushButton("Add URL")
|
||||
add_url_btn.clicked.connect(self._add_url)
|
||||
button_layout.addWidget(add_url_btn)
|
||||
|
||||
|
||||
remove_url_btn = QPushButton("Remove Selected")
|
||||
remove_url_btn.clicked.connect(self._remove_url)
|
||||
button_layout.addWidget(remove_url_btn)
|
||||
|
||||
|
||||
layout.addLayout(button_layout)
|
||||
layout.addStretch()
|
||||
|
||||
|
||||
widget.setLayout(layout)
|
||||
return widget
|
||||
|
||||
|
|
@ -341,27 +338,28 @@ class SettingsDialog(QDialog):
|
|||
"""Create logging configuration tab."""
|
||||
widget = QWidget()
|
||||
layout = QVBoxLayout()
|
||||
|
||||
|
||||
# Log level selection
|
||||
layout.addWidget(QLabel("Log Level:"))
|
||||
from PySide6.QtWidgets import QComboBox
|
||||
|
||||
self.log_level_combo: QComboBox = self._create_log_level_widget()
|
||||
layout.addWidget(self.log_level_combo)
|
||||
|
||||
|
||||
# Log file path
|
||||
layout.addWidget(QLabel("Log File (optional):"))
|
||||
log_file_layout = QHBoxLayout()
|
||||
|
||||
|
||||
self.log_file_input = QLineEdit()
|
||||
self.log_file_input.setText(str(self.config.log_file) if self.config.log_file else "")
|
||||
log_file_layout.addWidget(self.log_file_input)
|
||||
|
||||
|
||||
browse_btn = QPushButton("Browse...")
|
||||
browse_btn.clicked.connect(self._browse_log_file)
|
||||
log_file_layout.addWidget(browse_btn)
|
||||
|
||||
|
||||
layout.addLayout(log_file_layout)
|
||||
|
||||
|
||||
layout.addStretch()
|
||||
widget.setLayout(layout)
|
||||
return widget
|
||||
|
|
@ -370,7 +368,7 @@ class SettingsDialog(QDialog):
|
|||
"""Create window settings tab."""
|
||||
widget = QWidget()
|
||||
layout = QVBoxLayout()
|
||||
|
||||
|
||||
# Window width
|
||||
width_layout = QHBoxLayout()
|
||||
width_layout.addWidget(QLabel("Window Width:"))
|
||||
|
|
@ -381,7 +379,7 @@ class SettingsDialog(QDialog):
|
|||
width_layout.addWidget(self.width_spin)
|
||||
width_layout.addStretch()
|
||||
layout.addLayout(width_layout)
|
||||
|
||||
|
||||
# Window height
|
||||
height_layout = QHBoxLayout()
|
||||
height_layout.addWidget(QLabel("Window Height:"))
|
||||
|
|
@ -392,7 +390,7 @@ class SettingsDialog(QDialog):
|
|||
height_layout.addWidget(self.height_spin)
|
||||
height_layout.addStretch()
|
||||
layout.addLayout(height_layout)
|
||||
|
||||
|
||||
layout.addStretch()
|
||||
widget.setLayout(layout)
|
||||
return widget
|
||||
|
|
@ -401,52 +399,50 @@ class SettingsDialog(QDialog):
|
|||
"""Create profiles management tab."""
|
||||
widget = QWidget()
|
||||
layout = QVBoxLayout()
|
||||
|
||||
|
||||
layout.addWidget(QLabel("Saved Configuration Profiles:"))
|
||||
|
||||
|
||||
# List of profiles
|
||||
self.profiles_list = QListWidget()
|
||||
self._refresh_profiles_list()
|
||||
layout.addWidget(self.profiles_list)
|
||||
|
||||
|
||||
# Profile management buttons
|
||||
button_layout = QHBoxLayout()
|
||||
|
||||
|
||||
save_profile_btn = QPushButton("Save as Profile")
|
||||
save_profile_btn.clicked.connect(self._save_profile)
|
||||
button_layout.addWidget(save_profile_btn)
|
||||
|
||||
|
||||
load_profile_btn = QPushButton("Load Profile")
|
||||
load_profile_btn.clicked.connect(self._load_profile)
|
||||
button_layout.addWidget(load_profile_btn)
|
||||
|
||||
|
||||
delete_profile_btn = QPushButton("Delete Profile")
|
||||
delete_profile_btn.clicked.connect(self._delete_profile)
|
||||
button_layout.addWidget(delete_profile_btn)
|
||||
|
||||
|
||||
layout.addLayout(button_layout)
|
||||
|
||||
|
||||
# Export/Import buttons
|
||||
export_layout = QHBoxLayout()
|
||||
|
||||
|
||||
export_btn = QPushButton("Export Configuration")
|
||||
export_btn.clicked.connect(self._export_config)
|
||||
export_layout.addWidget(export_btn)
|
||||
|
||||
|
||||
import_btn = QPushButton("Import Configuration")
|
||||
import_btn.clicked.connect(self._import_config)
|
||||
export_layout.addWidget(import_btn)
|
||||
|
||||
|
||||
layout.addLayout(export_layout)
|
||||
layout.addStretch()
|
||||
|
||||
|
||||
widget.setLayout(layout)
|
||||
return widget
|
||||
|
||||
def _create_log_level_widget(self):
|
||||
def _create_log_level_widget(self) -> QComboBox:
|
||||
"""Create log level selection widget."""
|
||||
from PySide6.QtWidgets import QComboBox
|
||||
|
||||
combo = QComboBox()
|
||||
levels = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
|
||||
combo.addItems(levels)
|
||||
|
|
@ -467,11 +463,9 @@ class SettingsDialog(QDialog):
|
|||
def _add_url(self) -> None:
|
||||
"""Add a new allowed URL."""
|
||||
from PySide6.QtWidgets import QInputDialog
|
||||
|
||||
|
||||
url, ok = QInputDialog.getText(
|
||||
self,
|
||||
"Add URL",
|
||||
"Enter URL pattern (e.g., http://example.com or http://*.example.com):"
|
||||
self, "Add URL", "Enter URL pattern (e.g., http://example.com or http://*.example.com):"
|
||||
)
|
||||
if ok and url:
|
||||
self.urls_list.addItem(url)
|
||||
|
|
@ -484,10 +478,7 @@ class SettingsDialog(QDialog):
|
|||
def _browse_log_file(self) -> None:
|
||||
"""Browse for log file location."""
|
||||
file_path, _ = QFileDialog.getSaveFileName(
|
||||
self,
|
||||
"Select Log File",
|
||||
str(Path.home()),
|
||||
"Log Files (*.log);;All Files (*)"
|
||||
self, "Select Log File", str(Path.home()), "Log Files (*.log);;All Files (*)"
|
||||
)
|
||||
if file_path:
|
||||
self.log_file_input.setText(file_path)
|
||||
|
|
@ -501,13 +492,11 @@ class SettingsDialog(QDialog):
|
|||
def _save_profile(self) -> None:
|
||||
"""Save current configuration as a profile."""
|
||||
from PySide6.QtWidgets import QInputDialog
|
||||
|
||||
|
||||
profile_name, ok = QInputDialog.getText(
|
||||
self,
|
||||
"Save Profile",
|
||||
"Enter profile name (e.g., work, personal):"
|
||||
self, "Save Profile", "Enter profile name (e.g., work, personal):"
|
||||
)
|
||||
|
||||
|
||||
if ok and profile_name:
|
||||
try:
|
||||
self.profile_manager.save_profile(profile_name, self.config)
|
||||
|
|
@ -521,7 +510,7 @@ class SettingsDialog(QDialog):
|
|||
if not current_item:
|
||||
self._show_error("Please select a profile to load")
|
||||
return
|
||||
|
||||
|
||||
profile_name = current_item.text()
|
||||
try:
|
||||
config_data = self.profile_manager.load_profile(profile_name)
|
||||
|
|
@ -535,7 +524,7 @@ class SettingsDialog(QDialog):
|
|||
if not current_item:
|
||||
self._show_error("Please select a profile to delete")
|
||||
return
|
||||
|
||||
|
||||
profile_name = current_item.text()
|
||||
try:
|
||||
self.profile_manager.delete_profile(profile_name)
|
||||
|
|
@ -546,12 +535,9 @@ class SettingsDialog(QDialog):
|
|||
def _export_config(self) -> None:
|
||||
"""Export configuration to file."""
|
||||
file_path, _ = QFileDialog.getSaveFileName(
|
||||
self,
|
||||
"Export Configuration",
|
||||
str(Path.home()),
|
||||
"JSON Files (*.json);;All Files (*)"
|
||||
self, "Export Configuration", str(Path.home()), "JSON Files (*.json);;All Files (*)"
|
||||
)
|
||||
|
||||
|
||||
if file_path:
|
||||
try:
|
||||
ConfigExporter.export_to_json(self.config, Path(file_path))
|
||||
|
|
@ -561,12 +547,9 @@ class SettingsDialog(QDialog):
|
|||
def _import_config(self) -> None:
|
||||
"""Import configuration from file."""
|
||||
file_path, _ = QFileDialog.getOpenFileName(
|
||||
self,
|
||||
"Import Configuration",
|
||||
str(Path.home()),
|
||||
"JSON Files (*.json);;All Files (*)"
|
||||
self, "Import Configuration", str(Path.home()), "JSON Files (*.json);;All Files (*)"
|
||||
)
|
||||
|
||||
|
||||
if file_path:
|
||||
try:
|
||||
config_data = ConfigExporter.import_from_json(Path(file_path))
|
||||
|
|
@ -574,9 +557,9 @@ class SettingsDialog(QDialog):
|
|||
except ConfigurationError as e:
|
||||
self._show_error(f"Failed to import configuration: {e}")
|
||||
|
||||
def _apply_config_data(self, config_data: dict) -> None:
|
||||
def _apply_config_data(self, config_data: Dict[str, Any]) -> None:
|
||||
"""Apply imported configuration data to UI.
|
||||
|
||||
|
||||
Args:
|
||||
config_data: Configuration dictionary
|
||||
"""
|
||||
|
|
@ -584,60 +567,67 @@ class SettingsDialog(QDialog):
|
|||
self.paths_list.clear()
|
||||
for path in config_data.get("allowed_roots", []):
|
||||
self.paths_list.addItem(str(path))
|
||||
|
||||
|
||||
# Apply URLs
|
||||
self.urls_list.clear()
|
||||
for url in config_data.get("allowed_urls", []):
|
||||
self.urls_list.addItem(url)
|
||||
|
||||
|
||||
# Apply logging settings
|
||||
self.log_level_combo.setCurrentText(config_data.get("log_level", "INFO"))
|
||||
log_file = config_data.get("log_file")
|
||||
self.log_file_input.setText(str(log_file) if log_file else "")
|
||||
|
||||
|
||||
# Apply window settings
|
||||
self.width_spin.setValue(config_data.get("window_width", 800))
|
||||
self.height_spin.setValue(config_data.get("window_height", 600))
|
||||
|
||||
def get_config_data(self) -> dict:
|
||||
def get_config_data(self) -> Dict[str, Any]:
|
||||
"""Get updated configuration data from dialog.
|
||||
|
||||
|
||||
Returns:
|
||||
Configuration dictionary
|
||||
|
||||
|
||||
Raises:
|
||||
ConfigurationError: If configuration is invalid
|
||||
"""
|
||||
if self.url_mappings_table:
|
||||
url_mappings_table_count = self.url_mappings_table.rowCount() or 0
|
||||
else:
|
||||
url_mappings_table_count = 0
|
||||
config_data = {
|
||||
"app_name": self.config.app_name,
|
||||
"app_version": self.config.app_version,
|
||||
"log_level": self.log_level_combo.currentText(),
|
||||
"log_file": self.log_file_input.text() or None,
|
||||
"allowed_roots": [self.paths_list.item(i).text() for i in range(self.paths_list.count())],
|
||||
"allowed_roots": [
|
||||
self.paths_list.item(i).text() for i in range(self.paths_list.count())
|
||||
],
|
||||
"allowed_urls": [self.urls_list.item(i).text() for i in range(self.urls_list.count())],
|
||||
"webapp_url": self.webapp_url_input.text().strip(),
|
||||
"url_mappings": [
|
||||
{
|
||||
"url_prefix": self.url_mappings_table.item(i, 0).text(),
|
||||
"local_path": self.url_mappings_table.item(i, 1).text()
|
||||
"url_prefix": self.url_mappings_table.item(i, 0).text() if self.url_mappings_table.item(i, 0) else "", # type: ignore
|
||||
"local_path": self.url_mappings_table.item(i, 1).text() if self.url_mappings_table.item(i, 1) else "", # type: ignore
|
||||
}
|
||||
for i in range(self.url_mappings_table.rowCount())
|
||||
for i in range(url_mappings_table_count)
|
||||
],
|
||||
"window_width": self.width_spin.value(),
|
||||
"window_height": self.height_spin.value(),
|
||||
"enable_logging": self.config.enable_logging,
|
||||
}
|
||||
|
||||
|
||||
# Validate
|
||||
ConfigValidator.validate_or_raise(config_data)
|
||||
|
||||
|
||||
return config_data
|
||||
|
||||
def _show_error(self, message: str) -> None:
|
||||
"""Show error message to user.
|
||||
|
||||
|
||||
Args:
|
||||
message: Error message
|
||||
"""
|
||||
from PySide6.QtWidgets import QMessageBox
|
||||
|
||||
QMessageBox.critical(self, "Error", message)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue