diff --git a/src/ui/MainWinddow.ui b/src/ui/MainWinddow.ui index c8ee7c9..e2fcc72 100644 --- a/src/ui/MainWinddow.ui +++ b/src/ui/MainWinddow.ui @@ -341,6 +341,29 @@ + + + + false + + + ✅ Änderungen übernehmen + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + @@ -354,8 +377,8 @@ 0 0 - 625 - 700 + 726 + 695 diff --git a/src/ui/MainWinddow_ui.py b/src/ui/MainWinddow_ui.py index 05c4215..bbb127f 100644 --- a/src/ui/MainWinddow_ui.py +++ b/src/ui/MainWinddow_ui.py @@ -209,6 +209,16 @@ class Ui_MainWindow(object): self.horizontalLayout_3.addItem(self.horizontalSpacer_5) + self.accept_changes = QPushButton(self.frame_4) + self.accept_changes.setObjectName(u"accept_changes") + self.accept_changes.setEnabled(False) + + self.horizontalLayout_3.addWidget(self.accept_changes) + + self.horizontalSpacer_3 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) + + self.horizontalLayout_3.addItem(self.horizontalSpacer_3) + self.verticalLayout_4.addWidget(self.frame_4) @@ -217,7 +227,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, 625, 700)) + self.scrollAreaWidgetContents_2.setGeometry(QRect(0, 0, 726, 695)) self.verticalLayout_3 = QVBoxLayout(self.scrollAreaWidgetContents_2) self.verticalLayout_3.setObjectName(u"verticalLayout_3") self.verticalLayout_3.setContentsMargins(0, 0, 0, 0) @@ -293,6 +303,7 @@ class Ui_MainWindow(object): self.label_6.setText(QCoreApplication.translate("MainWindow", u"Vorher (Referenz)", None)) self.label_7.setText(QCoreApplication.translate("MainWindow", u"Nachher (Neu)", None)) self.label_5.setText(QCoreApplication.translate("MainWindow", u"Zoom", None)) + self.accept_changes.setText(QCoreApplication.translate("MainWindow", u"\u2705 \u00c4nderungen \u00fcbernehmen", None)) self.label_3.setText(QCoreApplication.translate("MainWindow", u"TextLabel", None)) self.label_4.setText(QCoreApplication.translate("MainWindow", u"TextLabel", None)) self.menuProjekt.setTitle(QCoreApplication.translate("MainWindow", u"Projekt", None)) diff --git a/src/ui/MainWindow.py b/src/ui/MainWindow.py index 7e4d4ad..7c95b28 100644 --- a/src/ui/MainWindow.py +++ b/src/ui/MainWindow.py @@ -209,6 +209,10 @@ class MainWindow(QMainWindow): self.current_page = 0 self.current_pdf = None + # Aktuelle Diff-PDF-Informationen (für Accept Changes) + self.current_diff_xml_path = None + self.current_diff_xsl_id = None + # Cache für die aktuell gerenderten Pixmaps (Performance-Optimierung) self.current_rendered_pixmaps = None @@ -752,6 +756,9 @@ class MainWindow(QMainWindow): # Button "lade aus FN2" verbinden self.ui.pB_lade_aus_fn2.clicked.connect(self.on_load_from_fn2_clicked) + # Button "Accept Changes" verbinden + self.ui.accept_changes.clicked.connect(self._on_accept_changes_clicked) + def _setup_tree_context_menu(self): """Richtet das Kontextmenü für das TreeWidget ein.""" # Aktiviere Kontextmenü für das TreeWidget @@ -1532,6 +1539,13 @@ class MainWindow(QMainWindow): # Setze die aktuelle PDF self.current_pdf = pdf_basename + # Speichere Diff-PDF-Informationen für Accept Changes + self.current_diff_xml_path = xml_file_path + self.current_diff_xsl_id = xsl_id_str + + # Aktiviere Accept-Changes-Button + self.ui.accept_changes.setEnabled(True) + # Zeige die erste Seite initial an self.render_and_display_page(pdf_basename, 0) @@ -3576,6 +3590,142 @@ class MainWindow(QMainWindow): f"{successful_count} von {total_count} Transformationen erfolgreich\n{failed_count} fehlgeschlagen", ) + def _find_next_diff_pdf(self) -> tuple[Path, str] | None: + """ + Findet die nächste Diff-PDF im Projekt. + + Returns: + tuple[Path, str] | None: (xml_file_path, xsl_id_str) der nächsten Diff-PDF oder None + """ + if not self.project: + return None + + diff_dir = self.project.project_dir / "diff" + if not diff_dir.exists(): + return None + + # Durchlaufe xml_item_map und prüfe welche Items Diff-PDFs haben + for map_key, tree_item in self.xml_item_map.items(): + # Map-Key hat Format "xml_path|xsl_id" + parts = map_key.split("|") + if len(parts) != 2: + continue + + xml_path_str = parts[0] + xsl_id_str = parts[1] + + # Konvertiere zu Path + xml_file_path = Path(xml_path_str) + + # Prüfe ob Diff-PDF existiert + xml_stem = xml_file_path.stem + pdf_basename = f"{xml_stem}_xsl_{xsl_id_str}.pdf" + diff_pdf_path = diff_dir / pdf_basename + + if diff_pdf_path.exists(): + return (xml_file_path, xsl_id_str) + + return None + + def _clear_pdf_viewer(self): + """Leert den PDF-Viewer und alle Thumbnails.""" + # Entferne Widgets aus Layouts + self._clear_layout(self.ui.verticalLayout_2) + self._clear_layout(self.ui.verticalLayout_3) + + # Zurücksetzen der Datenstrukturen + self.thumbnail_to_page = {} + self.pdf_documents = {} + self.current_rendered_pixmaps = None + self.fullsize_label = None + self.current_pdf = None + self.current_diff_xml_path = None + self.current_diff_xsl_id = None + + logger.info("PDF-Viewer geleert") + + def _on_accept_changes_clicked(self): + """ + Handler für Accept-Changes-Button. + Verschiebt new PDF nach ref, löscht diff PDF, aktualisiert Icons und lädt nächste Diff-PDF. + """ + try: + if not self.project or not self.current_diff_xml_path or not self.current_diff_xsl_id: + logger.warning("Keine aktuelle Diff-PDF zum Akzeptieren") + return + + # PDF-Dateinamen ermitteln + xml_stem = self.current_diff_xml_path.stem + pdf_basename = f"{xml_stem}_xsl_{self.current_diff_xsl_id}.pdf" + + # Pfade + diff_dir = self.project.project_dir / "diff" + ref_dir = self.project.project_dir / "ref" + new_dir = self.project.project_dir / "new" + + diff_pdf_path = diff_dir / pdf_basename + ref_pdf_path = ref_dir / pdf_basename + new_pdf_path = new_dir / pdf_basename + + logger.info(f"Akzeptiere Änderungen für: {pdf_basename}") + + # Prüfe ob new-PDF existiert + if not new_pdf_path.exists(): + QMessageBox.warning(self, "Fehler", f"New-PDF nicht gefunden:\n{pdf_basename}") + return + + # Lösche alte ref-PDF falls vorhanden + if ref_pdf_path.exists(): + ref_pdf_path.unlink() + logger.info(f"Alte Ref-PDF gelöscht: {ref_pdf_path}") + + # Verschiebe new-PDF nach ref + shutil.move(str(new_pdf_path), str(ref_pdf_path)) + logger.info(f"New-PDF verschoben nach Ref: {new_pdf_path} -> {ref_pdf_path}") + + # Lösche diff-PDF + if diff_pdf_path.exists(): + diff_pdf_path.unlink() + logger.info(f"Diff-PDF gelöscht: {diff_pdf_path}") + + # Diff-Icon beim aktuellen XML-Knoten entfernen + map_key = f"{self.current_diff_xml_path}|{self.current_diff_xsl_id}" + if map_key in self.xml_item_map: + tree_item = self.xml_item_map[map_key] + # Entferne Icon-Widget aus Spalte 2 + tree_item.setData(2, Qt.ItemDataRole.UserRole, None) + self.ui.treeWidget.setItemWidget(tree_item, 2, None) + logger.info(f"Diff-Icon entfernt für: {map_key}") + + # Diff-PDF-Anzahl auf übergeordneten Ebenen aktualisieren + self._update_all_diff_pdf_counts() + + # Finde nächste Diff-PDF + next_diff = self._find_next_diff_pdf() + + if next_diff: + # Lade nächste Diff-PDF + next_xml_path, next_xsl_id = next_diff + logger.info(f"Lade nächste Diff-PDF: {next_xml_path} / {next_xsl_id}") + self._load_pdf_for_comparison(next_xml_path, next_xsl_id) + + # Wähle den entsprechenden XML-Knoten im Baum aus + map_key = f"{next_xml_path}|{next_xsl_id}" + if map_key in self.xml_item_map: + tree_item = self.xml_item_map[map_key] + self.ui.treeWidget.setCurrentItem(tree_item) + self.ui.treeWidget.scrollToItem(tree_item) + logger.info(f"TreeWidget-Item ausgewählt: {map_key}") + else: + # Keine weiteren Diff-PDFs, Button deaktivieren und Viewer leeren + logger.info("Keine weiteren Diff-PDFs vorhanden") + self.ui.accept_changes.setEnabled(False) + self._clear_pdf_viewer() + + except Exception as e: + logger.error(f"Fehler beim Akzeptieren der Änderungen: {e}") + QMessageBox.critical(self, "Fehler", f"Fehler beim Akzeptieren der Änderungen:\n{str(e)}") + def closeEvent(self, event): """Wird beim Schließen der Anwendung aufgerufen.""" # UI-Zustände speichern