2025-06-16 20:30:56 +02:00
|
|
|
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):
|
2025-06-17 20:12:38 +02:00
|
|
|
def __init__(self, parent=None, project_data=None, edit_mode=False):
|
2025-06-16 20:30:56 +02:00
|
|
|
"""
|
|
|
|
|
Konstruktor für den PDF-Projekt-Dialog.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
parent: Übergeordnetes Widget
|
|
|
|
|
project_data: Bestehende Projektdaten zum Bearbeiten (optional)
|
2026-02-12 20:53:00 +01:00
|
|
|
edit_mode: Wenn True, wird der Projekt-Ordner deaktiviert (nur Name und Einstellungen ändern)
|
2025-06-16 20:30:56 +02:00
|
|
|
"""
|
|
|
|
|
super().__init__(parent)
|
|
|
|
|
|
|
|
|
|
# UI einrichten
|
|
|
|
|
self.ui = Ui_projectDlg()
|
|
|
|
|
self.ui.setupUi(self)
|
|
|
|
|
|
|
|
|
|
# Projektdaten speichern
|
|
|
|
|
self.project_data = project_data or {}
|
2025-06-17 20:12:38 +02:00
|
|
|
self.edit_mode = edit_mode
|
2025-06-16 20:30:56 +02:00
|
|
|
|
|
|
|
|
# Dialog-Eigenschaften setzen
|
|
|
|
|
self.setModal(True)
|
|
|
|
|
self.setWindowFlags(self.windowFlags() & ~Qt.WindowType.WindowContextHelpButtonHint)
|
|
|
|
|
|
|
|
|
|
# Signale verbinden
|
|
|
|
|
self._connect_signals()
|
|
|
|
|
|
|
|
|
|
# ComboBoxen initialisieren
|
|
|
|
|
self._init_combo_boxes()
|
|
|
|
|
|
2025-06-17 20:12:38 +02:00
|
|
|
# Edit-Modus konfigurieren
|
|
|
|
|
if self.edit_mode:
|
|
|
|
|
self._configure_edit_mode()
|
|
|
|
|
|
2025-06-16 20:30:56 +02:00
|
|
|
# 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)
|
2025-12-26 12:45:44 +01:00
|
|
|
|
|
|
|
|
# Browse-Button für FOP-Config-Ordner
|
|
|
|
|
self.ui.btnBrowseFopConfig.clicked.connect(self.browse_fop_config_dir)
|
|
|
|
|
|
2025-06-16 20:30:56 +02:00
|
|
|
# OK/Cancel Buttons sind bereits in der UI-Datei verbunden
|
|
|
|
|
# self.ui.buttonBox.accepted.connect(self.accept)
|
|
|
|
|
# self.ui.buttonBox.rejected.connect(self.reject)
|
2025-12-26 12:45:44 +01:00
|
|
|
|
2025-06-16 20:30:56 +02:00
|
|
|
# Ü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:
|
2025-07-14 21:00:06 +02:00
|
|
|
self.ui.cB_JavaVm.addItem(java_vm.version, java_vm.id)
|
2025-06-16 20:30:56 +02:00
|
|
|
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:
|
2025-07-14 21:00:06 +02:00
|
|
|
self.ui.cB_SaxonJar.addItem(saxon_jar.version, saxon_jar.id)
|
2025-06-16 20:30:56 +02:00
|
|
|
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:
|
2025-07-14 21:00:06 +02:00
|
|
|
self.ui.cB_ApacheFop.addItem(apache_fop.version, apache_fop.id)
|
2025-06-16 20:30:56 +02:00
|
|
|
if not app_settings.apache_fops:
|
|
|
|
|
self.ui.cB_ApacheFop.addItem("Keine Apache FOP-Instanzen konfiguriert", -1)
|
|
|
|
|
|
|
|
|
|
# diff-pdf ComboBox
|
2025-07-14 21:00:06 +02:00
|
|
|
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)
|
2025-06-16 20:30:56 +02:00
|
|
|
if not app_settings.diff_pdfs:
|
2025-07-14 21:00:06 +02:00
|
|
|
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)
|
2025-06-16 20:30:56 +02:00
|
|
|
|
|
|
|
|
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:
|
2025-07-14 21:00:06 +02:00
|
|
|
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'])
|
2025-12-26 12:45:44 +01:00
|
|
|
|
|
|
|
|
# FOP-Config-Ordner
|
|
|
|
|
if 'fop_config_dir' in self.project_data and self.project_data['fop_config_dir']:
|
|
|
|
|
self.ui.lineFopConfigDir.setText(str(self.project_data['fop_config_dir']))
|
2025-06-16 20:30:56 +02:00
|
|
|
|
|
|
|
|
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)
|
2025-12-26 12:45:44 +01:00
|
|
|
|
|
|
|
|
def browse_fop_config_dir(self):
|
|
|
|
|
"""Öffnet einen Dialog zum Auswählen des FOP-Config-Ordners."""
|
|
|
|
|
current_dir = self.ui.lineFopConfigDir.text()
|
|
|
|
|
if not current_dir or not os.path.exists(current_dir):
|
|
|
|
|
current_dir = os.path.expanduser("~")
|
|
|
|
|
|
|
|
|
|
selected_dir = QFileDialog.getExistingDirectory(
|
|
|
|
|
self,
|
|
|
|
|
"FOP-Config-Ordner auswählen",
|
|
|
|
|
current_dir,
|
|
|
|
|
QFileDialog.Option.ShowDirsOnly | QFileDialog.Option.DontResolveSymlinks
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if selected_dir:
|
|
|
|
|
self.ui.lineFopConfigDir.setText(selected_dir)
|
|
|
|
|
|
2025-06-16 20:30:56 +02:00
|
|
|
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
|
|
|
|
|
|
2025-07-14 21:00:06 +02:00
|
|
|
|
2025-06-16 20:30:56 +02:00
|
|
|
# Alle Validierungen bestanden
|
|
|
|
|
self.accept()
|
|
|
|
|
|
|
|
|
|
def get_project_data(self):
|
|
|
|
|
"""
|
|
|
|
|
Gibt die eingegebenen Projektdaten zurück.
|
2025-12-26 12:45:44 +01:00
|
|
|
|
2025-06-16 20:30:56 +02:00
|
|
|
Returns:
|
|
|
|
|
dict: Dictionary mit allen Projektdaten
|
|
|
|
|
"""
|
2025-12-26 12:45:44 +01:00
|
|
|
fop_config_dir = self.ui.lineFopConfigDir.text().strip()
|
2025-06-16 20:30:56 +02:00
|
|
|
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(),
|
2025-07-14 21:00:06 +02:00
|
|
|
'diff_pdf_id': self.ui.cB_Diff_Pdf.currentData(),
|
2025-12-26 12:45:44 +01:00
|
|
|
'postgre_sql_db_id': self.ui.cB_Postgres.currentData(),
|
|
|
|
|
'fop_config_dir': fop_config_dir if fop_config_dir else None
|
2025-06-16 20:30:56 +02:00
|
|
|
}
|
|
|
|
|
|
2025-06-17 20:12:38 +02:00
|
|
|
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")
|
|
|
|
|
|
2025-06-16 20:30:56 +02:00
|
|
|
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()
|
|
|
|
|
|