2026-03-21 16:54:21 +01:00
|
|
|
"""
|
|
|
|
|
Info-Dialog für DocuMentor.
|
|
|
|
|
|
|
|
|
|
Zeigt Programmversion, Python-Version und alle Drittanbieter-Bibliotheken
|
|
|
|
|
mit installierten Versionen und Lizenzinformationen an.
|
|
|
|
|
"""
|
|
|
|
|
import logging
|
|
|
|
|
import sys
|
|
|
|
|
from importlib.metadata import PackageNotFoundError, version
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
from PySide6.QtCore import Qt
|
|
|
|
|
from PySide6.QtGui import QFont
|
|
|
|
|
from PySide6.QtWidgets import (
|
|
|
|
|
QDialog,
|
|
|
|
|
QDialogButtonBox,
|
|
|
|
|
QFrame,
|
|
|
|
|
QHBoxLayout,
|
|
|
|
|
QHeaderView,
|
|
|
|
|
QLabel,
|
|
|
|
|
QTableWidget,
|
|
|
|
|
QTableWidgetItem,
|
|
|
|
|
QVBoxLayout,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
from license_parser import parse_license_file
|
|
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class AboutDialog(QDialog):
|
|
|
|
|
"""Info-Dialog mit Versionsinformationen und Drittanbieter-Lizenzen."""
|
|
|
|
|
|
|
|
|
|
def __init__(self, parent=None):
|
|
|
|
|
super().__init__(parent)
|
|
|
|
|
self.setWindowTitle("Über DocuMentor")
|
|
|
|
|
self.resize(950, 620)
|
|
|
|
|
self.setSizeGripEnabled(True)
|
|
|
|
|
self.setModal(True)
|
|
|
|
|
self._setup_ui()
|
|
|
|
|
self._populate_data()
|
|
|
|
|
|
|
|
|
|
def _get_app_version(self) -> str:
|
|
|
|
|
"""Ermittelt die Programmversion."""
|
|
|
|
|
try:
|
|
|
|
|
return version("DocuMentor")
|
|
|
|
|
except PackageNotFoundError:
|
|
|
|
|
# Fallback: pyproject.toml parsen (Entwicklungsmodus ohne Installation)
|
|
|
|
|
try:
|
|
|
|
|
import tomllib
|
|
|
|
|
|
|
|
|
|
pyproject = Path(__file__).parent.parent.parent / "pyproject.toml"
|
|
|
|
|
with open(pyproject, "rb") as f:
|
|
|
|
|
return tomllib.load(f)["project"]["version"]
|
|
|
|
|
except Exception:
|
|
|
|
|
return "unbekannt"
|
|
|
|
|
|
|
|
|
|
def _setup_ui(self):
|
|
|
|
|
"""Erstellt das Dialog-Layout programmatisch."""
|
|
|
|
|
layout = QVBoxLayout(self)
|
|
|
|
|
layout.setSpacing(8)
|
|
|
|
|
|
|
|
|
|
# App-Name
|
|
|
|
|
self.app_name_label = QLabel("DocuMentor")
|
|
|
|
|
font = QFont()
|
|
|
|
|
font.setPointSize(18)
|
|
|
|
|
font.setBold(True)
|
|
|
|
|
self.app_name_label.setFont(font)
|
|
|
|
|
self.app_name_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
|
|
|
|
layout.addWidget(self.app_name_label)
|
|
|
|
|
|
|
|
|
|
# Beschreibung
|
|
|
|
|
self.description_label = QLabel("Professionelle XSL-Transformations-Verwaltung und PDF-Generierung")
|
|
|
|
|
self.description_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
|
|
|
|
self.description_label.setWordWrap(True)
|
|
|
|
|
layout.addWidget(self.description_label)
|
|
|
|
|
|
|
|
|
|
# Version + Python-Version
|
|
|
|
|
self.version_label = QLabel()
|
|
|
|
|
self.version_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
|
|
|
|
layout.addWidget(self.version_label)
|
|
|
|
|
|
|
|
|
|
# Lizenz
|
|
|
|
|
self.license_label = QLabel("Lizenz: MIT")
|
|
|
|
|
self.license_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
|
|
|
|
layout.addWidget(self.license_label)
|
|
|
|
|
|
|
|
|
|
# Separator
|
|
|
|
|
separator = QFrame()
|
|
|
|
|
separator.setFrameShape(QFrame.Shape.HLine)
|
|
|
|
|
separator.setFrameShadow(QFrame.Shadow.Sunken)
|
|
|
|
|
layout.addWidget(separator)
|
|
|
|
|
|
|
|
|
|
# Überschrift für Tabelle
|
|
|
|
|
header_layout = QHBoxLayout()
|
|
|
|
|
table_header = QLabel("Drittanbieter-Bibliotheken:")
|
|
|
|
|
header_font = QFont()
|
|
|
|
|
header_font.setBold(True)
|
|
|
|
|
table_header.setFont(header_font)
|
|
|
|
|
header_layout.addWidget(table_header)
|
|
|
|
|
header_layout.addStretch()
|
|
|
|
|
layout.addLayout(header_layout)
|
|
|
|
|
|
|
|
|
|
# Dependency-Tabelle
|
|
|
|
|
self.table = QTableWidget()
|
|
|
|
|
self.table.setColumnCount(6)
|
|
|
|
|
self.table.setHorizontalHeaderLabels(["Name", "Lizenz", "Installiert", "Webseite", "Copyright", "Kategorie"])
|
|
|
|
|
self.table.setEditTriggers(QTableWidget.EditTrigger.NoEditTriggers)
|
|
|
|
|
self.table.setSelectionBehavior(QTableWidget.SelectionBehavior.SelectRows)
|
|
|
|
|
self.table.setAlternatingRowColors(True)
|
|
|
|
|
self.table.setSortingEnabled(True)
|
|
|
|
|
self.table.verticalHeader().setVisible(False)
|
|
|
|
|
|
|
|
|
|
# Spaltenbreiten
|
|
|
|
|
header = self.table.horizontalHeader()
|
|
|
|
|
header.resizeSection(0, 170) # Name
|
|
|
|
|
header.resizeSection(1, 180) # Lizenz
|
|
|
|
|
header.resizeSection(2, 80) # Installiert
|
2026-03-21 17:20:07 +01:00
|
|
|
header.resizeSection(5, 200) # Kategorie
|
2026-03-21 16:54:21 +01:00
|
|
|
header.setSectionResizeMode(3, QHeaderView.ResizeMode.Stretch) # Webseite
|
|
|
|
|
header.setSectionResizeMode(4, QHeaderView.ResizeMode.Stretch) # Copyright
|
|
|
|
|
|
|
|
|
|
layout.addWidget(self.table)
|
|
|
|
|
|
|
|
|
|
# Schließen-Button
|
|
|
|
|
button_box = QDialogButtonBox(QDialogButtonBox.StandardButton.Close)
|
|
|
|
|
button_box.rejected.connect(self.reject)
|
|
|
|
|
button_box.setCenterButtons(True)
|
|
|
|
|
layout.addWidget(button_box)
|
|
|
|
|
|
|
|
|
|
def _populate_data(self):
|
|
|
|
|
"""Befüllt den Dialog mit Versions- und Lizenzinformationen."""
|
|
|
|
|
# Version setzen
|
|
|
|
|
app_version = self._get_app_version()
|
|
|
|
|
python_version = f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
|
|
|
|
|
self.version_label.setText(f"Version: {app_version} | Python: {python_version}")
|
|
|
|
|
|
|
|
|
|
# Lizenzdaten laden und Tabelle befüllen
|
|
|
|
|
parsed = parse_license_file()
|
|
|
|
|
self.table.setRowCount(len(parsed.entries))
|
|
|
|
|
|
|
|
|
|
for row, entry in enumerate(parsed.entries):
|
|
|
|
|
self.table.setItem(row, 0, QTableWidgetItem(entry.name))
|
|
|
|
|
self.table.setItem(row, 1, QTableWidgetItem(entry.license))
|
|
|
|
|
self.table.setItem(row, 2, QTableWidgetItem(entry.installed_version or "—"))
|
|
|
|
|
self.table.setItem(row, 3, QTableWidgetItem(entry.website))
|
|
|
|
|
self.table.setItem(row, 4, QTableWidgetItem(entry.copyright))
|
|
|
|
|
self.table.setItem(row, 5, QTableWidgetItem(entry.category))
|