Die Drag&Drop-Funktionalität für XML-Dateien
This commit is contained in:
+256
-2
@@ -4,8 +4,8 @@ import time
|
||||
import polars as pl
|
||||
import shutil
|
||||
|
||||
from PySide6.QtCore import Qt, QSize
|
||||
from PySide6.QtGui import QCursor, QPixmap, QPainter, QAction, QIcon
|
||||
from PySide6.QtCore import Qt, QSize, QUrl
|
||||
from PySide6.QtGui import QCursor, QPixmap, QPainter, QAction, QIcon, QDragEnterEvent, QDropEvent
|
||||
from PySide6.QtWidgets import QLabel, QMainWindow, QApplication, QStyleFactory, QMenu, QTreeWidgetItem, QMessageBox, QFileDialog
|
||||
from PySide6.QtPdf import QPdfDocument
|
||||
|
||||
@@ -14,6 +14,7 @@ from ui.AppSettings import AppSettingsDlg
|
||||
from ui.PdfProject import PdfProjectDlg
|
||||
from ui.TreeNodeEditDialog import TreeNodeEditDialog
|
||||
from ui.XslFileEditDialog import XslFileEditDialog
|
||||
from ui.XmlToXslAssignDialog import XmlToXslAssignDialog
|
||||
from conf import app_settings, Project, ProjectData, TreeNode, XslFile, XmlFile
|
||||
from pathlib import Path
|
||||
|
||||
@@ -87,6 +88,9 @@ class MainWindow(QMainWindow):
|
||||
|
||||
# TreeWidget Styling für größeren vertikalen Abstand
|
||||
self._setup_tree_widget_styling()
|
||||
|
||||
# Drag&Drop für TreeWidget aktivieren
|
||||
self._setup_drag_drop()
|
||||
|
||||
def _setup_theme_menu(self):
|
||||
"""Initialisiert das Theme-Menü mit verfügbaren Themes."""
|
||||
@@ -1604,6 +1608,256 @@ class MainWindow(QMainWindow):
|
||||
print(f"Fehler beim Speichern der Projekt-Einstellungen: {e}")
|
||||
raise
|
||||
|
||||
def _setup_drag_drop(self):
|
||||
"""Aktiviert Drag&Drop für das TreeWidget."""
|
||||
try:
|
||||
# Aktiviere Drag&Drop für das TreeWidget
|
||||
self.ui.treeWidget.setAcceptDrops(True)
|
||||
self.ui.treeWidget.setDragDropMode(self.ui.treeWidget.DragDropMode.DropOnly)
|
||||
|
||||
# Überschreibe die Drag&Drop-Events
|
||||
self.ui.treeWidget.dragEnterEvent = self.tree_drag_enter_event
|
||||
self.ui.treeWidget.dragMoveEvent = self.tree_drag_move_event
|
||||
self.ui.treeWidget.dropEvent = self.tree_drop_event
|
||||
|
||||
print("Drag&Drop für TreeWidget aktiviert")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Fehler beim Aktivieren von Drag&Drop: {e}")
|
||||
|
||||
def tree_drag_enter_event(self, event: QDragEnterEvent):
|
||||
"""
|
||||
Wird ausgeführt, wenn ein Drag-Vorgang über das TreeWidget beginnt.
|
||||
|
||||
Args:
|
||||
event: Das Drag-Enter-Event
|
||||
"""
|
||||
try:
|
||||
# Prüfe ob URLs (Dateien) gedraggt werden
|
||||
if event.mimeData().hasUrls():
|
||||
urls = event.mimeData().urls()
|
||||
|
||||
# Prüfe ob mindestens eine XML-Datei dabei ist
|
||||
xml_files = [url.toLocalFile() for url in urls
|
||||
if url.toLocalFile().lower().endswith('.xml')]
|
||||
|
||||
if xml_files:
|
||||
event.acceptProposedAction()
|
||||
print(f"Drag-Enter akzeptiert: {len(xml_files)} XML-Dateien")
|
||||
else:
|
||||
event.ignore()
|
||||
print("Drag-Enter ignoriert: Keine XML-Dateien")
|
||||
else:
|
||||
event.ignore()
|
||||
print("Drag-Enter ignoriert: Keine URLs")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Fehler in tree_drag_enter_event: {e}")
|
||||
event.ignore()
|
||||
|
||||
def tree_drag_move_event(self, event):
|
||||
"""
|
||||
Wird ausgeführt, wenn ein Drag-Vorgang über das TreeWidget bewegt wird.
|
||||
|
||||
Args:
|
||||
event: Das Drag-Move-Event
|
||||
"""
|
||||
try:
|
||||
# Prüfe ob URLs (Dateien) gedraggt werden
|
||||
if event.mimeData().hasUrls():
|
||||
urls = event.mimeData().urls()
|
||||
|
||||
# Prüfe ob mindestens eine XML-Datei dabei ist
|
||||
xml_files = [url.toLocalFile() for url in urls
|
||||
if url.toLocalFile().lower().endswith('.xml')]
|
||||
|
||||
if xml_files:
|
||||
event.acceptProposedAction()
|
||||
else:
|
||||
event.ignore()
|
||||
else:
|
||||
event.ignore()
|
||||
|
||||
except Exception as e:
|
||||
print(f"Fehler in tree_drag_move_event: {e}")
|
||||
event.ignore()
|
||||
|
||||
def tree_drop_event(self, event: QDropEvent):
|
||||
"""
|
||||
Wird ausgeführt, wenn Dateien auf das TreeWidget gedroppt werden.
|
||||
|
||||
Args:
|
||||
event: Das Drop-Event
|
||||
"""
|
||||
try:
|
||||
# Prüfe ob ein Projekt geladen ist
|
||||
if not hasattr(self, 'project') or not self.project:
|
||||
QMessageBox.warning(self, "Warnung", "Kein Projekt geladen. Bitte öffnen Sie zuerst ein Projekt.")
|
||||
event.ignore()
|
||||
return
|
||||
|
||||
if not hasattr(self, 'pdf_project') or not self.pdf_project:
|
||||
QMessageBox.warning(self, "Warnung", "Keine Projekt-Einstellungen geladen.")
|
||||
event.ignore()
|
||||
return
|
||||
|
||||
# Hole die URLs aus dem Drop-Event
|
||||
if not event.mimeData().hasUrls():
|
||||
event.ignore()
|
||||
return
|
||||
|
||||
urls = event.mimeData().urls()
|
||||
xml_files = []
|
||||
|
||||
# Sammle alle XML-Dateien
|
||||
for url in urls:
|
||||
file_path = url.toLocalFile()
|
||||
if file_path.lower().endswith('.xml'):
|
||||
xml_files.append(Path(file_path))
|
||||
|
||||
if not xml_files:
|
||||
QMessageBox.information(self, "Information", "Keine XML-Dateien zum Hinzufügen gefunden.")
|
||||
event.ignore()
|
||||
return
|
||||
|
||||
print(f"Drop-Event: {len(xml_files)} XML-Dateien erkannt")
|
||||
|
||||
# Verarbeite jede XML-Datei einzeln
|
||||
for xml_file_path in xml_files:
|
||||
self._handle_xml_file_drop(xml_file_path)
|
||||
|
||||
event.acceptProposedAction()
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Fehler beim Verarbeiten des Drop-Events: {str(e)}"
|
||||
print(error_msg)
|
||||
QMessageBox.critical(self, "Fehler", error_msg)
|
||||
event.ignore()
|
||||
|
||||
def _handle_xml_file_drop(self, xml_file_path: Path):
|
||||
"""
|
||||
Verarbeitet eine einzelne XML-Datei, die per Drag&Drop hinzugefügt wurde.
|
||||
|
||||
Args:
|
||||
xml_file_path: Pfad zur XML-Datei
|
||||
"""
|
||||
try:
|
||||
print(f"Verarbeite XML-Datei: {xml_file_path}")
|
||||
|
||||
# Prüfe ob die Datei existiert
|
||||
if not xml_file_path.exists():
|
||||
QMessageBox.critical(self, "Fehler", f"Die XML-Datei existiert nicht:\n{xml_file_path}")
|
||||
return
|
||||
|
||||
# Öffne den Dialog zur Zuordnung zu XSL-Knoten
|
||||
dialog = XmlToXslAssignDialog(
|
||||
parent=self,
|
||||
xml_file_path=xml_file_path,
|
||||
project_nodes=self.pdf_project.nodes
|
||||
)
|
||||
|
||||
if dialog.exec() == XmlToXslAssignDialog.DialogCode.Accepted:
|
||||
# Hole die ausgewählten XSL-Knoten
|
||||
selected_xsl_nodes = dialog.get_selected_xsl_nodes()
|
||||
|
||||
if selected_xsl_nodes:
|
||||
# Verarbeite die Zuordnung
|
||||
self._assign_xml_to_xsl_nodes(xml_file_path, selected_xsl_nodes)
|
||||
else:
|
||||
print("Keine XSL-Knoten ausgewählt")
|
||||
else:
|
||||
print("Dialog abgebrochen")
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Fehler beim Verarbeiten der XML-Datei '{xml_file_path}': {str(e)}"
|
||||
print(error_msg)
|
||||
QMessageBox.critical(self, "Fehler", error_msg)
|
||||
|
||||
def _assign_xml_to_xsl_nodes(self, xml_file_path: Path, selected_xsl_nodes: list):
|
||||
"""
|
||||
Ordnet eine XML-Datei den ausgewählten XSL-Knoten zu.
|
||||
|
||||
Args:
|
||||
xml_file_path: Pfad zur XML-Datei
|
||||
selected_xsl_nodes: Liste der ausgewählten XSL-Knoten
|
||||
"""
|
||||
try:
|
||||
print(f"Ordne XML-Datei '{xml_file_path.name}' zu {len(selected_xsl_nodes)} XSL-Knoten zu")
|
||||
|
||||
# Erstelle xml-Ordner im Projekt-Verzeichnis falls er nicht existiert
|
||||
xml_dir = Path(self.project.project_dir) / "xml"
|
||||
xml_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Bestimme den Ziel-Pfad in xml-Ordner
|
||||
target_xml_path = xml_dir / xml_file_path.name
|
||||
|
||||
# Prüfe ob eine Datei mit gleichem Namen bereits existiert
|
||||
copy_file = True
|
||||
if target_xml_path.exists():
|
||||
reply = QMessageBox.question(
|
||||
self,
|
||||
"Datei existiert bereits",
|
||||
f"Eine XML-Datei mit dem Namen '{xml_file_path.name}' existiert bereits im xml-Ordner.\n\n"
|
||||
"Möchten Sie sie überschreiben?",
|
||||
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
|
||||
QMessageBox.StandardButton.No
|
||||
)
|
||||
|
||||
if reply != QMessageBox.StandardButton.Yes:
|
||||
copy_file = False
|
||||
|
||||
# Kopiere die XML-Datei in den xml-Ordner (falls gewünscht)
|
||||
if copy_file:
|
||||
shutil.copy2(xml_file_path, target_xml_path)
|
||||
print(f"XML-Datei kopiert: {xml_file_path} -> {target_xml_path}")
|
||||
|
||||
# Erstelle relatives Path zur XML-Datei (relativ zum xml-Ordner)
|
||||
relative_xml_path = Path("xml") / xml_file_path.name
|
||||
|
||||
# Füge die XML-Datei zu allen ausgewählten XSL-Knoten hinzu
|
||||
added_count = 0
|
||||
for xsl_node in selected_xsl_nodes:
|
||||
# Prüfe ob diese XML-Datei bereits in der XslFile-Node vorhanden ist
|
||||
existing_xml = None
|
||||
for xml_file in xsl_node.xmls:
|
||||
if xml_file.xml == relative_xml_path:
|
||||
existing_xml = xml_file
|
||||
break
|
||||
|
||||
if not existing_xml:
|
||||
# Erstelle neues XmlFile-Objekt und füge es zur XslFile-Node hinzu
|
||||
new_xml_file = XmlFile(xml=relative_xml_path)
|
||||
xsl_node.xmls.append(new_xml_file)
|
||||
added_count += 1
|
||||
print(f"XML-Datei '{xml_file_path.name}' zu XslFile-Node '{xsl_node.bez}' hinzugefügt")
|
||||
else:
|
||||
print(f"XML-Datei '{xml_file_path.name}' bereits in XslFile-Node '{xsl_node.bez}' vorhanden")
|
||||
|
||||
if added_count > 0:
|
||||
# Speichere die aktualisierten Projekt-Einstellungen
|
||||
self._save_project_settings()
|
||||
|
||||
# Aktualisiere das TreeWidget
|
||||
self._load_nodes_to_tree()
|
||||
|
||||
# Zeige Erfolgsmeldung
|
||||
QMessageBox.information(
|
||||
self,
|
||||
"Erfolg",
|
||||
f"XML-Datei '{xml_file_path.name}' wurde erfolgreich zu {added_count} XSL-Knoten hinzugefügt."
|
||||
)
|
||||
else:
|
||||
QMessageBox.information(
|
||||
self,
|
||||
"Information",
|
||||
f"XML-Datei '{xml_file_path.name}' war bereits in allen ausgewählten XSL-Knoten vorhanden."
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Fehler beim Zuordnen der XML-Datei: {str(e)}"
|
||||
print(error_msg)
|
||||
QMessageBox.critical(self, "Fehler", error_msg)
|
||||
|
||||
def closeEvent(self, event):
|
||||
"""Wird beim Schließen der Anwendung aufgerufen."""
|
||||
# PDF-Dokumente schließen ist bei QtPdf automatisch durch Garbage Collection
|
||||
|
||||
Reference in New Issue
Block a user