diff --git a/src/ui/MainWinddow.ui b/src/ui/MainWinddow.ui
index 81df27c..1f94a8f 100644
--- a/src/ui/MainWinddow.ui
+++ b/src/ui/MainWinddow.ui
@@ -95,76 +95,6 @@
- -
-
-
- QFrame::Shadow::Raised
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
-
- Qt::LayoutDirection::LeftToRight
-
-
- nur geänderte generieren
-
-
-
-
-
-
- -
-
-
- false
-
-
- Alle generieren
-
-
-
-
-
-
- -
-
-
- Qt::Orientation::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- lade aus FN2
-
-
-
-
-
-
-
-
-
@@ -188,8 +118,8 @@
0
0
- 68
- 728
+ 54
+ 716
@@ -416,8 +346,8 @@
0
0
- 726
- 697
+ 881
+ 684
@@ -449,7 +379,7 @@
0
0
1263
- 22
+ 33
+
+
@@ -507,10 +450,36 @@
false
+
+
+
Vorhandene Projekte
+
+
+ Alle XML-Dateien transformieren
+
+
+
+
+
+
+
+ Alle XML-Dateien neu transformieren (force)
+
+
+
+
+ FN2
+
+
+
+
+ Aus Datenbank laden
+
+
diff --git a/src/ui/MainWinddow_ui.py b/src/ui/MainWinddow_ui.py
index c12381d..d64d08b 100644
--- a/src/ui/MainWinddow_ui.py
+++ b/src/ui/MainWinddow_ui.py
@@ -3,7 +3,7 @@
################################################################################
## Form generated from reading UI file 'MainWinddow.ui'
##
-## Created by: Qt User Interface Compiler version 6.9.2
+## Created by: Qt User Interface Compiler version 6.10.1
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################
@@ -42,6 +42,18 @@ class Ui_MainWindow(object):
self.actionVorhandene_Projekte = QAction(MainWindow)
self.actionVorhandene_Projekte.setObjectName(u"actionVorhandene_Projekte")
self.actionVorhandene_Projekte.setEnabled(False)
+ icon3 = QIcon(QIcon.fromTheme(u"folder-open"))
+ self.actionVorhandene_Projekte.setIcon(icon3)
+ self.actionAlle_XML_Dateien_transformieren = QAction(MainWindow)
+ self.actionAlle_XML_Dateien_transformieren.setObjectName(u"actionAlle_XML_Dateien_transformieren")
+ self.actionAlle_XML_Dateien_neu_transformieren_force = QAction(MainWindow)
+ self.actionAlle_XML_Dateien_neu_transformieren_force.setObjectName(u"actionAlle_XML_Dateien_neu_transformieren_force")
+ icon4 = QIcon(QIcon.fromTheme(QIcon.ThemeIcon.ViewRefresh))
+ self.actionAlle_XML_Dateien_neu_transformieren_force.setIcon(icon4)
+ self.actionFN2 = QAction(MainWindow)
+ self.actionFN2.setObjectName(u"actionFN2")
+ self.actionAus_Datenbank_laden = QAction(MainWindow)
+ self.actionAus_Datenbank_laden.setObjectName(u"actionAus_Datenbank_laden")
self.centralwidget = QWidget(MainWindow)
self.centralwidget.setObjectName(u"centralwidget")
self.horizontalLayout = QHBoxLayout(self.centralwidget)
@@ -83,42 +95,6 @@ class Ui_MainWindow(object):
self.verticalLayout.addWidget(self.treeWidget)
- self.frame_2 = QFrame(self.frame)
- self.frame_2.setObjectName(u"frame_2")
- self.frame_2.setFrameShadow(QFrame.Shadow.Raised)
- self.horizontalLayout_2 = QHBoxLayout(self.frame_2)
- self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
- self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
- self.pushButton = QPushButton(self.frame_2)
- self.pushButton.setObjectName(u"pushButton")
- self.pushButton.setLayoutDirection(Qt.LayoutDirection.LeftToRight)
- icon3 = QIcon(QIcon.fromTheme(QIcon.ThemeIcon.MediaPlaybackStart))
- self.pushButton.setIcon(icon3)
-
- self.horizontalLayout_2.addWidget(self.pushButton)
-
- self.pushButton_2 = QPushButton(self.frame_2)
- self.pushButton_2.setObjectName(u"pushButton_2")
- self.pushButton_2.setAutoFillBackground(False)
- icon4 = QIcon(QIcon.fromTheme(QIcon.ThemeIcon.MediaSeekForward))
- self.pushButton_2.setIcon(icon4)
-
- self.horizontalLayout_2.addWidget(self.pushButton_2)
-
- self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
-
- self.horizontalLayout_2.addItem(self.horizontalSpacer)
-
- self.pB_lade_aus_fn2 = QPushButton(self.frame_2)
- self.pB_lade_aus_fn2.setObjectName(u"pB_lade_aus_fn2")
- icon5 = QIcon(QIcon.fromTheme(QIcon.ThemeIcon.GoDown))
- self.pB_lade_aus_fn2.setIcon(icon5)
-
- self.horizontalLayout_2.addWidget(self.pB_lade_aus_fn2)
-
-
- self.verticalLayout.addWidget(self.frame_2)
-
self.splitter.addWidget(self.frame)
self.scrollArea = QScrollArea(self.splitter)
self.scrollArea.setObjectName(u"scrollArea")
@@ -132,7 +108,7 @@ class Ui_MainWindow(object):
self.scrollArea.setWidgetResizable(True)
self.scrollAreaWidgetContents = QWidget()
self.scrollAreaWidgetContents.setObjectName(u"scrollAreaWidgetContents")
- self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 68, 728))
+ self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 54, 716))
self.verticalLayout_2 = QVBoxLayout(self.scrollAreaWidgetContents)
self.verticalLayout_2.setObjectName(u"verticalLayout_2")
self.label = QLabel(self.scrollAreaWidgetContents)
@@ -234,7 +210,7 @@ class Ui_MainWindow(object):
self.scrollArea_2.setWidgetResizable(True)
self.scrollAreaWidgetContents_2 = QWidget()
self.scrollAreaWidgetContents_2.setObjectName(u"scrollAreaWidgetContents_2")
- self.scrollAreaWidgetContents_2.setGeometry(QRect(0, 0, 726, 697))
+ self.scrollAreaWidgetContents_2.setGeometry(QRect(0, 0, 881, 684))
self.verticalLayout_3 = QVBoxLayout(self.scrollAreaWidgetContents_2)
self.verticalLayout_3.setObjectName(u"verticalLayout_3")
self.verticalLayout_3.setContentsMargins(0, 0, 0, 0)
@@ -249,17 +225,21 @@ class Ui_MainWindow(object):
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QMenuBar(MainWindow)
self.menubar.setObjectName(u"menubar")
- self.menubar.setGeometry(QRect(0, 0, 1263, 22))
+ self.menubar.setGeometry(QRect(0, 0, 1263, 33))
self.menuProjekt = QMenu(self.menubar)
self.menuProjekt.setObjectName(u"menuProjekt")
self.menuThema = QMenu(self.menubar)
self.menuThema.setObjectName(u"menuThema")
+ self.menuAktion = QMenu(self.menubar)
+ self.menuAktion.setObjectName(u"menuAktion")
+ self.menuAktion.setEnabled(False)
MainWindow.setMenuBar(self.menubar)
self.statusbar = QStatusBar(MainWindow)
self.statusbar.setObjectName(u"statusbar")
MainWindow.setStatusBar(self.statusbar)
self.menubar.addAction(self.menuProjekt.menuAction())
+ self.menubar.addAction(self.menuAktion.menuAction())
self.menubar.addAction(self.menuThema.menuAction())
self.menuProjekt.addAction(self.actionNeu)
self.menuProjekt.addSeparator()
@@ -268,6 +248,10 @@ class Ui_MainWindow(object):
self.menuProjekt.addAction(self.actionEinstellungen)
self.menuProjekt.addSeparator()
self.menuProjekt.addAction(self.actionBeenden)
+ self.menuAktion.addAction(self.actionAlle_XML_Dateien_transformieren)
+ self.menuAktion.addAction(self.actionAlle_XML_Dateien_neu_transformieren_force)
+ self.menuAktion.addSeparator()
+ self.menuAktion.addAction(self.actionAus_Datenbank_laden)
self.retranslateUi(MainWindow)
self.actionBeenden.triggered.connect(MainWindow.close)
@@ -287,9 +271,10 @@ class Ui_MainWindow(object):
self.actionEinstellungen.setShortcut(QCoreApplication.translate("MainWindow", u"Ctrl+S", None))
#endif // QT_CONFIG(shortcut)
self.actionVorhandene_Projekte.setText(QCoreApplication.translate("MainWindow", u"Vorhandene Projekte", None))
- self.pushButton.setText(QCoreApplication.translate("MainWindow", u"nur ge\u00e4nderte generieren", None))
- self.pushButton_2.setText(QCoreApplication.translate("MainWindow", u"Alle generieren", None))
- self.pB_lade_aus_fn2.setText(QCoreApplication.translate("MainWindow", u"lade aus FN2", None))
+ self.actionAlle_XML_Dateien_transformieren.setText(QCoreApplication.translate("MainWindow", u"Alle XML-Dateien transformieren", None))
+ self.actionAlle_XML_Dateien_neu_transformieren_force.setText(QCoreApplication.translate("MainWindow", u"Alle XML-Dateien neu transformieren (force)", None))
+ self.actionFN2.setText(QCoreApplication.translate("MainWindow", u"FN2", None))
+ self.actionAus_Datenbank_laden.setText(QCoreApplication.translate("MainWindow", u"Aus Datenbank laden", None))
self.label.setText("")
self.label_2.setText("")
self.view_ref_pdf.setText(QCoreApplication.translate("MainWindow", u"Vorher (Referenz)", None))
@@ -304,5 +289,6 @@ class Ui_MainWindow(object):
self.accept_changes.setText(QCoreApplication.translate("MainWindow", u"\u2705 \u00c4nderungen \u00fcbernehmen", None))
self.menuProjekt.setTitle(QCoreApplication.translate("MainWindow", u"Projekt", None))
self.menuThema.setTitle(QCoreApplication.translate("MainWindow", u"Thema", None))
+ self.menuAktion.setTitle(QCoreApplication.translate("MainWindow", u"Aktion", None))
# retranslateUi
diff --git a/src/ui/MainWindow.py b/src/ui/MainWindow.py
index 072454b..6f09d6e 100644
--- a/src/ui/MainWindow.py
+++ b/src/ui/MainWindow.py
@@ -284,6 +284,10 @@ class MainWindow(
# Worker-Pools werden jetzt erst beim Start der Transformation initialisiert (lazy loading)
+ # Aktiviere das Aktions-Menü, da ein Projekt geladen wurde
+ self.ui.menuAktion.setEnabled(True)
+ logger.info("Aktions-Menü aktiviert nach Projekt-Laden")
+
except Exception as e:
logger.error(f"Fehler beim Laden des Projekts '{project.name}': {e}")
# Fallback: Erstelle Standard-Einstellungen
@@ -326,8 +330,6 @@ class MainWindow(
def _connect_signals(self):
"""Verbindet Signale mit den entsprechenden Slots."""
- # Button-Klicks verbinden
- self.ui.pushButton.clicked.connect(self.on_button_clicked)
# Zoom-Slider verbinden
self.ui.zoom.valueChanged.connect(self.apply_zoom)
@@ -340,6 +342,8 @@ class MainWindow(
# Menü-Aktionen verbinden
self.ui.actionNeu.triggered.connect(self.open_new_project_dialog)
self.ui.actionEinstellungen.triggered.connect(self.open_settings_dialog)
+ self.ui.actionAlle_XML_Dateien_transformieren.triggered.connect(self._transform_all_xml_files)
+ self.ui.actionAlle_XML_Dateien_neu_transformieren_force.triggered.connect(self._transform_all_xml_files_force)
# Worker-Pool-Metriken Menüeintrag (programmatisch hinzufügen)
from PySide6.QtGui import QAction
@@ -360,8 +364,8 @@ class MainWindow(
else:
self.ui.menuProjekt.addAction(self.action_worker_metrics)
- # Button "lade aus FN2" verbinden
- self.ui.pB_lade_aus_fn2.clicked.connect(self.on_load_from_fn2_clicked)
+ # Menü-Aktion "Aus Datenbank laden" verbinden (macht das Gleiche wie Button)
+ self.ui.actionAus_Datenbank_laden.triggered.connect(self.on_load_from_fn2_clicked)
# Button "Accept Changes" verbinden
self.ui.accept_changes.clicked.connect(self._on_accept_changes_clicked)
@@ -462,10 +466,6 @@ class MainWindow(
logger.error(f"Fehler beim Erstellen der Projekt-Struktur: {e}")
raise
- def on_button_clicked(self):
- """Wird ausgeführt, wenn der Button geklickt wird."""
- logger.debug("Button wurde geklickt!")
-
def _update_diff_icons_for_existing_pdfs(self):
"""
Durchläuft alle XML-Items und setzt Icons für bereits existierende Diff-PDFs.
diff --git a/src/ui/mixins/transformation.py b/src/ui/mixins/transformation.py
index efe348c..c251cd0 100644
--- a/src/ui/mixins/transformation.py
+++ b/src/ui/mixins/transformation.py
@@ -740,3 +740,128 @@ class TransformationMixin:
"Abgeschlossen mit Fehlern",
f"{successful_count} von {total_count} Transformationen erfolgreich\n{failed_count} fehlgeschlagen\n\nGesamtdauer: {duration_str}",
)
+
+ def _transform_all_xml_files(self):
+ """
+ Transformiert ALLE XML-Dateien in allen TreeNodes des TreeWidgets.
+ Nur Dateien, die nicht up-to-date sind, werden transformiert.
+ """
+ try:
+ if not self.project or not self.pdf_project:
+ QMessageBox.warning(self, "Fehler", "Kein Projekt geladen")
+ return
+
+ # Sammle alle XSL/XML-Paare aus allen Root-Nodes
+ all_jobs = []
+ root = self.ui.treeWidget.invisibleRootItem()
+
+ for i in range(root.childCount()):
+ root_item = root.child(i)
+ root_node = root_item.data(0, Qt.ItemDataRole.UserRole)
+
+ if isinstance(root_node, TreeNode):
+ # Sammle alle XSL/XML-Paare rekursiv
+ xsl_xml_pairs = self._collect_all_xsl_xml_pairs_recursive(root_node, root_item)
+
+ # Erstelle TransformationJobs
+ for xsl_file_obj, xml_file_obj, xsl_file_item in xsl_xml_pairs:
+ job = self._create_transformation_job(xsl_file_obj, xml_file_obj, xsl_file_item)
+ if job:
+ all_jobs.append(job)
+
+ elif isinstance(root_node, XslFile):
+ # Direkt XslFile als Root-Element
+ for xml_file_obj in root_node.xmls:
+ job = self._create_transformation_job(root_node, xml_file_obj, root_item)
+ if job:
+ all_jobs.append(job)
+
+ if not all_jobs:
+ QMessageBox.information(self, "Info", "Keine XML-Dateien zum Transformieren gefunden")
+ return
+
+ # Frage Benutzer um Bestätigung
+ reply = QMessageBox.question(
+ self,
+ "Alle XML-Dateien transformieren",
+ f"Möchten Sie wirklich alle {len(all_jobs)} XML-Dateien transformieren?\n\n"
+ f"Nur Dateien mit Änderungen werden verarbeitet.",
+ QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
+ QMessageBox.StandardButton.Yes,
+ )
+
+ if reply != QMessageBox.StandardButton.Yes:
+ logger.info("Transformation abgebrochen durch Benutzer")
+ return
+
+ logger.info(f"Starte Transformation für alle {len(all_jobs)} XML-Dateien (nicht-force)")
+
+ # Starte Transformation in separatem Thread
+ self._start_transformation(all_jobs, force=False)
+
+ except Exception as e:
+ logger.error(f"Fehler beim Transformieren aller XML-Dateien: {e}")
+ QMessageBox.critical(self, "Fehler", f"Fehler beim Starten der Transformation: {str(e)}")
+
+ def _transform_all_xml_files_force(self):
+ """
+ Transformiert ALLE XML-Dateien in allen TreeNodes des TreeWidgets (force).
+ Alle Dateien werden unabhängig vom Änderungsstatus neu transformiert.
+ """
+ try:
+ if not self.project or not self.pdf_project:
+ QMessageBox.warning(self, "Fehler", "Kein Projekt geladen")
+ return
+
+ # Sammle alle XSL/XML-Paare aus allen Root-Nodes
+ all_jobs = []
+ root = self.ui.treeWidget.invisibleRootItem()
+
+ for i in range(root.childCount()):
+ root_item = root.child(i)
+ root_node = root_item.data(0, Qt.ItemDataRole.UserRole)
+
+ if isinstance(root_node, TreeNode):
+ # Sammle alle XSL/XML-Paare rekursiv
+ xsl_xml_pairs = self._collect_all_xsl_xml_pairs_recursive(root_node, root_item)
+
+ # Erstelle TransformationJobs
+ for xsl_file_obj, xml_file_obj, xsl_file_item in xsl_xml_pairs:
+ job = self._create_transformation_job(xsl_file_obj, xml_file_obj, xsl_file_item)
+ if job:
+ all_jobs.append(job)
+
+ elif isinstance(root_node, XslFile):
+ # Direkt XslFile als Root-Element
+ for xml_file_obj in root_node.xmls:
+ job = self._create_transformation_job(root_node, xml_file_obj, root_item)
+ if job:
+ all_jobs.append(job)
+
+ if not all_jobs:
+ QMessageBox.information(self, "Info", "Keine XML-Dateien zum Transformieren gefunden")
+ return
+
+ # Frage Benutzer um Bestätigung (mit Warnung wegen force)
+ reply = QMessageBox.question(
+ self,
+ "Alle XML-Dateien neu transformieren (force)",
+ f"Möchten Sie wirklich ALLE {len(all_jobs)} XML-Dateien NEU transformieren?\n\n"
+ f"⚠ WARNUNG: Im Force-Modus werden alle Dateien unabhängig von ihrem Status neu verarbeitet!\n"
+ f"Dies kann längere Zeit in Anspruch nehmen.",
+ QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
+ QMessageBox.StandardButton.No,
+ )
+
+ if reply != QMessageBox.StandardButton.Yes:
+ logger.info("Force-Transformation abgebrochen durch Benutzer")
+ return
+
+ logger.info(f"Starte Force-Transformation für alle {len(all_jobs)} XML-Dateien")
+
+ # Starte Transformation in separatem Thread (mit force=True)
+ self._start_transformation(all_jobs, force=True)
+
+ except Exception as e:
+ logger.error(f"Fehler beim Force-Transformieren aller XML-Dateien: {e}")
+ QMessageBox.critical(self, "Fehler", f"Fehler beim Starten der Force-Transformation: {str(e)}")