diff --git a/src/ui/mixins/tree_manager.py b/src/ui/mixins/tree_manager.py index b05afd8..c83c8cb 100644 --- a/src/ui/mixins/tree_manager.py +++ b/src/ui/mixins/tree_manager.py @@ -1031,6 +1031,23 @@ class TreeManagerMixin: logger.info(f"XML-Datei '{xml_filename}' aus XSL-Datei '{xsl_file_obj.bez}' entfernt") + # Prüfe ob die XML+XSL-Kombination noch woanders verwendet wird + # Wenn nicht, lösche die zugehörigen PDF-Dateien + xsl_id = xsl_file_obj.id + is_combination_used_elsewhere = self._is_xml_xsl_combination_used_elsewhere( + xml_file_obj.xml, xsl_id, xsl_file_obj + ) + + if not is_combination_used_elsewhere: + # Lösche alle PDF-Dateien für diese XML+XSL-Kombination + deleted_pdfs = self._delete_pdf_files_for_xml_xsl_combination(xml_file_obj.xml, xsl_id) + if deleted_pdfs > 0: + logger.info(f"{deleted_pdfs} PDF-Datei(en) für '{xml_filename}' (XSL: {xsl_file_obj.bez}) gelöscht") + else: + logger.debug( + f"XML+XSL-Kombination '{xml_filename}' + XSL-ID {xsl_id} wird noch anderswo verwendet - PDFs nicht gelöscht" + ) + # Frage ob die physische Datei auch gelöscht werden soll xml_file_path = Path(self.project.project_dir) / xml_file_obj.xml if xml_file_path.exists(): @@ -1117,6 +1134,95 @@ class TreeManagerMixin: return False + def _is_xml_xsl_combination_used_elsewhere(self, xml_path: Path, xsl_id: tuple, exclude_xsl_file) -> bool: + """ + Prüft ob eine XML+XSL-Kombination noch in anderen XSL-Dateien verwendet wird. + + Args: + xml_path: Pfad zur XML-Datei (relativ) + xsl_id: Tuple der XSL-ID + exclude_xsl_file: XSL-Datei die ausgeschlossen werden soll + + Returns: + bool: True wenn die Kombination noch anderswo verwendet wird + """ + try: + if not self.pdf_project or not self.pdf_project.nodes: + return False + + return self._check_xml_xsl_combination_recursive(self.pdf_project.nodes, xml_path, xsl_id, exclude_xsl_file) + except Exception as e: + logger.error(f"Fehler beim Prüfen der XML+XSL-Kombination: {e}") + return True # Im Zweifelsfall annehmen, dass sie verwendet wird + + def _check_xml_xsl_combination_recursive(self, nodes, xml_path: Path, xsl_id: tuple, exclude_xsl_file) -> bool: + """ + Prüft rekursiv ob eine XML+XSL-Kombination in den Nodes verwendet wird. + + Args: + nodes: Liste der zu prüfenden Nodes + xml_path: Pfad zur XML-Datei (relativ) + xsl_id: Tuple der XSL-ID + exclude_xsl_file: XSL-Datei die ausgeschlossen werden soll + + Returns: + bool: True wenn die Kombination gefunden wird + """ + for node in nodes: + if isinstance(node, XslFile) and node != exclude_xsl_file: + # Prüfe ob diese XSL-Datei die gleiche ID hat UND die XML-Datei verwendet + if node.id == xsl_id: + for xml_file in node.xmls: + if xml_file.xml == xml_path: + return True + elif isinstance(node, TreeNode) and node.children: + # Rekursiv in Knoten suchen + if self._check_xml_xsl_combination_recursive(node.children, xml_path, xsl_id, exclude_xsl_file): + return True + + return False + + def _delete_pdf_files_for_xml_xsl_combination(self, xml_path: Path, xsl_id: tuple) -> int: + """ + Löscht alle PDF-Dateien (new, ref, diff) für eine XML+XSL-Kombination. + + Args: + xml_path: Pfad zur XML-Datei (relativ) + xsl_id: Tuple der XSL-ID + + Returns: + int: Anzahl der gelöschten PDF-Dateien + """ + deleted_count = 0 + + try: + # Erzeuge den PDF-Dateinamen basierend auf XML und XSL-ID + base_name = xml_path.stem + xsl_id_str = "_".join(str(x) for x in xsl_id) + pdf_filename = f"{base_name}_xsl_{xsl_id_str}.pdf" + + # Lösche PDFs in allen drei Verzeichnissen + pdf_dirs = ["new", "ref", "diff"] + for dir_name in pdf_dirs: + pdf_path = self.project.project_dir / dir_name / pdf_filename + if pdf_path.exists(): + try: + pdf_path.unlink() + logger.info(f"PDF-Datei gelöscht: {pdf_path}") + deleted_count += 1 + except Exception as e: + logger.warning(f"Konnte PDF-Datei nicht löschen: {pdf_path} - {e}") + + if deleted_count > 0: + logger.info(f"{deleted_count} PDF-Datei(en) für {xml_path.name} (XSL-ID: {xsl_id}) gelöscht") + else: + logger.debug(f"Keine PDF-Dateien für {xml_path.name} (XSL-ID: {xsl_id}) gefunden") + + except Exception as e: + logger.error(f"Fehler beim Löschen der PDF-Dateien: {e}") + + return deleted_count + # Kontextmenü-Aktionen für Root-Elemente (Unbekannter Typ) def _add_root_tree_node(self): """Fügt einen neuen TreeNode als Root-Element hinzu."""