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.
|
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
|
## PySide6-GUI
|
||||||
- Beim Erstellen neuer Dialoge sollte immer eine passende UI-Datei erstellt werden
|
- 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 über die UI-Datei zu gestalten
|
- 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
|
- 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
|
- Die automatisch generierte .py-Datei muss in den Code eingebunden und verwendet werden
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,9 @@ class AppSettingsDlg(QDialog):
|
|||||||
self._setup_tables()
|
self._setup_tables()
|
||||||
self._populate_tables()
|
self._populate_tables()
|
||||||
|
|
||||||
|
# Performance-Tab initialisieren
|
||||||
|
self._populate_performance_tab()
|
||||||
|
|
||||||
def _connect_signals(self):
|
def _connect_signals(self):
|
||||||
"""Verbindet die Signale der UI-Elemente."""
|
"""Verbindet die Signale der UI-Elemente."""
|
||||||
# XSL-Ordner Tab
|
# XSL-Ordner Tab
|
||||||
@@ -271,6 +274,17 @@ class AppSettingsDlg(QDialog):
|
|||||||
self.ui.tablePostgreSqlDbs.setItem(row, 4, username_item)
|
self.ui.tablePostgreSqlDbs.setItem(row, 4, username_item)
|
||||||
self.ui.tablePostgreSqlDbs.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents)
|
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
|
# XSL-Ordner Methoden
|
||||||
def _add_xsl_dir(self):
|
def _add_xsl_dir(self):
|
||||||
"""Fügt einen neuen XSL-Ordner hinzu."""
|
"""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.xsl_dirs = self.temp_xsl_dirs.copy()
|
||||||
self.settings.pdf_projects = self.temp_pdf_projects.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()
|
self.settings.save()
|
||||||
|
|
||||||
super().accept()
|
super().accept()
|
||||||
|
|||||||
+141
-1
@@ -7,7 +7,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>833</width>
|
<width>833</width>
|
||||||
<height>387</height>
|
<height>446</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@@ -520,6 +520,146 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</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>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
+113
-6
@@ -3,7 +3,7 @@
|
|||||||
################################################################################
|
################################################################################
|
||||||
## Form generated from reading UI file 'AppSettings.ui'
|
## 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!
|
## 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,
|
QFont, QFontDatabase, QGradient, QIcon,
|
||||||
QImage, QKeySequence, QLinearGradient, QPainter,
|
QImage, QKeySequence, QLinearGradient, QPainter,
|
||||||
QPalette, QPixmap, QRadialGradient, QTransform)
|
QPalette, QPixmap, QRadialGradient, QTransform)
|
||||||
from PySide6.QtWidgets import (QAbstractButton, QApplication, QDialog, QDialogButtonBox,
|
from PySide6.QtWidgets import (QAbstractButton, QApplication, QCheckBox, QDialog,
|
||||||
QFrame, QHBoxLayout, QHeaderView, QPushButton,
|
QDialogButtonBox, QFrame, QGroupBox, QHBoxLayout,
|
||||||
QSizePolicy, QTabWidget, QTableWidget, QTableWidgetItem,
|
QHeaderView, QLabel, QPushButton, QSizePolicy,
|
||||||
QVBoxLayout, QWidget)
|
QSpacerItem, QSpinBox, QTabWidget, QTableWidget,
|
||||||
|
QTableWidgetItem, QVBoxLayout, QWidget)
|
||||||
|
|
||||||
class Ui_Dialog(object):
|
class Ui_Dialog(object):
|
||||||
def setupUi(self, Dialog):
|
def setupUi(self, Dialog):
|
||||||
if not Dialog.objectName():
|
if not Dialog.objectName():
|
||||||
Dialog.setObjectName(u"Dialog")
|
Dialog.setObjectName(u"Dialog")
|
||||||
Dialog.resize(833, 387)
|
Dialog.resize(833, 446)
|
||||||
self.verticalLayout = QVBoxLayout(Dialog)
|
self.verticalLayout = QVBoxLayout(Dialog)
|
||||||
self.verticalLayout.setObjectName(u"verticalLayout")
|
self.verticalLayout.setObjectName(u"verticalLayout")
|
||||||
self.tabSettings = QTabWidget(Dialog)
|
self.tabSettings = QTabWidget(Dialog)
|
||||||
@@ -302,6 +303,79 @@ class Ui_Dialog(object):
|
|||||||
self.verticalLayout_7.addWidget(self.frame_6)
|
self.verticalLayout_7.addWidget(self.frame_6)
|
||||||
|
|
||||||
self.tabSettings.addTab(self.tabPdfProject, "")
|
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)
|
self.verticalLayout.addWidget(self.tabSettings)
|
||||||
|
|
||||||
@@ -347,5 +421,38 @@ class Ui_Dialog(object):
|
|||||||
self.addProject.setText(QCoreApplication.translate("Dialog", u"Hinzuf\u00fcgen", None))
|
self.addProject.setText(QCoreApplication.translate("Dialog", u"Hinzuf\u00fcgen", None))
|
||||||
self.removeProject.setText(QCoreApplication.translate("Dialog", u"Entfernen", 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.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
|
# retranslateUi
|
||||||
|
|
||||||
|
|||||||
@@ -554,9 +554,6 @@ 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)
|
||||||
@@ -655,201 +652,6 @@ 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)
|
|
||||||
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):
|
def open_existing_project(self, project: Project):
|
||||||
"""
|
"""
|
||||||
Öffnet ein vorhandenes Projekt.
|
Öffnet ein vorhandenes Projekt.
|
||||||
|
|||||||
Reference in New Issue
Block a user