Feature: Konfigurierbare Worker-Anzahl für parallele Transformationen

Fügt UI-Element und Einstellung für max_workers hinzu:

Änderungen:
- AppSettings.max_workers Feld hinzugefügt (Standard: 8 Worker)
- Menü-Item "Performance-Einstellungen..." im Projekt-Menü
- QInputDialog zum einfachen Ändern der Worker-Anzahl (1-32)
- TransformationThread verwendet jetzt app_settings.max_workers
- Tooltip zeigt aktuelle Worker-Anzahl an

Benutzung:
1. Projekt-Menü → Performance-Einstellungen...
2. Worker-Anzahl eingeben (empfohlen: 8-12 für 16-Kern-System)
3. Einstellung wird sofort gespeichert
4. Beim nächsten Transformation aktiv

Alternative: max_workers direkt in config.json ändern

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-28 13:19:47 +01:00
parent 2daa77e85d
commit 5ecad6ce89
2 changed files with 54 additions and 8 deletions
+9 -7
View File
@@ -62,8 +62,8 @@ class XslDir(BaseModel):
id: int id: int
name: str name: str
path_to_root_dir: Path path_to_root_dir: Path
class SSLMode(str, Enum): class SSLMode(str, Enum):
DISABLE = "disable" DISABLE = "disable"
ALLOW = "allow" ALLOW = "allow"
@@ -72,6 +72,7 @@ class SSLMode(str, Enum):
VERIFY_CA = "verify-ca" VERIFY_CA = "verify-ca"
VERIFY_FULL = "verify-full" VERIFY_FULL = "verify-full"
class PostgreSqlDb(BaseModel): class PostgreSqlDb(BaseModel):
id: int id: int
name: str name: str
@@ -141,6 +142,7 @@ class AppSettings(BaseSettings):
pdf_projects: list[Project] = [] pdf_projects: list[Project] = []
postgresql_dbs: list[PostgreSqlDb] = [] postgresql_dbs: list[PostgreSqlDb] = []
theme: str | None = None theme: str | None = None
max_workers: int = 8 # Anzahl paralleler Worker für Transformationen (Standard: 8)
# UI-Zustand # UI-Zustand
window_geometry: tuple[int, int, int, int] | None = None # (x, y, width, height) window_geometry: tuple[int, int, int, int] | None = None # (x, y, width, height)
@@ -165,7 +167,7 @@ class AppSettings(BaseSettings):
# Ordner existert nicht # Ordner existert nicht
if not config_path.parent.exists(): if not config_path.parent.exists():
config_path.parent.mkdir(parents=True, exist_ok=True) config_path.parent.mkdir(parents=True, exist_ok=True)
if not config_path.parent.is_dir() or not os.access(config_path.parent, os.W_OK): if not config_path.parent.is_dir() or not os.access(config_path.parent, os.W_OK):
logger.exception(f"{config_path.parent} ist kein Verzeichnis oder es gibt keine Schreibrechte") logger.exception(f"{config_path.parent} ist kein Verzeichnis oder es gibt keine Schreibrechte")
sys.exit(1) sys.exit(1)
@@ -205,16 +207,16 @@ class ProjectData(BaseModel):
""" """
nodes: list[TreeNode] = [] nodes: list[TreeNode] = []
@classmethod @classmethod
def readSettings(cls, project_dir: Path): def readSettings(cls, project_dir: Path):
# Explizit UTF-8 Encoding verwenden # Explizit UTF-8 Encoding verwenden
project_yaml_path = project_dir / "project.yaml" project_yaml_path = project_dir / "project.yaml"
with open(project_yaml_path, 'r', encoding='utf-8') as f: with open(project_yaml_path, "r", encoding="utf-8") as f:
yaml = YAML(typ='safe') yaml = YAML(typ="safe")
yaml_data = yaml.load(f) yaml_data = yaml.load(f)
return cls.model_validate(yaml_data) return cls.model_validate(yaml_data)
def writeSettings(self, project_dir: Path): def writeSettings(self, project_dir: Path):
with open(project_dir / "project.yaml", "w", encoding="utf8") as f: with open(project_dir / "project.yaml", "w", encoding="utf8") as f:
f.write(to_yaml_str(self)) f.write(to_yaml_str(self))
+45 -1
View File
@@ -549,6 +549,9 @@ class MainWindow(QMainWindow):
# Vorhandene Projekte-Menü initialisieren # Vorhandene Projekte-Menü initialisieren
self._setup_projects_menu() self._setup_projects_menu()
# Performance-Einstellungen-Menü initialisieren
self._setup_performance_menu()
# #
if theme := app_settings.theme: if theme := app_settings.theme:
self.change_theme(theme) self.change_theme(theme)
@@ -644,6 +647,47 @@ class MainWindow(QMainWindow):
logger.info(f"Projekte-Menü initialisiert mit {len(app_settings.pdf_projects)} Projekten") logger.info(f"Projekte-Menü initialisiert mit {len(app_settings.pdf_projects)} Projekten")
def _setup_performance_menu(self):
"""Fügt ein Menü-Item für Performance-Einstellungen hinzu."""
# Füge Separator vor der Performance-Einstellung hinzu
self.ui.menuProjekt.addSeparator()
# Erstelle Aktion für Performance-Einstellungen
performance_action = QAction("Performance-Einstellungen...", self)
performance_action.setToolTip(f"Parallele Worker: {app_settings.max_workers}")
performance_action.triggered.connect(self._open_performance_settings)
# Füge die Aktion zum Projekt-Menü hinzu
self.ui.menuProjekt.addAction(performance_action)
logger.debug(f"Performance-Menü initialisiert (max_workers={app_settings.max_workers})")
def _open_performance_settings(self):
"""Öffnet einen Dialog für Performance-Einstellungen."""
from PySide6.QtWidgets import QInputDialog
current_workers = app_settings.max_workers
new_workers, ok = QInputDialog.getInt(
self,
"Performance-Einstellungen",
"Anzahl paralleler Worker für Transformationen:",
current_workers, # value
1, # minValue
32, # maxValue
1, # step
)
if ok and new_workers != current_workers:
app_settings.max_workers = new_workers
app_settings.save()
logger.info(f"max_workers geändert: {current_workers}{new_workers}")
QMessageBox.information(
self,
"Einstellungen gespeichert",
f"Anzahl paralleler Worker wurde auf {new_workers} gesetzt.\n\n"
f"Die Änderung wird bei der nächsten Transformation wirksam.",
)
def open_existing_project(self, project: Project): def open_existing_project(self, project: Project):
""" """
Öffnet ein vorhandenes Projekt. Öffnet ein vorhandenes Projekt.
@@ -3970,7 +4014,7 @@ class MainWindow(QMainWindow):
return return
# Erstelle und konfiguriere Thread # Erstelle und konfiguriere Thread
self.transformation_thread = TransformationThread(jobs, force=force) self.transformation_thread = TransformationThread(jobs, force=force, max_workers=app_settings.max_workers)
# Verbinde Signale # Verbinde Signale
self.transformation_thread.job_started.connect(self._on_transformation_job_started) self.transformation_thread.job_started.connect(self._on_transformation_job_started)