UX: Performance-Einstellungen in Programmeinstellungen integriert
Performance-Einstellungen wurden vom separaten Menüeintrag in den Programmeinstellungen-Dialog als eigener Tab verschoben: - Neuer "Performance"-Tab in AppSettings.ui mit drei Konfigurationsbereichen: • ThreadPoolExecutor: Worker-Anzahl (1-32, Standard: 8) • SaxonWorkerPool: Toggle für persistente JVM-Prozesse • FopWorkerPool: Toggle für persistente JVM-Prozesse - AppSettings.py erweitert: • _populate_performance_tab(): Lädt aktuelle Performance-Einstellungen • accept(): Speichert Performance-Einstellungen in app_settings - MainWindow.py bereinigt: • _setup_performance_menu() entfernt • _open_performance_settings() entfernt • Separater Menüeintrag im Projekt-Menü entfernt - AppSettings_ui.py mit pyside6-uic neu generiert Vorteile: Alle Programmeinstellungen sind nun zentral an einem Ort verfügbar, bessere Benutzererfahrung durch konsistente UI-Struktur. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -7,8 +7,8 @@ Spreche mit mir auf Deutsch! (Communicate with me in German!)
|
||||
DocuMentor (ehemals xsl-validator) ist eine PySide6-basierte Desktop-Anwendung zur Verwaltung und Validierung von XSL-Transformationen mit XML-Dateien. Sie bietet eine GUI zur Konfiguration von Transformations-Toolchains (Saxon, Apache FOP, diff-pdf) und zur Verwaltung von PDF-Generierungsprojekten mit PostgreSQL-Datenbankintegration.
|
||||
|
||||
## PySide6-GUI
|
||||
- Beim Erstellen neuer Dialoge sollte immer eine passende UI-Datei erstellt werden
|
||||
- Der Entwickler sollte später in der Lage sein, den neuen Dialog über die UI-Datei zu gestalten
|
||||
- Beim Erstellen neuer Dialoge und Fenster sollte immer eine entsprechende UI-Datei erstellt werden
|
||||
- Der Entwickler sollte später in der Lage sein, den neuen Dialog bzw. Fenster über diese UI-Datei zu gestalten
|
||||
- Aus der UI-Datei wird in Visual Studio Code über eine Erweiterung automatisch eine .py-Datei erzeugt
|
||||
- Die automatisch generierte .py-Datei muss in den Code eingebunden und verwendet werden
|
||||
|
||||
|
||||
@@ -46,6 +46,9 @@ class AppSettingsDlg(QDialog):
|
||||
self._setup_tables()
|
||||
self._populate_tables()
|
||||
|
||||
# Performance-Tab initialisieren
|
||||
self._populate_performance_tab()
|
||||
|
||||
def _connect_signals(self):
|
||||
"""Verbindet die Signale der UI-Elemente."""
|
||||
# XSL-Ordner Tab
|
||||
@@ -271,6 +274,17 @@ class AppSettingsDlg(QDialog):
|
||||
self.ui.tablePostgreSqlDbs.setItem(row, 4, username_item)
|
||||
self.ui.tablePostgreSqlDbs.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents)
|
||||
|
||||
def _populate_performance_tab(self):
|
||||
"""Initialisiert den Performance-Tab mit den aktuellen Einstellungen."""
|
||||
# Worker-Anzahl setzen
|
||||
self.ui.spinBoxWorkerCount.setValue(self.settings.max_workers)
|
||||
|
||||
# SaxonWorkerPool-Checkbox setzen
|
||||
self.ui.checkBoxUseSaxonPool.setChecked(self.settings.use_saxon_worker_pool)
|
||||
|
||||
# FopWorkerPool-Checkbox setzen
|
||||
self.ui.checkBoxUseFopPool.setChecked(self.settings.use_fop_worker_pool)
|
||||
|
||||
# XSL-Ordner Methoden
|
||||
def _add_xsl_dir(self):
|
||||
"""Fügt einen neuen XSL-Ordner hinzu."""
|
||||
@@ -723,6 +737,11 @@ class AppSettingsDlg(QDialog):
|
||||
self.settings.xsl_dirs = self.temp_xsl_dirs.copy()
|
||||
self.settings.pdf_projects = self.temp_pdf_projects.copy()
|
||||
|
||||
# Performance-Einstellungen übernehmen
|
||||
self.settings.max_workers = self.ui.spinBoxWorkerCount.value()
|
||||
self.settings.use_saxon_worker_pool = self.ui.checkBoxUseSaxonPool.isChecked()
|
||||
self.settings.use_fop_worker_pool = self.ui.checkBoxUseFopPool.isChecked()
|
||||
|
||||
self.settings.save()
|
||||
|
||||
super().accept()
|
||||
|
||||
+141
-1
@@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>833</width>
|
||||
<height>387</height>
|
||||
<height>446</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -520,6 +520,146 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabPerformance">
|
||||
<attribute name="title">
|
||||
<string>Performance</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBoxWorker">
|
||||
<property name="title">
|
||||
<string>ThreadPoolExecutor Einstellungen</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_10">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelWorkerCount">
|
||||
<property name="text">
|
||||
<string>Anzahl paralleler Worker für Transformationen:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinBoxWorkerCount">
|
||||
<property name="toolTip">
|
||||
<string>Anzahl der parallelen Worker-Threads für Transformationen (Standard: 8)</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>32</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>8</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBoxSaxonPool">
|
||||
<property name="title">
|
||||
<string>SaxonWorkerPool Einstellungen</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_11">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxUseSaxonPool">
|
||||
<property name="toolTip">
|
||||
<string>Aktiviert persistente JVM-Prozesse für Saxon-Transformationen.
|
||||
Vorteile: Bis zu 10x schneller durch Eliminierung von JVM-Startup-Overhead
|
||||
Nachteile: Benötigt JDK (javac) - funktioniert nicht mit JRE allein
|
||||
|
||||
Deaktivieren Sie diese Option, wenn:
|
||||
• Sie nur ein JRE (keine JDK) installiert haben
|
||||
• Sie Probleme mit dem Worker-Pool haben
|
||||
• Sie die Funktion testen möchten</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>SaxonWorkerPool verwenden (empfohlen)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelSaxonPoolInfo">
|
||||
<property name="text">
|
||||
<string><i>Hinweis: SaxonWorkerPool benötigt ein JDK (Java Development Kit).<br>Mit JRE allein werden Transformationen im Fallback-Modus ausgeführt.</i></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBoxFopPool">
|
||||
<property name="title">
|
||||
<string>FopWorkerPool Einstellungen</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_12">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxUseFopPool">
|
||||
<property name="toolTip">
|
||||
<string>Aktiviert persistente JVM-Prozesse für Apache FOP PDF-Generierung.
|
||||
Vorteile: Bis zu 10x schneller durch Eliminierung von JVM-Startup-Overhead
|
||||
Nachteile: Benötigt JDK (javac) - funktioniert nicht mit JRE allein
|
||||
|
||||
Deaktivieren Sie diese Option, wenn:
|
||||
• Sie nur ein JRE (keine JDK) installiert haben
|
||||
• Sie Probleme mit dem Worker-Pool haben
|
||||
• Sie die Funktion testen möchten</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>FopWorkerPool verwenden (empfohlen)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelFopPoolInfo">
|
||||
<property name="text">
|
||||
<string><i>Hinweis: FopWorkerPool benötigt ein JDK (Java Development Kit).<br>Mit JRE allein werden PDFs im Fallback-Modus generiert.</i></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="mouseTracking">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><span style=" font-weight:700; font-style:italic;">Hinweis: Änderungen in diesem Dialog sind unter Umständen erst nach neu start der Anwendung wirksam.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacerPerformance">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
||||
+113
-6
@@ -3,7 +3,7 @@
|
||||
################################################################################
|
||||
## Form generated from reading UI file 'AppSettings.ui'
|
||||
##
|
||||
## Created by: Qt User Interface Compiler version 6.9.1
|
||||
## Created by: Qt User Interface Compiler version 6.9.2
|
||||
##
|
||||
## WARNING! All changes made in this file will be lost when recompiling UI file!
|
||||
################################################################################
|
||||
@@ -15,16 +15,17 @@ from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
|
||||
QFont, QFontDatabase, QGradient, QIcon,
|
||||
QImage, QKeySequence, QLinearGradient, QPainter,
|
||||
QPalette, QPixmap, QRadialGradient, QTransform)
|
||||
from PySide6.QtWidgets import (QAbstractButton, QApplication, QDialog, QDialogButtonBox,
|
||||
QFrame, QHBoxLayout, QHeaderView, QPushButton,
|
||||
QSizePolicy, QTabWidget, QTableWidget, QTableWidgetItem,
|
||||
QVBoxLayout, QWidget)
|
||||
from PySide6.QtWidgets import (QAbstractButton, QApplication, QCheckBox, QDialog,
|
||||
QDialogButtonBox, QFrame, QGroupBox, QHBoxLayout,
|
||||
QHeaderView, QLabel, QPushButton, QSizePolicy,
|
||||
QSpacerItem, QSpinBox, QTabWidget, QTableWidget,
|
||||
QTableWidgetItem, QVBoxLayout, QWidget)
|
||||
|
||||
class Ui_Dialog(object):
|
||||
def setupUi(self, Dialog):
|
||||
if not Dialog.objectName():
|
||||
Dialog.setObjectName(u"Dialog")
|
||||
Dialog.resize(833, 387)
|
||||
Dialog.resize(833, 446)
|
||||
self.verticalLayout = QVBoxLayout(Dialog)
|
||||
self.verticalLayout.setObjectName(u"verticalLayout")
|
||||
self.tabSettings = QTabWidget(Dialog)
|
||||
@@ -302,6 +303,79 @@ class Ui_Dialog(object):
|
||||
self.verticalLayout_7.addWidget(self.frame_6)
|
||||
|
||||
self.tabSettings.addTab(self.tabPdfProject, "")
|
||||
self.tabPerformance = QWidget()
|
||||
self.tabPerformance.setObjectName(u"tabPerformance")
|
||||
self.verticalLayout_9 = QVBoxLayout(self.tabPerformance)
|
||||
self.verticalLayout_9.setObjectName(u"verticalLayout_9")
|
||||
self.groupBoxWorker = QGroupBox(self.tabPerformance)
|
||||
self.groupBoxWorker.setObjectName(u"groupBoxWorker")
|
||||
self.verticalLayout_10 = QVBoxLayout(self.groupBoxWorker)
|
||||
self.verticalLayout_10.setObjectName(u"verticalLayout_10")
|
||||
self.labelWorkerCount = QLabel(self.groupBoxWorker)
|
||||
self.labelWorkerCount.setObjectName(u"labelWorkerCount")
|
||||
|
||||
self.verticalLayout_10.addWidget(self.labelWorkerCount)
|
||||
|
||||
self.spinBoxWorkerCount = QSpinBox(self.groupBoxWorker)
|
||||
self.spinBoxWorkerCount.setObjectName(u"spinBoxWorkerCount")
|
||||
self.spinBoxWorkerCount.setMinimum(1)
|
||||
self.spinBoxWorkerCount.setMaximum(32)
|
||||
self.spinBoxWorkerCount.setValue(8)
|
||||
|
||||
self.verticalLayout_10.addWidget(self.spinBoxWorkerCount)
|
||||
|
||||
|
||||
self.verticalLayout_9.addWidget(self.groupBoxWorker)
|
||||
|
||||
self.groupBoxSaxonPool = QGroupBox(self.tabPerformance)
|
||||
self.groupBoxSaxonPool.setObjectName(u"groupBoxSaxonPool")
|
||||
self.verticalLayout_11 = QVBoxLayout(self.groupBoxSaxonPool)
|
||||
self.verticalLayout_11.setObjectName(u"verticalLayout_11")
|
||||
self.checkBoxUseSaxonPool = QCheckBox(self.groupBoxSaxonPool)
|
||||
self.checkBoxUseSaxonPool.setObjectName(u"checkBoxUseSaxonPool")
|
||||
|
||||
self.verticalLayout_11.addWidget(self.checkBoxUseSaxonPool)
|
||||
|
||||
self.labelSaxonPoolInfo = QLabel(self.groupBoxSaxonPool)
|
||||
self.labelSaxonPoolInfo.setObjectName(u"labelSaxonPoolInfo")
|
||||
self.labelSaxonPoolInfo.setWordWrap(True)
|
||||
|
||||
self.verticalLayout_11.addWidget(self.labelSaxonPoolInfo)
|
||||
|
||||
|
||||
self.verticalLayout_9.addWidget(self.groupBoxSaxonPool)
|
||||
|
||||
self.groupBoxFopPool = QGroupBox(self.tabPerformance)
|
||||
self.groupBoxFopPool.setObjectName(u"groupBoxFopPool")
|
||||
self.verticalLayout_12 = QVBoxLayout(self.groupBoxFopPool)
|
||||
self.verticalLayout_12.setObjectName(u"verticalLayout_12")
|
||||
self.checkBoxUseFopPool = QCheckBox(self.groupBoxFopPool)
|
||||
self.checkBoxUseFopPool.setObjectName(u"checkBoxUseFopPool")
|
||||
|
||||
self.verticalLayout_12.addWidget(self.checkBoxUseFopPool)
|
||||
|
||||
self.labelFopPoolInfo = QLabel(self.groupBoxFopPool)
|
||||
self.labelFopPoolInfo.setObjectName(u"labelFopPoolInfo")
|
||||
self.labelFopPoolInfo.setWordWrap(True)
|
||||
|
||||
self.verticalLayout_12.addWidget(self.labelFopPoolInfo)
|
||||
|
||||
|
||||
self.verticalLayout_9.addWidget(self.groupBoxFopPool)
|
||||
|
||||
self.label = QLabel(self.tabPerformance)
|
||||
self.label.setObjectName(u"label")
|
||||
self.label.setMouseTracking(True)
|
||||
self.label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
self.label.setWordWrap(True)
|
||||
|
||||
self.verticalLayout_9.addWidget(self.label)
|
||||
|
||||
self.verticalSpacerPerformance = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding)
|
||||
|
||||
self.verticalLayout_9.addItem(self.verticalSpacerPerformance)
|
||||
|
||||
self.tabSettings.addTab(self.tabPerformance, "")
|
||||
|
||||
self.verticalLayout.addWidget(self.tabSettings)
|
||||
|
||||
@@ -347,5 +421,38 @@ class Ui_Dialog(object):
|
||||
self.addProject.setText(QCoreApplication.translate("Dialog", u"Hinzuf\u00fcgen", None))
|
||||
self.removeProject.setText(QCoreApplication.translate("Dialog", u"Entfernen", None))
|
||||
self.tabSettings.setTabText(self.tabSettings.indexOf(self.tabPdfProject), QCoreApplication.translate("Dialog", u"PDF-Projekte", None))
|
||||
self.groupBoxWorker.setTitle(QCoreApplication.translate("Dialog", u"ThreadPoolExecutor Einstellungen", None))
|
||||
self.labelWorkerCount.setText(QCoreApplication.translate("Dialog", u"Anzahl paralleler Worker f\u00fcr Transformationen:", None))
|
||||
#if QT_CONFIG(tooltip)
|
||||
self.spinBoxWorkerCount.setToolTip(QCoreApplication.translate("Dialog", u"Anzahl der parallelen Worker-Threads f\u00fcr Transformationen (Standard: 8)", None))
|
||||
#endif // QT_CONFIG(tooltip)
|
||||
self.groupBoxSaxonPool.setTitle(QCoreApplication.translate("Dialog", u"SaxonWorkerPool Einstellungen", None))
|
||||
#if QT_CONFIG(tooltip)
|
||||
self.checkBoxUseSaxonPool.setToolTip(QCoreApplication.translate("Dialog", u"Aktiviert persistente JVM-Prozesse f\u00fcr Saxon-Transformationen.\n"
|
||||
"Vorteile: Bis zu 10x schneller durch Eliminierung von JVM-Startup-Overhead\n"
|
||||
"Nachteile: Ben\u00f6tigt JDK (javac) - funktioniert nicht mit JRE allein\n"
|
||||
"\n"
|
||||
"Deaktivieren Sie diese Option, wenn:\n"
|
||||
"\u2022 Sie nur ein JRE (keine JDK) installiert haben\n"
|
||||
"\u2022 Sie Probleme mit dem Worker-Pool haben\n"
|
||||
"\u2022 Sie die Funktion testen m\u00f6chten", None))
|
||||
#endif // QT_CONFIG(tooltip)
|
||||
self.checkBoxUseSaxonPool.setText(QCoreApplication.translate("Dialog", u"SaxonWorkerPool verwenden (empfohlen)", None))
|
||||
self.labelSaxonPoolInfo.setText(QCoreApplication.translate("Dialog", u"<i>Hinweis: SaxonWorkerPool ben\u00f6tigt ein JDK (Java Development Kit).<br>Mit JRE allein werden Transformationen im Fallback-Modus ausgef\u00fchrt.</i>", None))
|
||||
self.groupBoxFopPool.setTitle(QCoreApplication.translate("Dialog", u"FopWorkerPool Einstellungen", None))
|
||||
#if QT_CONFIG(tooltip)
|
||||
self.checkBoxUseFopPool.setToolTip(QCoreApplication.translate("Dialog", u"Aktiviert persistente JVM-Prozesse f\u00fcr Apache FOP PDF-Generierung.\n"
|
||||
"Vorteile: Bis zu 10x schneller durch Eliminierung von JVM-Startup-Overhead\n"
|
||||
"Nachteile: Ben\u00f6tigt JDK (javac) - funktioniert nicht mit JRE allein\n"
|
||||
"\n"
|
||||
"Deaktivieren Sie diese Option, wenn:\n"
|
||||
"\u2022 Sie nur ein JRE (keine JDK) installiert haben\n"
|
||||
"\u2022 Sie Probleme mit dem Worker-Pool haben\n"
|
||||
"\u2022 Sie die Funktion testen m\u00f6chten", None))
|
||||
#endif // QT_CONFIG(tooltip)
|
||||
self.checkBoxUseFopPool.setText(QCoreApplication.translate("Dialog", u"FopWorkerPool verwenden (empfohlen)", None))
|
||||
self.labelFopPoolInfo.setText(QCoreApplication.translate("Dialog", u"<i>Hinweis: FopWorkerPool ben\u00f6tigt ein JDK (Java Development Kit).<br>Mit JRE allein werden PDFs im Fallback-Modus generiert.</i>", None))
|
||||
self.label.setText(QCoreApplication.translate("Dialog", u"<html><head/><body><p><span style=\" font-weight:700; font-style:italic;\">Hinweis: \u00c4nderungen in diesem Dialog sind unter Umst\u00e4nden erst nach neu start der Anwendung wirksam.</span></p></body></html>", None))
|
||||
self.tabSettings.setTabText(self.tabSettings.indexOf(self.tabPerformance), QCoreApplication.translate("Dialog", u"Performance", None))
|
||||
# retranslateUi
|
||||
|
||||
|
||||
@@ -554,9 +554,6 @@ class MainWindow(QMainWindow):
|
||||
# Vorhandene Projekte-Menü initialisieren
|
||||
self._setup_projects_menu()
|
||||
|
||||
# Performance-Einstellungen-Menü initialisieren
|
||||
self._setup_performance_menu()
|
||||
|
||||
#
|
||||
if theme := app_settings.theme:
|
||||
self.change_theme(theme)
|
||||
@@ -655,201 +652,6 @@ class MainWindow(QMainWindow):
|
||||
|
||||
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)
|
||||
saxon_pool_status = "aktiviert" if app_settings.use_saxon_worker_pool else "deaktiviert"
|
||||
fop_pool_status = "aktiviert" if app_settings.use_fop_worker_pool else "deaktiviert"
|
||||
performance_action.setToolTip(
|
||||
f"Worker: {app_settings.max_workers} | SaxonWorkerPool: {saxon_pool_status} | FopWorkerPool: {fop_pool_status}"
|
||||
)
|
||||
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 (
|
||||
QDialog,
|
||||
QVBoxLayout,
|
||||
QHBoxLayout,
|
||||
QLabel,
|
||||
QSpinBox,
|
||||
QCheckBox,
|
||||
QPushButton,
|
||||
QGroupBox,
|
||||
)
|
||||
|
||||
# Erstelle benutzerdefinierten Dialog
|
||||
dialog = QDialog(self)
|
||||
dialog.setWindowTitle("Performance-Einstellungen")
|
||||
dialog.setMinimumWidth(450)
|
||||
|
||||
layout = QVBoxLayout()
|
||||
|
||||
# Worker-Anzahl Einstellung
|
||||
worker_group = QGroupBox("ThreadPoolExecutor Einstellungen")
|
||||
worker_layout = QVBoxLayout()
|
||||
|
||||
worker_label = QLabel("Anzahl paralleler Worker für Transformationen:")
|
||||
worker_spinbox = QSpinBox()
|
||||
worker_spinbox.setMinimum(1)
|
||||
worker_spinbox.setMaximum(32)
|
||||
worker_spinbox.setValue(app_settings.max_workers)
|
||||
worker_spinbox.setToolTip("Anzahl der parallelen Worker-Threads für Transformationen (Standard: 8)")
|
||||
|
||||
worker_layout.addWidget(worker_label)
|
||||
worker_layout.addWidget(worker_spinbox)
|
||||
worker_group.setLayout(worker_layout)
|
||||
layout.addWidget(worker_group)
|
||||
|
||||
# SaxonWorkerPool Einstellung
|
||||
pool_group = QGroupBox("SaxonWorkerPool Einstellungen")
|
||||
pool_layout = QVBoxLayout()
|
||||
|
||||
pool_checkbox = QCheckBox("SaxonWorkerPool verwenden (empfohlen)")
|
||||
pool_checkbox.setChecked(app_settings.use_saxon_worker_pool)
|
||||
pool_checkbox.setToolTip(
|
||||
"Aktiviert persistente JVM-Prozesse für Saxon-Transformationen.\n"
|
||||
"Vorteile: Bis zu 10x schneller durch Eliminierung von JVM-Startup-Overhead\n"
|
||||
"Nachteile: Benötigt JDK (javac) - funktioniert nicht mit JRE allein\n\n"
|
||||
"Deaktivieren Sie diese Option, wenn:\n"
|
||||
"• Sie nur ein JRE (keine JDK) installiert haben\n"
|
||||
"• Sie Probleme mit dem Worker-Pool haben\n"
|
||||
"• Sie die Funktion testen möchten"
|
||||
)
|
||||
|
||||
pool_info = QLabel(
|
||||
"<i>Hinweis: SaxonWorkerPool benötigt ein JDK (Java Development Kit).<br>"
|
||||
"Mit JRE allein werden Transformationen im Fallback-Modus ausgeführt.</i>"
|
||||
)
|
||||
pool_info.setWordWrap(True)
|
||||
|
||||
pool_layout.addWidget(pool_checkbox)
|
||||
pool_layout.addWidget(pool_info)
|
||||
pool_group.setLayout(pool_layout)
|
||||
layout.addWidget(pool_group)
|
||||
|
||||
# FopWorkerPool Einstellung
|
||||
fop_pool_group = QGroupBox("FopWorkerPool Einstellungen")
|
||||
fop_pool_layout = QVBoxLayout()
|
||||
|
||||
fop_pool_checkbox = QCheckBox("FopWorkerPool verwenden (empfohlen)")
|
||||
fop_pool_checkbox.setChecked(app_settings.use_fop_worker_pool)
|
||||
fop_pool_checkbox.setToolTip(
|
||||
"Aktiviert persistente JVM-Prozesse für Apache FOP PDF-Generierung.\n"
|
||||
"Vorteile: Bis zu 10x schneller durch Eliminierung von JVM-Startup-Overhead\n"
|
||||
"Nachteile: Benötigt JDK (javac) - funktioniert nicht mit JRE allein\n\n"
|
||||
"Deaktivieren Sie diese Option, wenn:\n"
|
||||
"• Sie nur ein JRE (keine JDK) installiert haben\n"
|
||||
"• Sie Probleme mit dem Worker-Pool haben\n"
|
||||
"• Sie die Funktion testen möchten"
|
||||
)
|
||||
|
||||
fop_pool_info = QLabel(
|
||||
"<i>Hinweis: FopWorkerPool benötigt ein JDK (Java Development Kit).<br>"
|
||||
"Mit JRE allein werden PDFs im Fallback-Modus generiert.</i>"
|
||||
)
|
||||
fop_pool_info.setWordWrap(True)
|
||||
|
||||
fop_pool_layout.addWidget(fop_pool_checkbox)
|
||||
fop_pool_layout.addWidget(fop_pool_info)
|
||||
fop_pool_group.setLayout(fop_pool_layout)
|
||||
layout.addWidget(fop_pool_group)
|
||||
|
||||
# OK/Abbrechen Buttons
|
||||
button_layout = QHBoxLayout()
|
||||
ok_button = QPushButton("OK")
|
||||
cancel_button = QPushButton("Abbrechen")
|
||||
|
||||
ok_button.clicked.connect(dialog.accept)
|
||||
cancel_button.clicked.connect(dialog.reject)
|
||||
|
||||
button_layout.addStretch()
|
||||
button_layout.addWidget(ok_button)
|
||||
button_layout.addWidget(cancel_button)
|
||||
layout.addLayout(button_layout)
|
||||
|
||||
dialog.setLayout(layout)
|
||||
|
||||
# Dialog anzeigen
|
||||
if dialog.exec() == QDialog.DialogCode.Accepted:
|
||||
# Speichere Änderungen
|
||||
current_workers = app_settings.max_workers
|
||||
current_use_pool = app_settings.use_saxon_worker_pool
|
||||
current_use_fop_pool = app_settings.use_fop_worker_pool
|
||||
|
||||
new_workers = worker_spinbox.value()
|
||||
new_use_pool = pool_checkbox.isChecked()
|
||||
new_use_fop_pool = fop_pool_checkbox.isChecked()
|
||||
|
||||
changes = []
|
||||
|
||||
if new_workers != current_workers:
|
||||
app_settings.max_workers = new_workers
|
||||
changes.append(f"Worker-Anzahl: {current_workers} → {new_workers}")
|
||||
logger.info(f"max_workers geändert: {current_workers} → {new_workers}")
|
||||
|
||||
if new_use_pool != current_use_pool:
|
||||
app_settings.use_saxon_worker_pool = new_use_pool
|
||||
status = "aktiviert" if new_use_pool else "deaktiviert"
|
||||
changes.append(f"SaxonWorkerPool: {status}")
|
||||
logger.info(f"use_saxon_worker_pool geändert: {current_use_pool} → {new_use_pool}")
|
||||
|
||||
if new_use_fop_pool != current_use_fop_pool:
|
||||
app_settings.use_fop_worker_pool = new_use_fop_pool
|
||||
status = "aktiviert" if new_use_fop_pool else "deaktiviert"
|
||||
changes.append(f"FopWorkerPool: {status}")
|
||||
logger.info(f"use_fop_worker_pool geändert: {current_use_fop_pool} → {new_use_fop_pool}")
|
||||
|
||||
if changes:
|
||||
# WICHTIG: Speichere Settings BEVOR wir Pools neu initialisieren
|
||||
app_settings.save()
|
||||
logger.info(f"Performance-Einstellungen gespeichert: {changes}")
|
||||
|
||||
# Initialisiere Worker Pools neu falls sich relevante Einstellungen geändert haben
|
||||
pools_reinitialized = False
|
||||
if self.project:
|
||||
# Saxon Worker Pool neu initialisieren?
|
||||
if new_use_pool != current_use_pool or new_workers != current_workers:
|
||||
logger.info(
|
||||
f"Saxon Worker Pool wird neu initialisiert "
|
||||
f"(use_pool: {current_use_pool}→{new_use_pool}, workers: {current_workers}→{new_workers})"
|
||||
)
|
||||
self._initialize_saxon_worker_pool()
|
||||
pools_reinitialized = True
|
||||
|
||||
# FOP Worker Pool neu initialisieren?
|
||||
if new_use_fop_pool != current_use_fop_pool or new_workers != current_workers:
|
||||
logger.info(
|
||||
f"FOP Worker Pool wird neu initialisiert "
|
||||
f"(use_pool: {current_use_fop_pool}→{new_use_fop_pool}, workers: {current_workers}→{new_workers})"
|
||||
)
|
||||
self._initialize_fop_worker_pool()
|
||||
pools_reinitialized = True
|
||||
else:
|
||||
logger.warning("Kein Projekt geladen - Worker Pools werden nicht neu initialisiert")
|
||||
|
||||
# Informiere Benutzer über Änderungen
|
||||
changes_text = "\n".join(f"• {change}" for change in changes)
|
||||
status_hint = ""
|
||||
|
||||
if pools_reinitialized:
|
||||
status_hint = "\n\nDie Worker Pools wurden automatisch mit den neuen Einstellungen neu gestartet."
|
||||
|
||||
QMessageBox.information(
|
||||
self,
|
||||
"Einstellungen gespeichert",
|
||||
f"Folgende Einstellungen wurden geändert:\n\n{changes_text}{status_hint}",
|
||||
)
|
||||
|
||||
def open_existing_project(self, project: Project):
|
||||
"""
|
||||
Öffnet ein vorhandenes Projekt.
|
||||
|
||||
Reference in New Issue
Block a user