import os from PySide6.QtCore import Qt from PySide6.QtWidgets import QDialog, QFileDialog, QMessageBox from conf import app_settings from ui.PdfProject_ui import Ui_projectDlg class PdfProjectDlg(QDialog): def __init__(self, parent=None, project_data=None, edit_mode=False): """ Konstruktor für den PDF-Projekt-Dialog. Args: parent: Übergeordnetes Widget project_data: Bestehende Projektdaten zum Bearbeiten (optional) edit_mode: Wenn True, werden Projekt-Name und -Ordner deaktiviert (nur Einstellungen ändern) """ super().__init__(parent) # UI einrichten self.ui = Ui_projectDlg() self.ui.setupUi(self) # Projektdaten speichern self.project_data = project_data or {} self.edit_mode = edit_mode # Dialog-Eigenschaften setzen self.setModal(True) self.setWindowFlags(self.windowFlags() & ~Qt.WindowType.WindowContextHelpButtonHint) # Signale verbinden self._connect_signals() # ComboBoxen initialisieren self._init_combo_boxes() # Edit-Modus konfigurieren if self.edit_mode: self._configure_edit_mode() # Bestehende Projektdaten laden, falls vorhanden if self.project_data: self._load_project_data() def _connect_signals(self): """Verbindet die Signale mit den entsprechenden Slots.""" # Browse-Button für Projekt-Ordner self.ui.pushButton.clicked.connect(self.browse_project_dir) # OK/Cancel Buttons sind bereits in der UI-Datei verbunden # self.ui.buttonBox.accepted.connect(self.accept) # self.ui.buttonBox.rejected.connect(self.reject) # Überschreibe accept() für Validierung self.ui.buttonBox.accepted.disconnect() self.ui.buttonBox.accepted.connect(self.validate_and_accept) def _init_combo_boxes(self): """Initialisiert die ComboBoxen mit Werten aus app_settings.""" # XSL-Ordner ComboBox self.ui.cB_XslDir.clear() for xsl_dir in app_settings.xsl_dirs: self.ui.cB_XslDir.addItem(xsl_dir.name, xsl_dir.id) if not app_settings.xsl_dirs: self.ui.cB_XslDir.addItem("Keine XSL-Ordner konfiguriert", -1) # Java VM ComboBox self.ui.cB_JavaVm.clear() for java_vm in app_settings.java_vms: self.ui.cB_JavaVm.addItem(java_vm.version, java_vm.id) if not app_settings.java_vms: self.ui.cB_JavaVm.addItem("Keine Java VMs konfiguriert", -1) # Saxon Jar ComboBox self.ui.cB_SaxonJar.clear() for saxon_jar in app_settings.saxon_jars: self.ui.cB_SaxonJar.addItem(saxon_jar.version, saxon_jar.id) if not app_settings.saxon_jars: self.ui.cB_SaxonJar.addItem("Keine Saxon JARs konfiguriert", -1) # Apache FOP ComboBox self.ui.cB_ApacheFop.clear() for apache_fop in app_settings.apache_fops: self.ui.cB_ApacheFop.addItem(apache_fop.version, apache_fop.id) if not app_settings.apache_fops: self.ui.cB_ApacheFop.addItem("Keine Apache FOP-Instanzen konfiguriert", -1) # diff-pdf ComboBox self.ui.cB_Diff_Pdf.clear() for postgres_db in app_settings.diff_pdfs: self.ui.cB_Diff_Pdf.addItem(postgres_db.version, postgres_db.id) if not app_settings.diff_pdfs: self.ui.cB_Diff_Pdf.addItem("Keine diff-pdf-Instanzen konfiguriert", -1) # Postgres ComboBox self.ui.cB_Postgres.clear() for postgres_db in app_settings.postgresql_dbs: self.ui.cB_Postgres.addItem(postgres_db.name, postgres_db.id) if not app_settings.postgresql_dbs: self.ui.cB_Postgres.addItem("Keine Postgres-Datenbanken konfiguriert", -1) def _load_project_data(self): """Lädt bestehende Projektdaten in die Eingabefelder.""" # Projekt-Name if 'name' in self.project_data: self.ui.lineProjectName.setText(self.project_data['name']) # Projekt-Ordner if 'project_dir' in self.project_data: self.ui.lineProjectDir.setText(str(self.project_data['project_dir'])) elif 'directory' in self.project_data: self.ui.lineProjectDir.setText(self.project_data['directory']) # ComboBox-Werte basierend auf IDs if 'xsl_dir_id' in self.project_data: self._select_combo_by_data(self.ui.cB_XslDir, self.project_data['xsl_dir_id']) if 'java_vm_id' in self.project_data: self._select_combo_by_data(self.ui.cB_JavaVm, self.project_data['java_vm_id']) if 'saxon_jar_id' in self.project_data: self._select_combo_by_data(self.ui.cB_SaxonJar, self.project_data['saxon_jar_id']) if 'apache_fop_id' in self.project_data: self._select_combo_by_data(self.ui.cB_ApacheFop, self.project_data['apache_fop_id']) if 'diff_pdf_id' in self.project_data: self._select_combo_by_data(self.ui.cB_Diff_Pdf, self.project_data['diff_pdf_id']) if 'postgre_sql_db_id' in self.project_data: self._select_combo_by_data(self.ui.cB_Postgres, self.project_data['postgre_sql_db_id']) def _select_combo_by_data(self, combo_box, data_value): """ Wählt einen ComboBox-Eintrag basierend auf dem data-Wert aus. Args: combo_box: Die ComboBox data_value: Der zu suchende data-Wert """ for i in range(combo_box.count()): if combo_box.itemData(i) == data_value: combo_box.setCurrentIndex(i) break def browse_project_dir(self): """Öffnet einen Dialog zum Auswählen des Projekt-Ordners.""" current_dir = self.ui.lineProjectDir.text() if not current_dir or not os.path.exists(current_dir): current_dir = os.path.expanduser("~") selected_dir = QFileDialog.getExistingDirectory( self, "Projekt-Ordner auswählen", current_dir, QFileDialog.Option.ShowDirsOnly | QFileDialog.Option.DontResolveSymlinks ) if selected_dir: self.ui.lineProjectDir.setText(selected_dir) # Automatisch Projekt-Name generieren, wenn leer if not self.ui.lineProjectName.text(): project_name = os.path.basename(selected_dir) self.ui.lineProjectName.setText(project_name) def validate_and_accept(self): """Validiert die Eingaben und akzeptiert den Dialog.""" # Projekt-Name prüfen project_name = self.ui.lineProjectName.text().strip() if not project_name: QMessageBox.warning( self, "Ungültige Eingabe", "Bitte geben Sie einen Projekt-Namen ein." ) self.ui.lineProjectName.setFocus() return # Projekt-Ordner prüfen project_dir = self.ui.lineProjectDir.text().strip() if not project_dir: QMessageBox.warning( self, "Ungültige Eingabe", "Bitte wählen Sie einen Projekt-Ordner aus." ) self.ui.pushButton.setFocus() return # Prüfen, ob der Ordner existiert if not os.path.exists(project_dir): reply = QMessageBox.question( self, "Ordner nicht gefunden", f"Der Ordner '{project_dir}' existiert nicht.\n" "Möchten Sie ihn erstellen?", QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, QMessageBox.StandardButton.No ) if reply == QMessageBox.StandardButton.Yes: try: os.makedirs(project_dir, exist_ok=True) except OSError as e: QMessageBox.critical( self, "Fehler", f"Der Ordner konnte nicht erstellt werden:\n{str(e)}" ) return else: return # Prüfen, ob der Ordner beschreibbar ist if not os.access(project_dir, os.W_OK): QMessageBox.warning( self, "Ungültiger Ordner", f"Der Ordner '{project_dir}' ist nicht beschreibbar.\n" "Bitte wählen Sie einen anderen Ordner aus." ) return # Alle Validierungen bestanden self.accept() def get_project_data(self): """ Gibt die eingegebenen Projektdaten zurück. Returns: dict: Dictionary mit allen Projektdaten """ return { 'name': self.ui.lineProjectName.text().strip(), 'project_dir': self.ui.lineProjectDir.text().strip(), 'xsl_dir_id': self.ui.cB_XslDir.currentData(), 'java_vm_id': self.ui.cB_JavaVm.currentData(), 'saxon_jar_id': self.ui.cB_SaxonJar.currentData(), 'apache_fop_id': self.ui.cB_ApacheFop.currentData(), 'diff_pdf_id': self.ui.cB_Diff_Pdf.currentData(), 'postgre_sql_db_id': self.ui.cB_Postgres.currentData() } def _configure_edit_mode(self): """Konfiguriert den Dialog für den Edit-Modus (nur Einstellungen ändern).""" # Projekt-Ordner und Browse-Button deaktivieren self.ui.lineProjectDir.setEnabled(False) self.ui.pushButton.setEnabled(False) # Dialog-Titel ändern self.setWindowTitle("Projekt-Einstellungen bearbeiten") def set_project_data(self, project_data): """ Setzt die Projektdaten in den Dialog. Args: project_data: Dictionary mit Projektdaten """ self.project_data = project_data self._load_project_data() # Convenience-Funktionen für einfache Verwendung def create_project_dialog(parent=None): """ Erstellt einen neuen Projekt-Dialog für ein neues Projekt. Args: parent: Übergeordnetes Widget Returns: PdfProjectDlg: Der Dialog """ return PdfProjectDlg(parent) def edit_project_dialog(parent=None, project_data=None): """ Erstellt einen Projekt-Dialog zum Bearbeiten eines bestehenden Projekts. Args: parent: Übergeordnetes Widget project_data: Bestehende Projektdaten Returns: PdfProjectDlg: Der Dialog """ return PdfProjectDlg(parent, project_data) def show_project_dialog(parent=None, project_data=None): """ Zeigt einen Projekt-Dialog an und gibt die Ergebnisse zurück. Args: parent: Übergeordnetes Widget project_data: Bestehende Projektdaten (optional) Returns: tuple: (accepted: bool, project_data: dict) """ dialog = PdfProjectDlg(parent, project_data) result = dialog.exec() if result == QDialog.DialogCode.Accepted: return True, dialog.get_project_data() else: return False, None