TreeNode-Kontextmenü: Transformations-Aktionen für alle untergeordneten XML-Dateien

Neue Funktionalität:
- TreeNode-Kontextmenü hat jetzt "Alle XML-Dateien transformieren" Aktionen
- Beide Aktionen (normal und force) transformieren rekursiv alle untergeordneten XML-Dateien
- Menüpunkte sind nur aktiv, wenn mindestens eine XML-Datei vorhanden ist

Implementierung:
- _has_xml_files_recursive(): Prüft rekursiv auf vorhandene XML-Dateien
- _collect_all_xsl_xml_pairs_recursive(): Sammelt alle XSL/XML-Paare im Teilbaum
- _transform_tree_node(): Transformiert alle gefundenen XML-Dateien
- Kontextmenü erweitert mit intelligenter Aktivierung/Deaktivierung

🤖 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-14 20:45:53 +01:00
parent f591be2ea9
commit 56f81ca858
+124
View File
@@ -912,6 +912,24 @@ class MainWindow(QMainWindow):
menu.addSeparator()
# Transformations-Aktionen (nur aktiv wenn XML-Dateien vorhanden)
tree_node_obj = item.data(0, Qt.ItemDataRole.UserRole) if item else None
has_xml_files = tree_node_obj and self._has_xml_files_recursive(tree_node_obj)
action_transform = QAction("Alle XML-Dateien transformieren", self)
action_transform.setIcon(QIcon(QIcon.fromTheme("system-run")))
action_transform.triggered.connect(lambda: self._transform_tree_node(item))
action_transform.setEnabled(has_xml_files)
menu.addAction(action_transform)
action_transform_force = QAction("Alle XML-Dateien neu transformieren (force)", self)
action_transform_force.setIcon(QIcon(QIcon.fromTheme("view-refresh")))
action_transform_force.triggered.connect(lambda: self._transform_tree_node(item, force=True))
action_transform_force.setEnabled(has_xml_files)
menu.addAction(action_transform_force)
menu.addSeparator()
action_edit = QAction("Bearbeiten", self)
action_edit.setIcon(QIcon(QIcon.fromTheme(QIcon.ThemeIcon.DocumentProperties)))
action_edit.triggered.connect(lambda: self._edit_tree_node(item))
@@ -3070,6 +3088,112 @@ class MainWindow(QMainWindow):
logger.error(f"Fehler beim Transformieren der XSL-Datei: {e}")
QMessageBox.critical(self, "Fehler", f"Fehler beim Transformieren: {str(e)}")
def _has_xml_files_recursive(self, node: TreeNode) -> bool:
"""
Prüft rekursiv, ob unter einem TreeNode mindestens eine XML-Datei vorhanden ist.
Args:
node: Der TreeNode
Returns:
bool: True wenn mindestens eine XML-Datei gefunden wurde
"""
if not hasattr(node, 'children') or not node.children:
return False
for child in node.children:
if isinstance(child, XslFile):
if child.xmls:
return True
elif isinstance(child, TreeNode):
if self._has_xml_files_recursive(child):
return True
return False
def _collect_all_xsl_xml_pairs_recursive(
self, tree_node: TreeNode, tree_item: QTreeWidgetItem
) -> list[tuple[XslFile, XmlFile, QTreeWidgetItem]]:
"""
Sammelt rekursiv alle (XslFile, XmlFile, XslFileItem) Tupel unter einem TreeNode.
Args:
tree_node: Der TreeNode
tree_item: Das TreeWidgetItem des TreeNode
Returns:
list: Liste von (XslFile, XmlFile, XslFileItem) Tupeln
"""
pairs = []
if not hasattr(tree_node, 'children') or not tree_node.children:
return pairs
# Durchlaufe alle Kinder des TreeNode
for i in range(tree_item.childCount()):
child_item = tree_item.child(i)
child_node = child_item.data(0, Qt.ItemDataRole.UserRole)
if isinstance(child_node, XslFile):
# XslFile gefunden - sammle alle XML-Dateien
for xml_file_obj in child_node.xmls:
pairs.append((child_node, xml_file_obj, child_item))
elif isinstance(child_node, TreeNode):
# Rekursiv in Unterknoten suchen
pairs.extend(self._collect_all_xsl_xml_pairs_recursive(child_node, child_item))
return pairs
def _transform_tree_node(self, item: QTreeWidgetItem, force: bool = False):
"""
Transformiert alle XML-Dateien unter einem TreeNode (rekursiv).
Args:
item: Das TreeWidgetItem des TreeNode
force: Wenn True, wird Transformation auch bei aktuellem Output durchgeführt
"""
try:
# Hole TreeNode-Objekt
tree_node_obj = item.data(0, Qt.ItemDataRole.UserRole)
if not isinstance(tree_node_obj, TreeNode):
logger.error(f"Item ist kein TreeNode: {type(tree_node_obj)}")
QMessageBox.warning(self, "Fehler", "Konnte TreeNode nicht ermitteln")
return
# Prüfe ob XML-Dateien vorhanden sind
if not self._has_xml_files_recursive(tree_node_obj):
QMessageBox.information(self, "Info", "Keine XML-Dateien unter diesem Knoten gefunden")
return
# Sammle alle XSL/XML-Paare rekursiv
xsl_xml_pairs = self._collect_all_xsl_xml_pairs_recursive(tree_node_obj, item)
if not xsl_xml_pairs:
QMessageBox.information(self, "Info", "Keine XML-Dateien gefunden")
return
# Erstelle TransformationJobs für alle XML-Dateien
jobs = []
for xsl_file_obj, xml_file_obj, xsl_file_item in xsl_xml_pairs:
# Übergebe das XslFile-TreeWidgetItem für Parameter-Sammlung
job = self._create_transformation_job(xsl_file_obj, xml_file_obj, xsl_file_item)
if job:
jobs.append(job)
if not jobs:
QMessageBox.warning(self, "Fehler", "Konnte keine Transformations-Jobs erstellen")
return
logger.info(f"Starte Transformation für {len(jobs)} XML-Dateien unter TreeNode '{tree_node_obj.bez}'")
# Starte Transformation in separatem Thread
self._start_transformation(jobs, force=force)
except Exception as e:
logger.error(f"Fehler beim Transformieren des TreeNode: {e}")
QMessageBox.critical(self, "Fehler", f"Fehler beim Transformieren: {str(e)}")
def _create_transformation_job(
self, xsl_file_obj: XslFile, xml_file_obj: XmlFile, xsl_file_item: QTreeWidgetItem | None = None
) -> TransformationJob | None: