From 9be6ac24e90a31df16e69153bf862292e4dbd990 Mon Sep 17 00:00:00 2001 From: Vitali Graf Date: Mon, 9 Mar 2026 19:53:34 +0100 Subject: [PATCH] Refactor: AppSettings CRUD-Methoden durch generische Helfer vereinfacht MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 4 generische Helfer (_add_item, _remove_item, _edit_item, _update_remove_button) ersetzen 26 nahezu identische CRUD-Methoden für 7 Tool-Typen. _make_centered_item eliminiert QTableWidgetItem-Duplikation in populate-Methoden. Ergebnis: 805 → 508 Zeilen (-37%). Co-Authored-By: Claude Sonnet 4.6 --- src/ui/AppSettings.py | 724 +++++++++++++----------------------------- 1 file changed, 214 insertions(+), 510 deletions(-) diff --git a/src/ui/AppSettings.py b/src/ui/AppSettings.py index 08a1fc0..059e932 100644 --- a/src/ui/AppSettings.py +++ b/src/ui/AppSettings.py @@ -1,4 +1,4 @@ -from PySide6.QtWidgets import QDialog, QTableWidgetItem, QHeaderView +from PySide6.QtWidgets import QDialog, QTableWidgetItem, QHeaderView, QAbstractItemView from PySide6.QtCore import Qt from pathlib import Path @@ -23,14 +23,11 @@ class AppSettingsDlg(QDialog): ): super().__init__(parent) - # UI einrichten self.ui = Ui_Dialog() self.ui.setupUi(self) - # Einstellungen speichern self.settings = settings - # Temporäre Listen für Änderungen self.temp_java_vms = self.settings.java_vms.copy() self.temp_diff_pdfs = self.settings.diff_pdfs.copy() self.temp_saxon_jars = self.settings.saxon_jars.copy() @@ -39,94 +36,121 @@ class AppSettingsDlg(QDialog): self.temp_pdf_projects = self.settings.pdf_projects.copy() self.temp_postgresql_dbs = self.settings.postgresql_dbs.copy() - # Signale verbinden self._connect_signals() - - # Tabellen initialisieren self._setup_tables() self._populate_tables() - - # Performance-Tab initialisieren self._populate_performance_tab() + # --- Generische Helfer --- + + def _update_remove_button(self, table, button): + """Aktiviert/deaktiviert einen Entfernen-Button je nach Tabellenauswahl.""" + button.setEnabled(table.currentRow() >= 0) + + def _add_item(self, dialog_class, temp_list, settings_attr, factory_fn, populate_fn): + """Öffnet einen Dialog, erstellt ein neues Objekt und fügt es der Liste hinzu.""" + dialog = dialog_class(self) + if dialog.exec() == QDialog.DialogCode.Accepted: + data = dialog.get_data() + if data: + new_id = max((x.id for x in temp_list), default=0) + 1 + temp_list.append(factory_fn(new_id, data)) + populate_fn() + setattr(self.settings, settings_attr, temp_list.copy()) + self.settings.save() + self._refresh_main_window_projects_menu() + + def _remove_item(self, table, temp_list, settings_attr, update_fn, populate_fn): + """Entfernt das ausgewählte Element aus der Liste und speichert die Einstellungen.""" + row = table.currentRow() + if row >= 0: + del temp_list[row] + populate_fn() + update_fn() + setattr(self.settings, settings_attr, temp_list.copy()) + self.settings.save() + self._refresh_main_window_projects_menu() + + def _edit_item(self, index, temp_list, dialog_class, fields, populate_fn): + """Öffnet einen Bearbeitungs-Dialog für das gewählte Element.""" + row = index.row() + if 0 <= row < len(temp_list): + item = temp_list[row] + dialog = dialog_class(self) + dialog.set_data({f: getattr(item, f) for f in fields}) + if dialog.exec() == QDialog.DialogCode.Accepted: + new_data = dialog.get_data() + if new_data: + for f in fields: + setattr(item, f, new_data[f]) + populate_fn() + + # --- Signale und Tabellen-Setup --- + def _connect_signals(self): """Verbindet die Signale der UI-Elemente.""" - # XSL-Ordner Tab self.ui.addXsl.clicked.connect(self._add_xsl_dir) self.ui.removeXsl.clicked.connect(self._remove_xsl_dir) self.ui.tableXsls.itemSelectionChanged.connect(self._update_xsl_buttons) - # Java VM Tab self.ui.addJavaVm.clicked.connect(self._add_java_vm) self.ui.removeJavaVm.clicked.connect(self._remove_java_vm) self.ui.tableJavaVms.itemSelectionChanged.connect(self._update_java_vm_buttons) - # Saxon Tab self.ui.addSaxon.clicked.connect(self._add_saxon) self.ui.removeSaxon.clicked.connect(self._remove_saxon) self.ui.tableSaxons.itemSelectionChanged.connect(self._update_saxon_buttons) - # Apache FOP Tab self.ui.addApacheFop.clicked.connect(self._add_apache_fop) self.ui.removeApacheFop.clicked.connect(self._remove_apache_fop) self.ui.tableApacheFops.itemSelectionChanged.connect(self._update_apache_fop_buttons) - # Diff PDF Tab self.ui.addDiffPdf.clicked.connect(self._add_diff_pdf) self.ui.removeDiffPdf.clicked.connect(self._remove_diff_pdf) self.ui.tableDiffPdfs.itemSelectionChanged.connect(self._update_diff_pdf_buttons) - # PDF-Projekte Tab self.ui.removeProject.clicked.connect(self._remove_pdf_project) self.ui.addProject.clicked.connect(self._add_pdf_project) self.ui.tablePdfProjects.itemSelectionChanged.connect(self._update_pdf_project_buttons) - # PostgreSQL Tab self.ui.addPostgreSql.clicked.connect(self._add_postgresql_db) self.ui.removePostgreSql.clicked.connect(self._remove_postgresql_db) self.ui.tablePostgreSqlDbs.itemSelectionChanged.connect(self._update_postgresql_db_buttons) def _setup_tables(self): """Richtet die Tabellen-Header ein und macht sie unveränderbar.""" - from PySide6.QtWidgets import QAbstractItemView - - # XSL-Ordner Tabelle self.ui.tableXsls.setHorizontalHeaderLabels(["Name", "Pfad"]) self.ui.tableXsls.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers) self.ui.tableXsls.doubleClicked.connect(self._edit_xsl_dir) - # Java VM Tabelle self.ui.tableJavaVms.setHorizontalHeaderLabels(["Version", "Pfad"]) self.ui.tableJavaVms.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers) self.ui.tableJavaVms.doubleClicked.connect(self._edit_java_vm) - # Saxon Tabelle self.ui.tableSaxons.setHorizontalHeaderLabels(["Version", "JAR-Pfad", "Erweiterung"]) self.ui.tableSaxons.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers) self.ui.tableSaxons.doubleClicked.connect(self._edit_saxon) - # Apache FOP Tabelle self.ui.tableApacheFops.setHorizontalHeaderLabels(["Version", "Pfad", "Erweiterung"]) self.ui.tableApacheFops.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers) self.ui.tableApacheFops.doubleClicked.connect(self._edit_apache_fop) - # Diff PDF Tabelle self.ui.tableDiffPdfs.setHorizontalHeaderLabels(["Version", "Pfad", "Parameter", "Erweiterung"]) self.ui.tableDiffPdfs.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers) self.ui.tableDiffPdfs.doubleClicked.connect(self._edit_diff_pdf) - # PDF-Projekte Tabelle self.ui.tablePdfProjects.setHorizontalHeaderLabels( ["Name", "Projekt-Ordner", "XSL-Ordner", "Java-VM", "Saxon", "Apache FOP", "Diff-PDF"] ) self.ui.tablePdfProjects.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers) self.ui.tablePdfProjects.doubleClicked.connect(self._edit_pdf_project) - # PostgreSQL Tabelle self.ui.tablePostgreSqlDbs.setHorizontalHeaderLabels(["Name", "Host", "Port", "Datenbank", "Benutzer"]) self.ui.tablePostgreSqlDbs.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers) self.ui.tablePostgreSqlDbs.doubleClicked.connect(self._edit_postgresql_db) + # --- Tabellen befüllen --- + def _populate_tables(self): """Füllt alle Tabellen mit den aktuellen Einstellungen.""" self._populate_xsl_table() @@ -137,160 +161,86 @@ class AppSettingsDlg(QDialog): self._populate_pdf_project_table() self._populate_postgresql_db_table() + def _make_centered_item(self, text: str) -> QTableWidgetItem: + item = QTableWidgetItem(text) + item.setTextAlignment(Qt.AlignmentFlag.AlignCenter) + return item + def _populate_xsl_table(self): """Füllt die XSL-Ordner Tabelle.""" self.ui.tableXsls.setRowCount(len(self.temp_xsl_dirs)) - for row, xsl_dir in enumerate(self.temp_xsl_dirs): - name_item = QTableWidgetItem(xsl_dir.name) - name_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter) - self.ui.tableXsls.setItem(row, 0, name_item) - - path_item = QTableWidgetItem(str(xsl_dir.path_to_root_dir)) - path_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter) - self.ui.tableXsls.setItem(row, 1, path_item) + for row, x in enumerate(self.temp_xsl_dirs): + self.ui.tableXsls.setItem(row, 0, self._make_centered_item(x.name)) + self.ui.tableXsls.setItem(row, 1, self._make_centered_item(str(x.path_to_root_dir))) self.ui.tableXsls.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents) def _populate_java_vm_table(self): """Füllt die Java VM Tabelle.""" self.ui.tableJavaVms.setRowCount(len(self.temp_java_vms)) - for row, java_vm in enumerate(self.temp_java_vms): - version_item = QTableWidgetItem(java_vm.version) - version_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter) - self.ui.tableJavaVms.setItem(row, 0, version_item) - - path_item = QTableWidgetItem(str(java_vm.path_to_binary_file)) - path_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter) - self.ui.tableJavaVms.setItem(row, 1, path_item) + for row, x in enumerate(self.temp_java_vms): + self.ui.tableJavaVms.setItem(row, 0, self._make_centered_item(x.version)) + self.ui.tableJavaVms.setItem(row, 1, self._make_centered_item(str(x.path_to_binary_file))) self.ui.tableJavaVms.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents) def _populate_saxon_table(self): """Füllt die Saxon Tabelle.""" self.ui.tableSaxons.setRowCount(len(self.temp_saxon_jars)) - for row, saxon in enumerate(self.temp_saxon_jars): - version_item = QTableWidgetItem(saxon.version) - version_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter) - self.ui.tableSaxons.setItem(row, 0, version_item) - - path_item = QTableWidgetItem(str(saxon.path_to_jar_file)) - path_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter) - self.ui.tableSaxons.setItem(row, 1, path_item) - - extension_item = QTableWidgetItem(saxon.output_file_extension) - extension_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter) - self.ui.tableSaxons.setItem(row, 2, extension_item) + for row, x in enumerate(self.temp_saxon_jars): + self.ui.tableSaxons.setItem(row, 0, self._make_centered_item(x.version)) + self.ui.tableSaxons.setItem(row, 1, self._make_centered_item(str(x.path_to_jar_file))) + self.ui.tableSaxons.setItem(row, 2, self._make_centered_item(x.output_file_extension)) self.ui.tableSaxons.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents) def _populate_apache_fop_table(self): """Füllt die Apache FOP Tabelle.""" self.ui.tableApacheFops.setRowCount(len(self.temp_apache_fops)) - for row, fop in enumerate(self.temp_apache_fops): - version_item = QTableWidgetItem(fop.version) - version_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter) - self.ui.tableApacheFops.setItem(row, 0, version_item) - - path_item = QTableWidgetItem(str(fop.path_to_dir)) - path_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter) - self.ui.tableApacheFops.setItem(row, 1, path_item) - - extension_item = QTableWidgetItem(fop.output_file_extension) - extension_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter) - self.ui.tableApacheFops.setItem(row, 2, extension_item) + for row, x in enumerate(self.temp_apache_fops): + self.ui.tableApacheFops.setItem(row, 0, self._make_centered_item(x.version)) + self.ui.tableApacheFops.setItem(row, 1, self._make_centered_item(str(x.path_to_dir))) + self.ui.tableApacheFops.setItem(row, 2, self._make_centered_item(x.output_file_extension)) self.ui.tableApacheFops.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents) def _populate_diff_pdf_table(self): """Füllt die Diff PDF Tabelle.""" self.ui.tableDiffPdfs.setRowCount(len(self.temp_diff_pdfs)) - for row, diff_pdf in enumerate(self.temp_diff_pdfs): - version_item = QTableWidgetItem(diff_pdf.version) - version_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter) - self.ui.tableDiffPdfs.setItem(row, 0, version_item) - - path_item = QTableWidgetItem(str(diff_pdf.path_to_binary_file)) - path_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter) - self.ui.tableDiffPdfs.setItem(row, 1, path_item) - - params_item = QTableWidgetItem(", ".join(diff_pdf.default_params)) - params_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter) - self.ui.tableDiffPdfs.setItem(row, 2, params_item) - - extension_item = QTableWidgetItem(diff_pdf.output_file_extension) - extension_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter) - self.ui.tableDiffPdfs.setItem(row, 3, extension_item) + for row, x in enumerate(self.temp_diff_pdfs): + self.ui.tableDiffPdfs.setItem(row, 0, self._make_centered_item(x.version)) + self.ui.tableDiffPdfs.setItem(row, 1, self._make_centered_item(str(x.path_to_binary_file))) + self.ui.tableDiffPdfs.setItem(row, 2, self._make_centered_item(", ".join(x.default_params))) + self.ui.tableDiffPdfs.setItem(row, 3, self._make_centered_item(x.output_file_extension)) self.ui.tableDiffPdfs.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents) def _populate_pdf_project_table(self): """Füllt die PDF-Projekte Tabelle.""" self.ui.tablePdfProjects.setRowCount(len(self.temp_pdf_projects)) - for row, pdf_project in enumerate(self.temp_pdf_projects): - name_item = QTableWidgetItem(pdf_project.name) - name_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter) - self.ui.tablePdfProjects.setItem(row, 0, name_item) - - project_dir_item = QTableWidgetItem(str(pdf_project.project_dir)) - project_dir_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter) - self.ui.tablePdfProjects.setItem(row, 1, project_dir_item) - - xsl_item = QTableWidgetItem(pdf_project.getXsl()) - xsl_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter) - self.ui.tablePdfProjects.setItem(row, 2, xsl_item) - - java_vm_item = QTableWidgetItem(pdf_project.getJavaVm()) - java_vm_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter) - self.ui.tablePdfProjects.setItem(row, 3, java_vm_item) - - saxon_item = QTableWidgetItem(pdf_project.getSaxon()) - saxon_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter) - self.ui.tablePdfProjects.setItem(row, 4, saxon_item) - - apache_fop_item = QTableWidgetItem(pdf_project.getApacheFop()) - apache_fop_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter) - self.ui.tablePdfProjects.setItem(row, 5, apache_fop_item) - - diff_pdf_item = QTableWidgetItem(pdf_project.getDiffPdf()) - diff_pdf_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter) - self.ui.tablePdfProjects.setItem(row, 6, diff_pdf_item) + for row, p in enumerate(self.temp_pdf_projects): + self.ui.tablePdfProjects.setItem(row, 0, self._make_centered_item(p.name)) + self.ui.tablePdfProjects.setItem(row, 1, self._make_centered_item(str(p.project_dir))) + self.ui.tablePdfProjects.setItem(row, 2, self._make_centered_item(p.getXsl())) + self.ui.tablePdfProjects.setItem(row, 3, self._make_centered_item(p.getJavaVm())) + self.ui.tablePdfProjects.setItem(row, 4, self._make_centered_item(p.getSaxon())) + self.ui.tablePdfProjects.setItem(row, 5, self._make_centered_item(p.getApacheFop())) + self.ui.tablePdfProjects.setItem(row, 6, self._make_centered_item(p.getDiffPdf())) self.ui.tablePdfProjects.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents) def _populate_postgresql_db_table(self): """Füllt die PostgreSQL-Datenbank Tabelle.""" self.ui.tablePostgreSqlDbs.setRowCount(len(self.temp_postgresql_dbs)) - for row, postgresql_db in enumerate(self.temp_postgresql_dbs): - name_item = QTableWidgetItem(postgresql_db.name) - name_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter) - self.ui.tablePostgreSqlDbs.setItem(row, 0, name_item) - - host_item = QTableWidgetItem(postgresql_db.host) - host_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter) - self.ui.tablePostgreSqlDbs.setItem(row, 1, host_item) - - port_item = QTableWidgetItem(str(postgresql_db.port)) - port_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter) - self.ui.tablePostgreSqlDbs.setItem(row, 2, port_item) - - database_item = QTableWidgetItem(postgresql_db.database) - database_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter) - self.ui.tablePostgreSqlDbs.setItem(row, 3, database_item) - - username_item = QTableWidgetItem(postgresql_db.username) - username_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter) - self.ui.tablePostgreSqlDbs.setItem(row, 4, username_item) + for row, x in enumerate(self.temp_postgresql_dbs): + self.ui.tablePostgreSqlDbs.setItem(row, 0, self._make_centered_item(x.name)) + self.ui.tablePostgreSqlDbs.setItem(row, 1, self._make_centered_item(x.host)) + self.ui.tablePostgreSqlDbs.setItem(row, 2, self._make_centered_item(str(x.port))) + self.ui.tablePostgreSqlDbs.setItem(row, 3, self._make_centered_item(x.database)) + self.ui.tablePostgreSqlDbs.setItem(row, 4, self._make_centered_item(x.username)) 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) - - # XSLT-Version ComboBox setzen - if self.settings.saxon_xslt_version == XsltVersion.XSLT_1_0: - self.ui.comboBoxXsltVersion.setCurrentIndex(0) - else: # XSLT_2_0_3_0 - self.ui.comboBoxXsltVersion.setCurrentIndex(1) - - # FopWorkerPool-Checkbox setzen + self.ui.comboBoxXsltVersion.setCurrentIndex( + 0 if self.settings.saxon_xslt_version == XsltVersion.XSLT_1_0 else 1 + ) self.ui.checkBoxUseFopPool.setChecked(self.settings.use_fop_worker_pool) def _refresh_main_window_projects_menu(self): @@ -298,201 +248,138 @@ class AppSettingsDlg(QDialog): if self.parent() and hasattr(self.parent(), "_setup_projects_menu"): self.parent()._setup_projects_menu() - # XSL-Ordner Methoden - def _add_xsl_dir(self): - """Fügt einen neuen XSL-Ordner hinzu.""" - dialog = XslDirConfigDialog(self) - if dialog.exec() == QDialog.DialogCode.Accepted: - data = dialog.get_data() - if data: - # Neue ID generieren - new_id = max([x.id for x in self.temp_xsl_dirs], default=0) + 1 - new_xsl_dir = XslDir(id=new_id, name=data["name"], path_to_root_dir=data["path_to_root_dir"]) - self.temp_xsl_dirs.append(new_xsl_dir) - self._populate_xsl_table() + # --- XSL-Ordner --- - self.settings.xsl_dirs = self.temp_xsl_dirs.copy() - self.settings.save() - self._refresh_main_window_projects_menu() + def _add_xsl_dir(self): + self._add_item( + XslDirConfigDialog, self.temp_xsl_dirs, "xsl_dirs", + lambda id, d: XslDir(id=id, name=d["name"], path_to_root_dir=d["path_to_root_dir"]), + self._populate_xsl_table, + ) def _remove_xsl_dir(self): - """Entfernt den ausgewählten XSL-Ordner.""" - current_row = self.ui.tableXsls.currentRow() - if current_row >= 0: - del self.temp_xsl_dirs[current_row] - self._populate_xsl_table() - self._update_xsl_buttons() - - self.settings.xsl_dirs = self.temp_xsl_dirs.copy() - self.settings.save() - self._refresh_main_window_projects_menu() + self._remove_item( + self.ui.tableXsls, self.temp_xsl_dirs, "xsl_dirs", + self._update_xsl_buttons, self._populate_xsl_table, + ) def _update_xsl_buttons(self): - """Aktualisiert den Status der XSL-Buttons.""" - has_selection = self.ui.tableXsls.currentRow() >= 0 - self.ui.removeXsl.setEnabled(has_selection) + self._update_remove_button(self.ui.tableXsls, self.ui.removeXsl) + + def _edit_xsl_dir(self, index): + self._edit_item(index, self.temp_xsl_dirs, XslDirConfigDialog, + ["name", "path_to_root_dir"], self._populate_xsl_table) + + # --- Java VM --- - # Java VM Methoden def _add_java_vm(self): - """Fügt eine neue Java VM hinzu.""" - dialog = JavaVmConfigDialog(self) - if dialog.exec() == QDialog.DialogCode.Accepted: - data = dialog.get_data() - if data: - new_id = max([x.id for x in self.temp_java_vms], default=0) + 1 - new_java_vm = JavaVm( - id=new_id, version=data["version"], path_to_binary_file=data["path_to_binary_file"] - ) - self.temp_java_vms.append(new_java_vm) - self._populate_java_vm_table() - - self.settings.java_vms = self.temp_java_vms.copy() - self.settings.save() - self._refresh_main_window_projects_menu() + self._add_item( + JavaVmConfigDialog, self.temp_java_vms, "java_vms", + lambda id, d: JavaVm(id=id, version=d["version"], path_to_binary_file=d["path_to_binary_file"]), + self._populate_java_vm_table, + ) def _remove_java_vm(self): - """Entfernt die ausgewählte Java VM.""" - current_row = self.ui.tableJavaVms.currentRow() - if current_row >= 0: - del self.temp_java_vms[current_row] - self._populate_java_vm_table() - self._update_java_vm_buttons() - - self.settings.java_vms = self.temp_java_vms.copy() - self.settings.save() - self._refresh_main_window_projects_menu() + self._remove_item( + self.ui.tableJavaVms, self.temp_java_vms, "java_vms", + self._update_java_vm_buttons, self._populate_java_vm_table, + ) def _update_java_vm_buttons(self): - """Aktualisiert den Status der Java VM-Buttons.""" - has_selection = self.ui.tableJavaVms.currentRow() >= 0 - self.ui.removeJavaVm.setEnabled(has_selection) + self._update_remove_button(self.ui.tableJavaVms, self.ui.removeJavaVm) + + def _edit_java_vm(self, index): + self._edit_item(index, self.temp_java_vms, JavaVmConfigDialog, + ["version", "path_to_binary_file"], self._populate_java_vm_table) + + # --- Saxon --- - # Saxon Methoden def _add_saxon(self): - """Fügt eine neue Saxon JAR hinzu.""" - dialog = SaxonJarConfigDialog(self) - if dialog.exec() == QDialog.DialogCode.Accepted: - data = dialog.get_data() - if data: - new_id = max([x.id for x in self.temp_saxon_jars], default=0) + 1 - new_saxon = SaxonJar( - id=new_id, - version=data["version"], - path_to_jar_file=data["path_to_jar_file"], - output_file_extension=data["output_file_extension"], - ) - self.temp_saxon_jars.append(new_saxon) - self._populate_saxon_table() - - self.settings.saxon_jars = self.temp_saxon_jars.copy() - self.settings.save() - self._refresh_main_window_projects_menu() + self._add_item( + SaxonJarConfigDialog, self.temp_saxon_jars, "saxon_jars", + lambda id, d: SaxonJar( + id=id, version=d["version"], + path_to_jar_file=d["path_to_jar_file"], + output_file_extension=d["output_file_extension"], + ), + self._populate_saxon_table, + ) def _remove_saxon(self): - """Entfernt die ausgewählte Saxon JAR.""" - current_row = self.ui.tableSaxons.currentRow() - if current_row >= 0: - del self.temp_saxon_jars[current_row] - self._populate_saxon_table() - self._update_saxon_buttons() - - self.settings.saxon_jars = self.temp_saxon_jars.copy() - self.settings.save() - self._refresh_main_window_projects_menu() + self._remove_item( + self.ui.tableSaxons, self.temp_saxon_jars, "saxon_jars", + self._update_saxon_buttons, self._populate_saxon_table, + ) def _update_saxon_buttons(self): - """Aktualisiert den Status der Saxon-Buttons.""" - has_selection = self.ui.tableSaxons.currentRow() >= 0 - self.ui.removeSaxon.setEnabled(has_selection) + self._update_remove_button(self.ui.tableSaxons, self.ui.removeSaxon) + + def _edit_saxon(self, index): + self._edit_item(index, self.temp_saxon_jars, SaxonJarConfigDialog, + ["version", "path_to_jar_file", "output_file_extension"], self._populate_saxon_table) + + # --- Apache FOP --- - # Apache FOP Methoden def _add_apache_fop(self): - """Fügt eine neue Apache FOP Konfiguration hinzu.""" - dialog = ApacheFopConfigDialog(self) - if dialog.exec() == QDialog.DialogCode.Accepted: - data = dialog.get_data() - if data: - new_id = max([x.id for x in self.temp_apache_fops], default=0) + 1 - new_fop = ApacheFop( - id=new_id, - version=data["version"], - path_to_dir=data["path_to_dir"], - output_file_extension=data["output_file_extension"], - ) - self.temp_apache_fops.append(new_fop) - self._populate_apache_fop_table() - - self.settings.apache_fops = self.temp_apache_fops.copy() - self.settings.save() - self._refresh_main_window_projects_menu() + self._add_item( + ApacheFopConfigDialog, self.temp_apache_fops, "apache_fops", + lambda id, d: ApacheFop( + id=id, version=d["version"], + path_to_dir=d["path_to_dir"], + output_file_extension=d["output_file_extension"], + ), + self._populate_apache_fop_table, + ) def _remove_apache_fop(self): - """Entfernt die ausgewählte Apache FOP Konfiguration.""" - current_row = self.ui.tableApacheFops.currentRow() - if current_row >= 0: - del self.temp_apache_fops[current_row] - self._populate_apache_fop_table() - self._update_apache_fop_buttons() - - self.settings.apache_fops = self.temp_apache_fops.copy() - self.settings.save() - self._refresh_main_window_projects_menu() + self._remove_item( + self.ui.tableApacheFops, self.temp_apache_fops, "apache_fops", + self._update_apache_fop_buttons, self._populate_apache_fop_table, + ) def _update_apache_fop_buttons(self): - """Aktualisiert den Status der Apache FOP-Buttons.""" - has_selection = self.ui.tableApacheFops.currentRow() >= 0 - self.ui.removeApacheFop.setEnabled(has_selection) + self._update_remove_button(self.ui.tableApacheFops, self.ui.removeApacheFop) + + def _edit_apache_fop(self, index): + self._edit_item(index, self.temp_apache_fops, ApacheFopConfigDialog, + ["version", "path_to_dir", "output_file_extension"], self._populate_apache_fop_table) + + # --- Diff PDF --- - # Diff PDF Methoden def _add_diff_pdf(self): - """Fügt eine neue Diff PDF Konfiguration hinzu.""" - dialog = DiffPdfConfigDialog(self) - if dialog.exec() == QDialog.DialogCode.Accepted: - data = dialog.get_data() - if data: - new_id = max([x.id for x in self.temp_diff_pdfs], default=0) + 1 - new_diff_pdf = DiffPdf( - id=new_id, - version=data["version"], - path_to_binary_file=data["path_to_binary_file"], - default_params=data["default_params"], - output_file_extension=data["output_file_extension"], - ) - self.temp_diff_pdfs.append(new_diff_pdf) - self._populate_diff_pdf_table() - - self.settings.diff_pdfs = self.temp_diff_pdfs.copy() - self.settings.save() - self._refresh_main_window_projects_menu() + self._add_item( + DiffPdfConfigDialog, self.temp_diff_pdfs, "diff_pdfs", + lambda id, d: DiffPdf( + id=id, version=d["version"], + path_to_binary_file=d["path_to_binary_file"], + default_params=d["default_params"], + output_file_extension=d["output_file_extension"], + ), + self._populate_diff_pdf_table, + ) def _remove_diff_pdf(self): - """Entfernt die ausgewählte Diff PDF Konfiguration.""" - current_row = self.ui.tableDiffPdfs.currentRow() - if current_row >= 0: - del self.temp_diff_pdfs[current_row] - self._populate_diff_pdf_table() - self._update_diff_pdf_buttons() - - self.settings.diff_pdfs = self.temp_diff_pdfs.copy() - self.settings.save() - self._refresh_main_window_projects_menu() + self._remove_item( + self.ui.tableDiffPdfs, self.temp_diff_pdfs, "diff_pdfs", + self._update_diff_pdf_buttons, self._populate_diff_pdf_table, + ) def _update_diff_pdf_buttons(self): - """Aktualisiert den Status der Diff PDF-Buttons.""" - has_selection = self.ui.tableDiffPdfs.currentRow() >= 0 - self.ui.removeDiffPdf.setEnabled(has_selection) + self._update_remove_button(self.ui.tableDiffPdfs, self.ui.removeDiffPdf) + + def _edit_diff_pdf(self, index): + self._edit_item(index, self.temp_diff_pdfs, DiffPdfConfigDialog, + ["version", "path_to_binary_file", "default_params", "output_file_extension"], + self._populate_diff_pdf_table) + + # --- PDF-Projekte (Sonderbehandlung wegen komplexer Logik) --- - # PDF-Projekt Methoden def _add_pdf_project(self): """Fügt ein neues PDF-Projekt hinzu.""" dialog = PdfProjectDlg(self) if dialog.exec() == PdfProjectDlg.DialogCode.Accepted: project_data = dialog.get_project_data() - - # Neue ID generieren - new_id = max([p.id for p in self.temp_pdf_projects], default=0) + 1 - - # Erstelle PdfProject-Objekt + new_id = max((p.id for p in self.temp_pdf_projects), default=0) + 1 new_project = Project( id=new_id, name=project_data["name"], @@ -505,151 +392,26 @@ class AppSettingsDlg(QDialog): postgre_sql_db_id=project_data["postgre_sql_db_id"] if project_data["postgre_sql_db_id"] != -1 else 1, fop_config_dir=Path(project_data["fop_config_dir"]) if project_data.get("fop_config_dir") else None, ) - self.temp_pdf_projects.append(new_project) self._populate_pdf_project_table() - self.settings.pdf_projects = self.temp_pdf_projects.copy() self.settings.save() self._refresh_main_window_projects_menu() def _remove_pdf_project(self): - """Entfernt das ausgewählte PDF-Projekt.""" - current_row = self.ui.tablePdfProjects.currentRow() - if current_row >= 0: - del self.temp_pdf_projects[current_row] - self._populate_pdf_project_table() - self._update_pdf_project_buttons() - - self.settings.pdf_projects = self.temp_pdf_projects.copy() - self.settings.save() - self._refresh_main_window_projects_menu() + self._remove_item( + self.ui.tablePdfProjects, self.temp_pdf_projects, "pdf_projects", + self._update_pdf_project_buttons, self._populate_pdf_project_table, + ) def _update_pdf_project_buttons(self): - """Aktualisiert den Status der PDF-Projekt-Buttons.""" - has_selection = self.ui.tablePdfProjects.currentRow() >= 0 - self.ui.removeProject.setEnabled(has_selection) - - # Bearbeitungsmethoden für Doppelklick-Events - def _edit_xsl_dir(self, index): - """Bearbeitet einen XSL-Ordner per Doppelklick.""" - row = index.row() - if 0 <= row < len(self.temp_xsl_dirs): - xsl_dir = self.temp_xsl_dirs[row] - dialog = XslDirConfigDialog(self) - - # Vorhandene Daten setzen - data = {"name": xsl_dir.name, "path_to_root_dir": xsl_dir.path_to_root_dir} - dialog.set_data(data) - - if dialog.exec() == QDialog.DialogCode.Accepted: - new_data = dialog.get_data() - if new_data: - # Daten aktualisieren - xsl_dir.name = new_data["name"] - xsl_dir.path_to_root_dir = new_data["path_to_root_dir"] - self._populate_xsl_table() - - def _edit_java_vm(self, index): - """Bearbeitet eine Java VM per Doppelklick.""" - row = index.row() - if 0 <= row < len(self.temp_java_vms): - java_vm = self.temp_java_vms[row] - dialog = JavaVmConfigDialog(self) - - # Vorhandene Daten setzen - data = {"version": java_vm.version, "path_to_binary_file": java_vm.path_to_binary_file} - dialog.set_data(data) - - if dialog.exec() == QDialog.DialogCode.Accepted: - new_data = dialog.get_data() - if new_data: - # Daten aktualisieren - java_vm.version = new_data["version"] - java_vm.path_to_binary_file = new_data["path_to_binary_file"] - self._populate_java_vm_table() - - def _edit_saxon(self, index): - """Bearbeitet eine Saxon JAR per Doppelklick.""" - row = index.row() - if 0 <= row < len(self.temp_saxon_jars): - saxon = self.temp_saxon_jars[row] - dialog = SaxonJarConfigDialog(self) - - # Vorhandene Daten setzen - data = { - "version": saxon.version, - "path_to_jar_file": saxon.path_to_jar_file, - "output_file_extension": saxon.output_file_extension, - } - dialog.set_data(data) - - if dialog.exec() == QDialog.DialogCode.Accepted: - new_data = dialog.get_data() - if new_data: - # Daten aktualisieren - saxon.version = new_data["version"] - saxon.path_to_jar_file = new_data["path_to_jar_file"] - saxon.output_file_extension = new_data["output_file_extension"] - self._populate_saxon_table() - - def _edit_apache_fop(self, index): - """Bearbeitet eine Apache FOP Konfiguration per Doppelklick.""" - row = index.row() - if 0 <= row < len(self.temp_apache_fops): - fop = self.temp_apache_fops[row] - dialog = ApacheFopConfigDialog(self) - - # Vorhandene Daten setzen - data = { - "version": fop.version, - "path_to_dir": fop.path_to_dir, - "output_file_extension": fop.output_file_extension, - } - dialog.set_data(data) - - if dialog.exec() == QDialog.DialogCode.Accepted: - new_data = dialog.get_data() - if new_data: - # Daten aktualisieren - fop.version = new_data["version"] - fop.path_to_dir = new_data["path_to_dir"] - fop.output_file_extension = new_data["output_file_extension"] - self._populate_apache_fop_table() - - def _edit_diff_pdf(self, index): - """Bearbeitet eine Diff PDF Konfiguration per Doppelklick.""" - row = index.row() - if 0 <= row < len(self.temp_diff_pdfs): - diff_pdf = self.temp_diff_pdfs[row] - dialog = DiffPdfConfigDialog(self) - - # Vorhandene Daten setzen - data = { - "version": diff_pdf.version, - "path_to_binary_file": diff_pdf.path_to_binary_file, - "default_params": diff_pdf.default_params, - "output_file_extension": diff_pdf.output_file_extension, - } - dialog.set_data(data) - - if dialog.exec() == QDialog.DialogCode.Accepted: - new_data = dialog.get_data() - if new_data: - # Daten aktualisieren - diff_pdf.version = new_data["version"] - diff_pdf.path_to_binary_file = new_data["path_to_binary_file"] - diff_pdf.default_params = new_data["default_params"] - diff_pdf.output_file_extension = new_data["output_file_extension"] - self._populate_diff_pdf_table() + self._update_remove_button(self.ui.tablePdfProjects, self.ui.removeProject) def _edit_pdf_project(self, index): """Bearbeitet ein PDF-Projekt per Doppelklick (nur Einstellungen).""" row = index.row() if 0 <= row < len(self.temp_pdf_projects): pdf_project = self.temp_pdf_projects[row] - - # Projektdaten für Dialog vorbereiten project_data = { "name": pdf_project.name, "project_dir": str(pdf_project.project_dir), @@ -661,14 +423,9 @@ class AppSettingsDlg(QDialog): "postgre_sql_db_id": pdf_project.postgre_sql_db_id, "fop_config_dir": str(pdf_project.fop_config_dir) if pdf_project.fop_config_dir else None, } - - # Dialog im Edit-Modus öffnen (Projekt-Ordner deaktiviert) dialog = PdfProjectDlg(self, project_data, edit_mode=True) - if dialog.exec() == PdfProjectDlg.DialogCode.Accepted: new_data = dialog.get_project_data() - - # Einstellungen aktualisieren (Ordner bleibt unverändert) pdf_project.name = new_data["name"] pdf_project.java_vm_id = ( new_data["java_vm_id"] if new_data["java_vm_id"] != -1 else pdf_project.java_vm_id @@ -693,88 +450,41 @@ class AppSettingsDlg(QDialog): pdf_project.fop_config_dir = ( Path(new_data["fop_config_dir"]) if new_data.get("fop_config_dir") else None ) - self._populate_pdf_project_table() - - # Einstellungen speichern self.settings.pdf_projects = self.temp_pdf_projects.copy() self.settings.save() self._refresh_main_window_projects_menu() - # PostgreSQL Methoden - def _add_postgresql_db(self): - """Fügt eine neue PostgreSQL-Datenbank hinzu.""" - dialog = PostgreSqlConfigDialog(self) - if dialog.exec() == QDialog.DialogCode.Accepted: - data = dialog.get_data() - if data: - new_id = max([x.id for x in self.temp_postgresql_dbs], default=0) + 1 - new_postgresql_db = PostgreSqlDb( - id=new_id, - name=data["name"], - host=data["host"], - port=data["port"], - database=data["database"], - username=data["username"], - password=data["password"], - ) - self.temp_postgresql_dbs.append(new_postgresql_db) - self._populate_postgresql_db_table() + # --- PostgreSQL --- - self.settings.postgresql_dbs = self.temp_postgresql_dbs.copy() - self.settings.save() - self._refresh_main_window_projects_menu() + def _add_postgresql_db(self): + self._add_item( + PostgreSqlConfigDialog, self.temp_postgresql_dbs, "postgresql_dbs", + lambda id, d: PostgreSqlDb( + id=id, name=d["name"], host=d["host"], port=d["port"], + database=d["database"], username=d["username"], password=d["password"], + ), + self._populate_postgresql_db_table, + ) def _remove_postgresql_db(self): - """Entfernt die ausgewählte PostgreSQL-Datenbank.""" - current_row = self.ui.tablePostgreSqlDbs.currentRow() - if current_row >= 0: - del self.temp_postgresql_dbs[current_row] - self._populate_postgresql_db_table() - self._update_postgresql_db_buttons() - - self.settings.postgresql_dbs = self.temp_postgresql_dbs.copy() - self.settings.save() - self._refresh_main_window_projects_menu() + self._remove_item( + self.ui.tablePostgreSqlDbs, self.temp_postgresql_dbs, "postgresql_dbs", + self._update_postgresql_db_buttons, self._populate_postgresql_db_table, + ) def _update_postgresql_db_buttons(self): - """Aktualisiert den Status der PostgreSQL-Buttons.""" - has_selection = self.ui.tablePostgreSqlDbs.currentRow() >= 0 - self.ui.removePostgreSql.setEnabled(has_selection) + self._update_remove_button(self.ui.tablePostgreSqlDbs, self.ui.removePostgreSql) def _edit_postgresql_db(self, index): - """Bearbeitet eine PostgreSQL-Datenbank per Doppelklick.""" - row = index.row() - if 0 <= row < len(self.temp_postgresql_dbs): - postgresql_db = self.temp_postgresql_dbs[row] - dialog = PostgreSqlConfigDialog(self) + self._edit_item(index, self.temp_postgresql_dbs, PostgreSqlConfigDialog, + ["name", "host", "port", "database", "username", "password"], + self._populate_postgresql_db_table) - # Vorhandene Daten setzen - data = { - "name": postgresql_db.name, - "host": postgresql_db.host, - "port": postgresql_db.port, - "database": postgresql_db.database, - "username": postgresql_db.username, - "password": postgresql_db.password, - } - dialog.set_data(data) - - if dialog.exec() == QDialog.DialogCode.Accepted: - new_data = dialog.get_data() - if new_data: - # Daten aktualisieren - postgresql_db.name = new_data["name"] - postgresql_db.host = new_data["host"] - postgresql_db.port = new_data["port"] - postgresql_db.database = new_data["database"] - postgresql_db.username = new_data["username"] - postgresql_db.password = new_data["password"] - self._populate_postgresql_db_table() + # --- Dialog-Abschluss --- def accept(self): """Übernimmt die Änderungen und schließt den Dialog.""" - # Aktualisiere die ursprünglichen Einstellungen self.settings.java_vms = self.temp_java_vms.copy() self.settings.diff_pdfs = self.temp_diff_pdfs.copy() self.settings.saxon_jars = self.temp_saxon_jars.copy() @@ -782,21 +492,15 @@ class AppSettingsDlg(QDialog): self.settings.xsl_dirs = self.temp_xsl_dirs.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() - - # XSLT-Version übernehmen - if self.ui.comboBoxXsltVersion.currentIndex() == 0: - self.settings.saxon_xslt_version = XsltVersion.XSLT_1_0 - else: - self.settings.saxon_xslt_version = XsltVersion.XSLT_2_0_3_0 - + self.settings.saxon_xslt_version = ( + XsltVersion.XSLT_1_0 if self.ui.comboBoxXsltVersion.currentIndex() == 0 else XsltVersion.XSLT_2_0_3_0 + ) self.settings.use_fop_worker_pool = self.ui.checkBoxUseFopPool.isChecked() self.settings.save() self._refresh_main_window_projects_menu() - super().accept() def get_settings(self) -> AppSettings: