Version 1.7.0: Feather Icons via Qt-Ressourcensystem eingebunden

Alle QIcon.fromTheme()-Aufrufe durch eingebettete Feather Icons ersetzt,
die unter Windows zuverlässig funktionieren. Icons passen sich automatisch
der Palette-Farbe des aktiven Themes an (QSvgRenderer + currentColor).

- scripts/download_icons.py: lädt 20 Feather-SVGs von GitHub
- src/res/icons/: 20 SVG-Dateien (MIT-Lizenz, stroke=currentColor)
- src/res/resources.qrc + resources_rc.py: Qt-Ressourcensystem
- src/icons.py: icon()-Hilfsfunktion mit Palette-Farb-Injection
- MainWindow, AppSettings, XslDependencyDialog, tree_manager,
  XsltParamsEditDialog, ProjectXsltParamsDialog: Icons gesetzt
- Theme-Wechsel aktualisiert Icons und Tree-Items sofort
- THIRD_PARTY_LICENSES.txt: Feather Icons (MIT) eingetragen

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-30 16:13:22 +02:00
parent bf2db92040
commit ec753a5770
36 changed files with 916 additions and 56 deletions
+1 -1
View File
@@ -4,7 +4,7 @@
<!-- Paket-Definition (ersetzt Product in v4) --> <!-- Paket-Definition (ersetzt Product in v4) -->
<Package <Package
Name="DocuMentor" Name="DocuMentor"
Version="1.6.6" Version="1.7.0"
Manufacturer="Vitali Graf / Software- und Datenbankentwicklung" Manufacturer="Vitali Graf / Software- und Datenbankentwicklung"
UpgradeCode="F498B66C-726D-44AA-95F4-CB4FBDCEF26E" UpgradeCode="F498B66C-726D-44AA-95F4-CB4FBDCEF26E"
Language="1031" Language="1031"
+11 -1
View File
@@ -115,6 +115,16 @@ Diese Bibliotheken sind direkt im Quellcode von DocuMentor enthalten.
Datei: src/res/vis-network.min.js Datei: src/res/vis-network.min.js
Hinweis: Wird inline in QWebEngineView für den XSL-Abhängigkeitsgraph verwendet Hinweis: Wird inline in QWebEngineView für den XSL-Abhängigkeitsgraph verwendet
2. Feather Icons
Version: 4.29.2
Lizenz: MIT License
Webseite: https://feathericons.com
GitHub: https://github.com/feathericons/feather
Beschreibung: Simply beautiful open source icons
Copyright: Copyright (c) 2013-2017 Cole Bemis
Datei: src/res/icons/, src/res/resources_rc.py
Hinweis: SVG-Icons werden via Qt-Ressourcensystem eingebettet; Farbe wird zur Laufzeit aus der Qt-Palette gesetzt
================================================================================ ================================================================================
Externe Tools (nicht eingebettet) Externe Tools (nicht eingebettet)
================================================================================ ================================================================================
@@ -253,5 +263,5 @@ HINWEISE
================================================================================ ================================================================================
Stand: April 2026 Stand: April 2026
Erstellt für: DocuMentor v1.6.6 Erstellt für: DocuMentor v1.7.0
================================================================================ ================================================================================
+1 -1
View File
@@ -10,7 +10,7 @@
; Build-Befehl: iscc installer.iss ; Build-Befehl: iscc installer.iss
#define MyAppName "DocuMentor" #define MyAppName "DocuMentor"
#define MyAppVersion "1.6.6" #define MyAppVersion "1.7.0"
#define MyAppPublisher "Ihr Name/Organisation" #define MyAppPublisher "Ihr Name/Organisation"
#define MyAppURL "https://github.com/yourusername/xsl-validator" #define MyAppURL "https://github.com/yourusername/xsl-validator"
#define MyAppExeName "DocuMentor.exe" #define MyAppExeName "DocuMentor.exe"
+1 -1
View File
@@ -1,6 +1,6 @@
[project] [project]
name = "DocuMentor" name = "DocuMentor"
version = "1.6.6" version = "1.7.0"
description = "Professionelle XSL-Transformations-Verwaltung und PDF-Generierung" description = "Professionelle XSL-Transformations-Verwaltung und PDF-Generierung"
readme = "README.md" readme = "README.md"
license = {text = "MIT"} license = {text = "MIT"}
+76
View File
@@ -0,0 +1,76 @@
"""
Lädt Feather Icons (MIT-Lizenz) von GitHub herunter und speichert sie in src/res/icons/.
Stroke-Farbe wird auf #444444 gesetzt für bessere Sichtbarkeit in hellen und dunklen Themes.
Ausführung: uv run python scripts/download_icons.py
"""
import urllib.request
from pathlib import Path
ICONS = [
"folder-plus",
"log-out",
"settings",
"folder",
"refresh-cw",
"plus-circle",
"minus-circle",
"play-circle",
"file",
"check-circle",
"info",
"git-branch",
"file-text",
"code",
"chevron-down",
"chevron-up",
"trash-2",
"file-plus",
"columns",
"sliders",
"folder-open",
]
BASE_URL = "https://raw.githubusercontent.com/feathericons/feather/master/icons/{name}.svg"
OUTPUT_DIR = Path(__file__).parent.parent / "src" / "res" / "icons"
def download_icons():
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
success = 0
failed = []
for name in ICONS:
url = BASE_URL.format(name=name)
dest = OUTPUT_DIR / f"{name}.svg"
if dest.exists():
print(f" [OK] {name}.svg (bereits vorhanden)")
success += 1
continue
try:
with urllib.request.urlopen(url, timeout=10) as response:
content = response.read().decode("utf-8")
content = content.replace('stroke="#000000"', 'stroke="#444444"')
content = content.replace("stroke='#000000'", "stroke='#444444'")
dest.write_text(content, encoding="utf-8")
print(f" [OK] {name}.svg")
success += 1
except Exception as e:
print(f" [FEHLER] {name}.svg: {e}")
failed.append(name)
print(f"\n{success}/{len(ICONS)} Icons heruntergeladen nach {OUTPUT_DIR}")
if failed:
print(f"Fehlgeschlagen: {', '.join(failed)}")
if __name__ == "__main__":
print(f"Lade {len(ICONS)} Feather Icons herunter ...")
download_icons()
+72
View File
@@ -0,0 +1,72 @@
import logging
from PySide6.QtCore import QByteArray, QFile, Qt
from PySide6.QtGui import QIcon, QPainter, QPixmap, QPalette
from PySide6.QtSvg import QSvgRenderer
from PySide6.QtWidgets import QApplication
logger = logging.getLogger(__name__)
_ICON_MAP: dict[str, str] = {
"folder-plus": ":/icons/folder-plus.svg",
"log-out": ":/icons/log-out.svg",
"settings": ":/icons/settings.svg",
"folder": ":/icons/folder.svg",
"refresh-cw": ":/icons/refresh-cw.svg",
"plus-circle": ":/icons/plus-circle.svg",
"minus-circle": ":/icons/minus-circle.svg",
"play-circle": ":/icons/play-circle.svg",
"file": ":/icons/file.svg",
"check-circle": ":/icons/check-circle.svg",
"info": ":/icons/info.svg",
"git-branch": ":/icons/git-branch.svg",
"file-text": ":/icons/file-text.svg",
"code": ":/icons/code.svg",
"chevron-down": ":/icons/chevron-down.svg",
"chevron-up": ":/icons/chevron-up.svg",
"trash-2": ":/icons/trash-2.svg",
"file-plus": ":/icons/file-plus.svg",
"columns": ":/icons/columns.svg",
"sliders": ":/icons/sliders.svg",
}
def icon(name: str) -> QIcon:
"""
Lädt ein Icon aus dem Qt-Ressource-System und färbt es mit der aktuellen Palette-Farbe.
Args:
name: Feather-Icon-Name (z.B. "folder-plus", "settings")
Returns:
QIcon in der Textfarbe des aktiven Themes, oder leerer QIcon bei unbekanntem Namen
"""
path = _ICON_MAP.get(name)
if path is None:
logger.warning(f"Unbekannter Icon-Name: {name!r}")
return QIcon()
app = QApplication.instance()
if app is None:
return QIcon(path)
color = app.palette().color(QPalette.ColorRole.WindowText).name().encode()
f = QFile(path)
if not f.open(QFile.OpenModeFlag.ReadOnly):
logger.warning(f"Icon konnte nicht geöffnet werden: {path}")
return QIcon(path)
svg_data = QByteArray(bytes(f.readAll()).replace(b"currentColor", color))
f.close()
renderer = QSvgRenderer(svg_data)
result = QIcon()
for size in (16, 24, 32):
pixmap = QPixmap(size, size)
pixmap.fill(Qt.GlobalColor.transparent)
painter = QPainter(pixmap)
renderer.render(painter)
painter.end()
result.addPixmap(pixmap)
return result
+3
View File
@@ -98,6 +98,9 @@ def main():
if icon_path.exists(): if icon_path.exists():
app.setWindowIcon(QIcon(str(icon_path))) app.setWindowIcon(QIcon(str(icon_path)))
# Qt-Ressourcen registrieren (Icons)
import res.resources_rc # noqa: F401
# Hauptfenster erstellen # Hauptfenster erstellen
window = MainWindow() window = MainWindow()
+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>

After

Width:  |  Height:  |  Size: 275 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>

After

Width:  |  Height:  |  Size: 222 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="18 15 12 9 6 15"/></svg>

After

Width:  |  Height:  |  Size: 223 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg>

After

Width:  |  Height:  |  Size: 258 B

+1
View File
@@ -0,0 +1 @@
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3h7a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-7m0-18H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h7m0-18v18"/></svg>

After

Width:  |  Height:  |  Size: 288 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="12" y1="18" x2="12" y2="12"/><line x1="9" y1="15" x2="15" y2="15"/></svg>

After

Width:  |  Height:  |  Size: 369 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><polyline points="10 9 9 9 8 9"/></svg>

After

Width:  |  Height:  |  Size: 401 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"/><polyline points="13 2 13 9 20 9"/></svg>

After

Width:  |  Height:  |  Size: 292 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/><line x1="12" y1="11" x2="12" y2="17"/><line x1="9" y1="14" x2="15" y2="14"/></svg>

After

Width:  |  Height:  |  Size: 351 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>

After

Width:  |  Height:  |  Size: 274 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="6" y1="3" x2="6" y2="15"/><circle cx="18" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M18 9a9 9 0 0 1-9 9"/></svg>

After

Width:  |  Height:  |  Size: 314 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg>

After

Width:  |  Height:  |  Size: 298 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></svg>

After

Width:  |  Height:  |  Size: 313 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="8" y1="12" x2="16" y2="12"/></svg>

After

Width:  |  Height:  |  Size: 257 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><polygon points="10 8 16 12 10 16 10 8"/></svg>

After

Width:  |  Height:  |  Size: 260 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="16"/><line x1="8" y1="12" x2="16" y2="12"/></svg>

After

Width:  |  Height:  |  Size: 295 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="23 4 23 10 17 10"/><polyline points="1 20 1 14 7 14"/><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/></svg>

After

Width:  |  Height:  |  Size: 339 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>

After

Width:  |  Height:  |  Size: 964 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="4" y1="21" x2="4" y2="14"/><line x1="4" y1="10" x2="4" y2="3"/><line x1="12" y1="21" x2="12" y2="12"/><line x1="12" y1="8" x2="12" y2="3"/><line x1="20" y1="21" x2="20" y2="16"/><line x1="20" y1="12" x2="20" y2="3"/><line x1="1" y1="14" x2="7" y2="14"/><line x1="9" y1="8" x2="15" y2="8"/><line x1="17" y1="16" x2="23" y2="16"/></svg>

After

Width:  |  Height:  |  Size: 525 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><line x1="10" y1="11" x2="10" y2="17"/><line x1="14" y1="11" x2="14" y2="17"/></svg>

After

Width:  |  Height:  |  Size: 388 B

+25
View File
@@ -0,0 +1,25 @@
<!DOCTYPE RCC>
<RCC version="1.0">
<qresource prefix="/">
<file>icons/folder-plus.svg</file>
<file>icons/log-out.svg</file>
<file>icons/settings.svg</file>
<file>icons/folder.svg</file>
<file>icons/refresh-cw.svg</file>
<file>icons/plus-circle.svg</file>
<file>icons/minus-circle.svg</file>
<file>icons/play-circle.svg</file>
<file>icons/file.svg</file>
<file>icons/check-circle.svg</file>
<file>icons/info.svg</file>
<file>icons/git-branch.svg</file>
<file>icons/file-text.svg</file>
<file>icons/code.svg</file>
<file>icons/chevron-down.svg</file>
<file>icons/chevron-up.svg</file>
<file>icons/trash-2.svg</file>
<file>icons/file-plus.svg</file>
<file>icons/columns.svg</file>
<file>icons/sliders.svg</file>
</qresource>
</RCC>
+634
View File
@@ -0,0 +1,634 @@
# Resource object code (Python 3)
# Created by: object code
# Created by: The Resource Compiler for Qt version 6.11.1
# WARNING! All changes made in this file will be lost!
from PySide6 import QtCore
qt_resource_data = b"\
\x00\x00\x01\x01\
<\
svg xmlns=\x22http:\
//www.w3.org/200\
0/svg\x22 width=\x2224\
\x22 height=\x2224\x22 vi\
ewBox=\x220 0 24 24\
\x22 fill=\x22none\x22 st\
roke=\x22currentCol\
or\x22 stroke-width\
=\x222\x22 stroke-line\
cap=\x22round\x22 stro\
ke-linejoin=\x22rou\
nd\x22><circle cx=\x22\
12\x22 cy=\x2212\x22 r=\x221\
0\x22/><line x1=\x228\x22\
y1=\x2212\x22 x2=\x2216\x22\
y2=\x2212\x22/></svg>\
\
\x00\x00\x02\x0d\
<\
svg xmlns=\x22http:\
//www.w3.org/200\
0/svg\x22 width=\x2224\
\x22 height=\x2224\x22 vi\
ewBox=\x220 0 24 24\
\x22 fill=\x22none\x22 st\
roke=\x22currentCol\
or\x22 stroke-width\
=\x222\x22 stroke-line\
cap=\x22round\x22 stro\
ke-linejoin=\x22rou\
nd\x22><line x1=\x224\x22\
y1=\x2221\x22 x2=\x224\x22 \
y2=\x2214\x22/><line x\
1=\x224\x22 y1=\x2210\x22 x2\
=\x224\x22 y2=\x223\x22/><li\
ne x1=\x2212\x22 y1=\x222\
1\x22 x2=\x2212\x22 y2=\x221\
2\x22/><line x1=\x2212\
\x22 y1=\x228\x22 x2=\x2212\x22\
y2=\x223\x22/><line x\
1=\x2220\x22 y1=\x2221\x22 x\
2=\x2220\x22 y2=\x2216\x22/>\
<line x1=\x2220\x22 y1\
=\x2212\x22 x2=\x2220\x22 y2\
=\x223\x22/><line x1=\x22\
1\x22 y1=\x2214\x22 x2=\x227\
\x22 y2=\x2214\x22/><line\
x1=\x229\x22 y1=\x228\x22 x\
2=\x2215\x22 y2=\x228\x22/><\
line x1=\x2217\x22 y1=\
\x2216\x22 x2=\x2223\x22 y2=\
\x2216\x22/></svg>\
\x00\x00\x01\x04\
<\
svg xmlns=\x22http:\
//www.w3.org/200\
0/svg\x22 width=\x2224\
\x22 height=\x2224\x22 vi\
ewBox=\x220 0 24 24\
\x22 fill=\x22none\x22 st\
roke=\x22currentCol\
or\x22 stroke-width\
=\x222\x22 stroke-line\
cap=\x22round\x22 stro\
ke-linejoin=\x22rou\
nd\x22><circle cx=\x22\
12\x22 cy=\x2212\x22 r=\x221\
0\x22/><polygon poi\
nts=\x2210 8 16 12 \
10 16 10 8\x22/></s\
vg>\
\x00\x00\x01 \
<\
svg width=\x2224\x22 h\
eight=\x2224\x22 viewB\
ox=\x220 0 24 24\x22 x\
mlns=\x22http://www\
.w3.org/2000/svg\
\x22 fill=\x22none\x22 st\
roke=\x22currentCol\
or\x22 stroke-width\
=\x222\x22 stroke-line\
cap=\x22round\x22 stro\
ke-linejoin=\x22rou\
nd\x22><path d=\x22M12\
3h7a2 2 0 0 1 2\
2v14a2 2 0 0 1-\
2 2h-7m0-18H5a2 \
2 0 0 0-2 2v14a2\
2 0 0 0 2 2h7m0\
-18v18\x22/></svg>\
\x00\x00\x01_\
<\
svg xmlns=\x22http:\
//www.w3.org/200\
0/svg\x22 width=\x2224\
\x22 height=\x2224\x22 vi\
ewBox=\x220 0 24 24\
\x22 fill=\x22none\x22 st\
roke=\x22currentCol\
or\x22 stroke-width\
=\x222\x22 stroke-line\
cap=\x22round\x22 stro\
ke-linejoin=\x22rou\
nd\x22><path d=\x22M22\
19a2 2 0 0 1-2 \
2H4a2 2 0 0 1-2-\
2V5a2 2 0 0 1 2-\
2h5l2 3h9a2 2 0 \
0 1 2 2z\x22/><line\
x1=\x2212\x22 y1=\x2211\x22\
x2=\x2212\x22 y2=\x2217\x22\
/><line x1=\x229\x22 y\
1=\x2214\x22 x2=\x2215\x22 y\
2=\x2214\x22/></svg>\
\x00\x00\x01$\
<\
svg xmlns=\x22http:\
//www.w3.org/200\
0/svg\x22 width=\x2224\
\x22 height=\x2224\x22 vi\
ewBox=\x220 0 24 24\
\x22 fill=\x22none\x22 st\
roke=\x22currentCol\
or\x22 stroke-width\
=\x222\x22 stroke-line\
cap=\x22round\x22 stro\
ke-linejoin=\x22rou\
nd\x22><path d=\x22M13\
2H6a2 2 0 0 0-2\
2v16a2 2 0 0 0 \
2 2h12a2 2 0 0 0\
2-2V9z\x22/><polyl\
ine points=\x2213 2\
13 9 20 9\x22/></s\
vg>\
\x00\x00\x01S\
<\
svg xmlns=\x22http:\
//www.w3.org/200\
0/svg\x22 width=\x2224\
\x22 height=\x2224\x22 vi\
ewBox=\x220 0 24 24\
\x22 fill=\x22none\x22 st\
roke=\x22currentCol\
or\x22 stroke-width\
=\x222\x22 stroke-line\
cap=\x22round\x22 stro\
ke-linejoin=\x22rou\
nd\x22><polyline po\
ints=\x2223 4 23 10\
17 10\x22/><polyli\
ne points=\x221 20 \
1 14 7 14\x22/><pat\
h d=\x22M3.51 9a9 9\
0 0 1 14.85-3.3\
6L23 10M1 14l4.6\
4 4.36A9 9 0 0 0\
20.49 15\x22/></sv\
g>\
\x00\x00\x01\x12\
<\
svg xmlns=\x22http:\
//www.w3.org/200\
0/svg\x22 width=\x2224\
\x22 height=\x2224\x22 vi\
ewBox=\x220 0 24 24\
\x22 fill=\x22none\x22 st\
roke=\x22currentCol\
or\x22 stroke-width\
=\x222\x22 stroke-line\
cap=\x22round\x22 stro\
ke-linejoin=\x22rou\
nd\x22><path d=\x22M22\
19a2 2 0 0 1-2 \
2H4a2 2 0 0 1-2-\
2V5a2 2 0 0 1 2-\
2h5l2 3h9a2 2 0 \
0 1 2 2z\x22/></svg\
>\
\x00\x00\x00\xde\
<\
svg xmlns=\x22http:\
//www.w3.org/200\
0/svg\x22 width=\x2224\
\x22 height=\x2224\x22 vi\
ewBox=\x220 0 24 24\
\x22 fill=\x22none\x22 st\
roke=\x22currentCol\
or\x22 stroke-width\
=\x222\x22 stroke-line\
cap=\x22round\x22 stro\
ke-linejoin=\x22rou\
nd\x22><polyline po\
ints=\x226 9 12 15 \
18 9\x22/></svg>\
\x00\x00\x03\xc4\
<\
svg xmlns=\x22http:\
//www.w3.org/200\
0/svg\x22 width=\x2224\
\x22 height=\x2224\x22 vi\
ewBox=\x220 0 24 24\
\x22 fill=\x22none\x22 st\
roke=\x22currentCol\
or\x22 stroke-width\
=\x222\x22 stroke-line\
cap=\x22round\x22 stro\
ke-linejoin=\x22rou\
nd\x22><circle cx=\x22\
12\x22 cy=\x2212\x22 r=\x223\
\x22/><path d=\x22M19.\
4 15a1.65 1.65 0\
0 0 .33 1.82l.0\
6.06a2 2 0 0 1 0\
2.83 2 2 0 0 1-\
2.83 0l-.06-.06a\
1.65 1.65 0 0 0-\
1.82-.33 1.65 1.\
65 0 0 0-1 1.51V\
21a2 2 0 0 1-2 2\
2 2 0 0 1-2-2v-\
.09A1.65 1.65 0 \
0 0 9 19.4a1.65 \
1.65 0 0 0-1.82.\
33l-.06.06a2 2 0\
0 1-2.83 0 2 2 \
0 0 1 0-2.83l.06\
-.06a1.65 1.65 0\
0 0 .33-1.82 1.\
65 1.65 0 0 0-1.\
51-1H3a2 2 0 0 1\
-2-2 2 2 0 0 1 2\
-2h.09A1.65 1.65\
0 0 0 4.6 9a1.6\
5 1.65 0 0 0-.33\
-1.82l-.06-.06a2\
2 0 0 1 0-2.83 \
2 2 0 0 1 2.83 0\
l.06.06a1.65 1.6\
5 0 0 0 1.82.33H\
9a1.65 1.65 0 0 \
0 1-1.51V3a2 2 0\
0 1 2-2 2 2 0 0\
1 2 2v.09a1.65 \
1.65 0 0 0 1 1.5\
1 1.65 1.65 0 0 \
0 1.82-.33l.06-.\
06a2 2 0 0 1 2.8\
3 0 2 2 0 0 1 0 \
2.83l-.06.06a1.6\
5 1.65 0 0 0-.33\
1.82V9a1.65 1.6\
5 0 0 0 1.51 1H2\
1a2 2 0 0 1 2 2 \
2 2 0 0 1-2 2h-.\
09a1.65 1.65 0 0\
0-1.51 1z\x22/></s\
vg>\
\x00\x00\x01'\
<\
svg xmlns=\x22http:\
//www.w3.org/200\
0/svg\x22 width=\x2224\
\x22 height=\x2224\x22 vi\
ewBox=\x220 0 24 24\
\x22 fill=\x22none\x22 st\
roke=\x22currentCol\
or\x22 stroke-width\
=\x222\x22 stroke-line\
cap=\x22round\x22 stro\
ke-linejoin=\x22rou\
nd\x22><circle cx=\x22\
12\x22 cy=\x2212\x22 r=\x221\
0\x22/><line x1=\x2212\
\x22 y1=\x228\x22 x2=\x2212\x22\
y2=\x2216\x22/><line \
x1=\x228\x22 y1=\x2212\x22 x\
2=\x2216\x22 y2=\x2212\x22/>\
</svg>\
\x00\x00\x019\
<\
svg xmlns=\x22http:\
//www.w3.org/200\
0/svg\x22 width=\x2224\
\x22 height=\x2224\x22 vi\
ewBox=\x220 0 24 24\
\x22 fill=\x22none\x22 st\
roke=\x22currentCol\
or\x22 stroke-width\
=\x222\x22 stroke-line\
cap=\x22round\x22 stro\
ke-linejoin=\x22rou\
nd\x22><path d=\x22M9 \
21H5a2 2 0 0 1-2\
-2V5a2 2 0 0 1 2\
-2h4\x22/><polyline\
points=\x2216 17 2\
1 12 16 7\x22/><lin\
e x1=\x2221\x22 y1=\x2212\
\x22 x2=\x229\x22 y2=\x2212\x22\
/></svg>\
\x00\x00\x01\x13\
<\
svg xmlns=\x22http:\
//www.w3.org/200\
0/svg\x22 width=\x2224\
\x22 height=\x2224\x22 vi\
ewBox=\x220 0 24 24\
\x22 fill=\x22none\x22 st\
roke=\x22currentCol\
or\x22 stroke-width\
=\x222\x22 stroke-line\
cap=\x22round\x22 stro\
ke-linejoin=\x22rou\
nd\x22><path d=\x22M22\
11.08V12a10 10 \
0 1 1-5.93-9.14\x22\
/><polyline poin\
ts=\x2222 4 12 14.0\
1 9 11.01\x22/></sv\
g>\
\x00\x00\x01*\
<\
svg xmlns=\x22http:\
//www.w3.org/200\
0/svg\x22 width=\x2224\
\x22 height=\x2224\x22 vi\
ewBox=\x220 0 24 24\
\x22 fill=\x22none\x22 st\
roke=\x22currentCol\
or\x22 stroke-width\
=\x222\x22 stroke-line\
cap=\x22round\x22 stro\
ke-linejoin=\x22rou\
nd\x22><circle cx=\x22\
12\x22 cy=\x2212\x22 r=\x221\
0\x22/><line x1=\x2212\
\x22 y1=\x2216\x22 x2=\x2212\
\x22 y2=\x2212\x22/><line\
x1=\x2212\x22 y1=\x228\x22 \
x2=\x2212.01\x22 y2=\x228\
\x22/></svg>\
\x00\x00\x00\xdf\
<\
svg xmlns=\x22http:\
//www.w3.org/200\
0/svg\x22 width=\x2224\
\x22 height=\x2224\x22 vi\
ewBox=\x220 0 24 24\
\x22 fill=\x22none\x22 st\
roke=\x22currentCol\
or\x22 stroke-width\
=\x222\x22 stroke-line\
cap=\x22round\x22 stro\
ke-linejoin=\x22rou\
nd\x22><polyline po\
ints=\x2218 15 12 9\
6 15\x22/></svg>\
\x00\x00\x01\x91\
<\
svg xmlns=\x22http:\
//www.w3.org/200\
0/svg\x22 width=\x2224\
\x22 height=\x2224\x22 vi\
ewBox=\x220 0 24 24\
\x22 fill=\x22none\x22 st\
roke=\x22currentCol\
or\x22 stroke-width\
=\x222\x22 stroke-line\
cap=\x22round\x22 stro\
ke-linejoin=\x22rou\
nd\x22><path d=\x22M14\
2H6a2 2 0 0 0-2\
2v16a2 2 0 0 0 \
2 2h12a2 2 0 0 0\
2-2V8z\x22/><polyl\
ine points=\x2214 2\
14 8 20 8\x22/><li\
ne x1=\x2216\x22 y1=\x221\
3\x22 x2=\x228\x22 y2=\x2213\
\x22/><line x1=\x2216\x22\
y1=\x2217\x22 x2=\x228\x22 \
y2=\x2217\x22/><polyli\
ne points=\x2210 9 \
9 9 8 9\x22/></svg>\
\
\x00\x00\x01q\
<\
svg xmlns=\x22http:\
//www.w3.org/200\
0/svg\x22 width=\x2224\
\x22 height=\x2224\x22 vi\
ewBox=\x220 0 24 24\
\x22 fill=\x22none\x22 st\
roke=\x22currentCol\
or\x22 stroke-width\
=\x222\x22 stroke-line\
cap=\x22round\x22 stro\
ke-linejoin=\x22rou\
nd\x22><path d=\x22M14\
2H6a2 2 0 0 0-2\
2v16a2 2 0 0 0 \
2 2h12a2 2 0 0 0\
2-2V8z\x22/><polyl\
ine points=\x2214 2\
14 8 20 8\x22/><li\
ne x1=\x2212\x22 y1=\x221\
8\x22 x2=\x2212\x22 y2=\x221\
2\x22/><line x1=\x229\x22\
y1=\x2215\x22 x2=\x2215\x22\
y2=\x2215\x22/></svg>\
\
\x00\x00\x01\x02\
<\
svg xmlns=\x22http:\
//www.w3.org/200\
0/svg\x22 width=\x2224\
\x22 height=\x2224\x22 vi\
ewBox=\x220 0 24 24\
\x22 fill=\x22none\x22 st\
roke=\x22currentCol\
or\x22 stroke-width\
=\x222\x22 stroke-line\
cap=\x22round\x22 stro\
ke-linejoin=\x22rou\
nd\x22><polyline po\
ints=\x2216 18 22 1\
2 16 6\x22/><polyli\
ne points=\x228 6 2\
12 8 18\x22/></svg\
>\
\x00\x00\x01\x84\
<\
svg xmlns=\x22http:\
//www.w3.org/200\
0/svg\x22 width=\x2224\
\x22 height=\x2224\x22 vi\
ewBox=\x220 0 24 24\
\x22 fill=\x22none\x22 st\
roke=\x22currentCol\
or\x22 stroke-width\
=\x222\x22 stroke-line\
cap=\x22round\x22 stro\
ke-linejoin=\x22rou\
nd\x22><polyline po\
ints=\x223 6 5 6 21\
6\x22/><path d=\x22M1\
9 6v14a2 2 0 0 1\
-2 2H7a2 2 0 0 1\
-2-2V6m3 0V4a2 2\
0 0 1 2-2h4a2 2\
0 0 1 2 2v2\x22/><\
line x1=\x2210\x22 y1=\
\x2211\x22 x2=\x2210\x22 y2=\
\x2217\x22/><line x1=\x22\
14\x22 y1=\x2211\x22 x2=\x22\
14\x22 y2=\x2217\x22/></s\
vg>\
\x00\x00\x01:\
<\
svg xmlns=\x22http:\
//www.w3.org/200\
0/svg\x22 width=\x2224\
\x22 height=\x2224\x22 vi\
ewBox=\x220 0 24 24\
\x22 fill=\x22none\x22 st\
roke=\x22currentCol\
or\x22 stroke-width\
=\x222\x22 stroke-line\
cap=\x22round\x22 stro\
ke-linejoin=\x22rou\
nd\x22><line x1=\x226\x22\
y1=\x223\x22 x2=\x226\x22 y\
2=\x2215\x22/><circle \
cx=\x2218\x22 cy=\x226\x22 r\
=\x223\x22/><circle cx\
=\x226\x22 cy=\x2218\x22 r=\x22\
3\x22/><path d=\x22M18\
9a9 9 0 0 1-9 9\
\x22/></svg>\
"
qt_resource_name = b"\
\x00\x05\
\x00o\xa6S\
\x00i\
\x00c\x00o\x00n\x00s\
\x00\x10\
\x02\xfe\x1a\xa7\
\x00m\
\x00i\x00n\x00u\x00s\x00-\x00c\x00i\x00r\x00c\x00l\x00e\x00.\x00s\x00v\x00g\
\x00\x0b\
\x0cb\x05\x87\
\x00s\
\x00l\x00i\x00d\x00e\x00r\x00s\x00.\x00s\x00v\x00g\
\x00\x0f\
\x0b\xa3Gg\
\x00p\
\x00l\x00a\x00y\x00-\x00c\x00i\x00r\x00c\x00l\x00e\x00.\x00s\x00v\x00g\
\x00\x0b\
\x04\x82\x9dG\
\x00c\
\x00o\x00l\x00u\x00m\x00n\x00s\x00.\x00s\x00v\x00g\
\x00\x0f\
\x06\x9fG\xa7\
\x00f\
\x00o\x00l\x00d\x00e\x00r\x00-\x00p\x00l\x00u\x00s\x00.\x00s\x00v\x00g\
\x00\x08\
\x00(Wg\
\x00f\
\x00i\x00l\x00e\x00.\x00s\x00v\x00g\
\x00\x0e\
\x04\x1b\xd7\x87\
\x00r\
\x00e\x00f\x00r\x00e\x00s\x00h\x00-\x00c\x00w\x00.\x00s\x00v\x00g\
\x00\x0a\
\x0a\xc8\xf6\x87\
\x00f\
\x00o\x00l\x00d\x00e\x00r\x00.\x00s\x00v\x00g\
\x00\x10\
\x0e\x17\x06\x87\
\x00c\
\x00h\x00e\x00v\x00r\x00o\x00n\x00-\x00d\x00o\x00w\x00n\x00.\x00s\x00v\x00g\
\x00\x0c\
\x0b\xdf,\xc7\
\x00s\
\x00e\x00t\x00t\x00i\x00n\x00g\x00s\x00.\x00s\x00v\x00g\
\x00\x0f\
\x02\xe3G'\
\x00p\
\x00l\x00u\x00s\x00-\x00c\x00i\x00r\x00c\x00l\x00e\x00.\x00s\x00v\x00g\
\x00\x0b\
\x06!\xeeG\
\x00l\
\x00o\x00g\x00-\x00o\x00u\x00t\x00.\x00s\x00v\x00g\
\x00\x10\
\x0d\xfd\xe1'\
\x00c\
\x00h\x00e\x00c\x00k\x00-\x00c\x00i\x00r\x00c\x00l\x00e\x00.\x00s\x00v\x00g\
\x00\x08\
\x04\xd2T\xc7\
\x00i\
\x00n\x00f\x00o\x00.\x00s\x00v\x00g\
\x00\x0e\
\x09Xl\x87\
\x00c\
\x00h\x00e\x00v\x00r\x00o\x00n\x00-\x00u\x00p\x00.\x00s\x00v\x00g\
\x00\x0d\
\x06\xf2R'\
\x00f\
\x00i\x00l\x00e\x00-\x00t\x00e\x00x\x00t\x00.\x00s\x00v\x00g\
\x00\x0d\
\x09\xc3S\x87\
\x00f\
\x00i\x00l\x00e\x00-\x00p\x00l\x00u\x00s\x00.\x00s\x00v\x00g\
\x00\x08\
\x05\xa8W\x87\
\x00c\
\x00o\x00d\x00e\x00.\x00s\x00v\x00g\
\x00\x0b\
\x0b\xf2K\xe7\
\x00t\
\x00r\x00a\x00s\x00h\x00-\x002\x00.\x00s\x00v\x00g\
\x00\x0e\
\x04|qG\
\x00g\
\x00i\x00t\x00-\x00b\x00r\x00a\x00n\x00c\x00h\x00.\x00s\x00v\x00g\
"
qt_resource_struct = b"\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x14\x00\x00\x00\x02\
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\xb6\x00\x00\x00\x00\x00\x01\x00\x00\x06\xa5\
\x00\x00\x01\x9ey\x0c6\xfa\
\x00\x00\x01L\x00\x00\x00\x00\x00\x01\x00\x00\x0e\xe4\
\x00\x00\x01\x9ey\x0c3\x89\
\x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
\x00\x00\x01\x9ey\x0c4\x94\
\x00\x00\x00\xcc\x00\x00\x00\x00\x00\x01\x00\x00\x07\xcd\
\x00\x00\x01\x9ey\x0c2\xb4\
\x00\x00\x02\x5c\x00\x00\x00\x00\x00\x01\x00\x00\x1a\x0c\
\x00\x00\x01\x9ey\x0c:\x95\
\x00\x00\x00v\x00\x00\x00\x00\x00\x01\x00\x00\x04\x1e\
\x00\x00\x01\x9ey\x0cB\x90\
\x00\x00\x01\xb2\x00\x00\x00\x00\x00\x01\x00\x00\x12c\
\x00\x00\x01\x9ey\x0c9c\
\x00\x00\x02*\x00\x00\x00\x00\x00\x01\x00\x00\x17~\
\x00\x00\x01\x9ey\x0c<\x93\
\x00\x00\x01p\x00\x00\x00\x00\x00\x01\x00\x00\x10\x0f\
\x00\x00\x01\x9ey\x0c.\xf3\
\x00\x00\x00\x92\x00\x00\x00\x00\x00\x01\x00\x00\x05B\
\x00\x00\x01\x9ey\x0c-\x81\
\x00\x00\x01\xea\x00\x00\x00\x00\x00\x01\x00\x00\x14t\
\x00\x00\x01\x9ey\x0c;i\
\x00\x00\x01\xc8\x00\x00\x00\x00\x00\x01\x00\x00\x13\x91\
\x00\x00\x01\x9ey\x0c>\xf8\
\x00\x00\x02\x0a\x00\x00\x00\x00\x00\x01\x00\x00\x16\x09\
\x00\x00\x01\x9ey\x0cA`\
\x00\x00\x00\xee\x00\x00\x00\x00\x00\x01\x00\x00\x09$\
\x00\x00\x01\x9ey\x0c1c\
\x00\x00\x00R\x00\x00\x00\x00\x00\x01\x00\x00\x03\x16\
\x00\x00\x01\x9ey\x0c5\xc9\
\x00\x00\x01.\x00\x00\x00\x00\x00\x01\x00\x00\x0b\x1c\
\x00\x00\x01\x9ey\x0c00\
\x00\x00\x02@\x00\x00\x00\x00\x00\x01\x00\x00\x18\x84\
\x00\x00\x01\x9ey\x0c?\xdf\
\x00\x00\x006\x00\x00\x00\x00\x00\x01\x00\x00\x01\x05\
\x00\x00\x01\x9ey\x0cC\xc7\
\x00\x00\x01\x8c\x00\x00\x00\x00\x00\x01\x00\x00\x11L\
\x00\x00\x01\x9ey\x0c8.\
\x00\x00\x01\x08\x00\x00\x00\x00\x00\x01\x00\x00\x0a:\
\x00\x00\x01\x9ey\x0c=\xc8\
"
def qInitResources():
QtCore.qRegisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)
def qCleanupResources():
QtCore.qUnregisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)
qInitResources()
+11
View File
@@ -1,6 +1,7 @@
from PySide6.QtWidgets import QDialog, QTableWidgetItem, QHeaderView, QAbstractItemView from PySide6.QtWidgets import QDialog, QTableWidgetItem, QHeaderView, QAbstractItemView
from PySide6.QtCore import Qt from PySide6.QtCore import Qt
from pathlib import Path from pathlib import Path
from icons import icon
from ui.AppSettings_ui import Ui_Dialog from ui.AppSettings_ui import Ui_Dialog
from ui.JavaVmConfigDialog import JavaVmConfigDialog from ui.JavaVmConfigDialog import JavaVmConfigDialog
@@ -36,11 +37,21 @@ class AppSettingsDlg(QDialog):
self.temp_pdf_projects = self.settings.pdf_projects.copy() self.temp_pdf_projects = self.settings.pdf_projects.copy()
self.temp_postgresql_dbs = self.settings.postgresql_dbs.copy() self.temp_postgresql_dbs = self.settings.postgresql_dbs.copy()
self._setup_icons()
self._connect_signals() self._connect_signals()
self._setup_tables() self._setup_tables()
self._populate_tables() self._populate_tables()
self._populate_performance_tab() self._populate_performance_tab()
def _setup_icons(self):
"""Setzt Feather Icons für alle Hinzufügen/Entfernen-Buttons."""
add = icon("plus-circle")
remove = icon("minus-circle")
for btn_name in ("addXsl", "addJavaVm", "addSaxon", "addApacheFop", "addDiffPdf", "addPostgreSql", "addProject"):
getattr(self.ui, btn_name).setIcon(add)
for btn_name in ("removeXsl", "removeJavaVm", "removeSaxon", "removeApacheFop", "removeDiffPdf", "removePostgreSql", "removeProject"):
getattr(self.ui, btn_name).setIcon(remove)
# --- Generische Helfer --- # --- Generische Helfer ---
def _update_remove_button(self, table, button): def _update_remove_button(self, table, button):
+22 -4
View File
@@ -25,6 +25,7 @@ from ui.mixins import (
TransformationMixin, TransformationMixin,
) )
from conf import app_settings, Project, ProjectData, TreeNode, XslFile from conf import app_settings, Project, ProjectData, TreeNode, XslFile
from icons import icon
from pathlib import Path from pathlib import Path
@@ -140,9 +141,27 @@ class MainWindow(
# Zoom per Mausrad (STRG+Mausrad) für PDF-Viewer aktivieren # Zoom per Mausrad (STRG+Mausrad) für PDF-Viewer aktivieren
self._setup_scroll_area_zoom() self._setup_scroll_area_zoom()
# Icons setzen (überschreibt fromTheme()-Icons aus _ui.py)
self._setup_icons()
# Gespeicherte UI-Zustände wiederherstellen # Gespeicherte UI-Zustände wiederherstellen
self._restore_ui_state() self._restore_ui_state()
def _setup_icons(self):
"""Setzt Feather Icons für alle Menü-Aktionen und Buttons."""
self.ui.actionNeu.setIcon(icon("folder-plus"))
self.ui.actionBeenden.setIcon(icon("log-out"))
self.ui.actionEinstellungen.setIcon(icon("settings"))
self.ui.actionVorhandene_Projekte.setIcon(icon("folder"))
self.ui.actionAlle_XML_Dateien_neu_transformieren_force.setIcon(icon("refresh-cw"))
self.ui.view_ref_pdf.setIcon(icon("file"))
self.ui.view_new_pdf.setIcon(icon("file"))
self.ui.accept_changes.setIcon(icon("check-circle"))
if hasattr(self, "action_xsl_dependencies"):
self.action_xsl_dependencies.setIcon(icon("git-branch"))
if hasattr(self, "action_info"):
self.action_info.setIcon(icon("info"))
def _restore_ui_state(self): def _restore_ui_state(self):
"""Stellt die gespeicherten UI-Zustände wieder her (Fenstergeometrie, Splitter, TreeWidget-Spalten).""" """Stellt die gespeicherten UI-Zustände wieder her (Fenstergeometrie, Splitter, TreeWidget-Spalten)."""
global app_settings global app_settings
@@ -339,6 +358,9 @@ class MainWindow(
logger.info(f"Theme erfolgreich gewechselt zu: {theme_name}") logger.info(f"Theme erfolgreich gewechselt zu: {theme_name}")
app_settings.theme = theme_name app_settings.theme = theme_name
app_settings.save() app_settings.save()
self._setup_icons()
if hasattr(self, "pdf_project") and self.pdf_project:
self._load_nodes_to_tree()
else: else:
logger.error(f"Fehler: Theme '{theme_name}' konnte nicht erstellt werden") logger.error(f"Fehler: Theme '{theme_name}' konnte nicht erstellt werden")
@@ -385,10 +407,7 @@ class MainWindow(
self.ui.menuProjekt.addAction(self.action_worker_metrics) self.ui.menuProjekt.addAction(self.action_worker_metrics)
# Menü-Aktion "Abhängigkeitsgraph" zum Aktion-Menü hinzufügen # Menü-Aktion "Abhängigkeitsgraph" zum Aktion-Menü hinzufügen
from PySide6.QtGui import QIcon as _QIcon
self.action_xsl_dependencies = QAction("XSL-Abhängigkeitsgraph", self) self.action_xsl_dependencies = QAction("XSL-Abhängigkeitsgraph", self)
self.action_xsl_dependencies.setIcon(_QIcon(_QIcon.fromTheme("view-list-tree")))
self.action_xsl_dependencies.triggered.connect(self._show_xsl_dependency_dialog) self.action_xsl_dependencies.triggered.connect(self._show_xsl_dependency_dialog)
self.ui.menuAktion.addSeparator() self.ui.menuAktion.addSeparator()
self.ui.menuAktion.addAction(self.action_xsl_dependencies) self.ui.menuAktion.addAction(self.action_xsl_dependencies)
@@ -406,7 +425,6 @@ class MainWindow(
# Hilfe-Menü programmatisch erstellen # Hilfe-Menü programmatisch erstellen
self.menu_hilfe = QMenu("Hilfe", self) self.menu_hilfe = QMenu("Hilfe", self)
self.action_info = QAction("Info ...", self) self.action_info = QAction("Info ...", self)
self.action_info.setIcon(_QIcon(_QIcon.fromTheme("help-about")))
self.action_info.triggered.connect(self._show_about_dialog) self.action_info.triggered.connect(self._show_about_dialog)
self.menu_hilfe.addAction(self.action_info) self.menu_hilfe.addAction(self.action_info)
self.ui.menubar.addMenu(self.menu_hilfe) self.ui.menubar.addMenu(self.menu_hilfe)
+4
View File
@@ -1,5 +1,6 @@
from PySide6.QtWidgets import QDialog, QTableWidgetItem from PySide6.QtWidgets import QDialog, QTableWidgetItem
from ui.ProjectXsltParamsDialog_ui import Ui_ProjectXsltParamsDialog from ui.ProjectXsltParamsDialog_ui import Ui_ProjectXsltParamsDialog
from icons import icon
class ProjectXsltParamsDialog(QDialog): class ProjectXsltParamsDialog(QDialog):
@@ -11,6 +12,9 @@ class ProjectXsltParamsDialog(QDialog):
self.ui = Ui_ProjectXsltParamsDialog() self.ui = Ui_ProjectXsltParamsDialog()
self.ui.setupUi(self) self.ui.setupUi(self)
self.ui.addParamButton.setIcon(icon("plus-circle"))
self.ui.removeParamButton.setIcon(icon("minus-circle"))
self.ui.addParamButton.clicked.connect(self._add_parameter) self.ui.addParamButton.clicked.connect(self._add_parameter)
self.ui.removeParamButton.clicked.connect(self._remove_parameter) self.ui.removeParamButton.clicked.connect(self._remove_parameter)
+5 -4
View File
@@ -12,7 +12,7 @@ import tempfile
from pathlib import Path from pathlib import Path
from PySide6.QtCore import QUrl, Qt from PySide6.QtCore import QUrl, Qt
from PySide6.QtGui import QIcon from icons import icon
from PySide6.QtWidgets import ( from PySide6.QtWidgets import (
QComboBox, QComboBox,
QDialog, QDialog,
@@ -154,6 +154,7 @@ class XslDependencyDialog(QDialog):
# Sidebar initial ausblenden # Sidebar initial ausblenden
self.ui.sidebarWidget.setVisible(False) self.ui.sidebarWidget.setVisible(False)
self.ui.mainSplitter.setSizes([1000, 0]) self.ui.mainSplitter.setSizes([1000, 0])
self.ui.settingsButton.setIcon(icon("sliders"))
self.ui.settingsButton.clicked.connect(self._toggle_sidebar) self.ui.settingsButton.clicked.connect(self._toggle_sidebar)
# Netzwerkgraph-Tab ausblenden wenn WebEngine nicht verfügbar # Netzwerkgraph-Tab ausblenden wenn WebEngine nicht verfügbar
@@ -220,7 +221,7 @@ class XslDependencyDialog(QDialog):
"""Befüllt den Dateibaum mit allen XSL-Dateien und Abhängigkeitszahlen.""" """Befüllt den Dateibaum mit allen XSL-Dateien und Abhängigkeitszahlen."""
self.ui.fileTree.clear() self.ui.fileTree.clear()
xsl_icon = QIcon.fromTheme("text-x-generic") xsl_icon = icon("file-text")
for xsl_file in sorted(self._full_graph.keys(), key=lambda p: self._rel_path(p).lower()): for xsl_file in sorted(self._full_graph.keys(), key=lambda p: self._rel_path(p).lower()):
deps_count = len(self._full_graph.get(xsl_file, set())) deps_count = len(self._full_graph.get(xsl_file, set()))
@@ -260,8 +261,8 @@ class XslDependencyDialog(QDialog):
rel_name = self._rel_path(xsl_file) rel_name = self._rel_path(xsl_file)
self.ui.rightLabel.setText(f"Abhängigkeiten: {rel_name}") self.ui.rightLabel.setText(f"Abhängigkeiten: {rel_name}")
import_icon = QIcon.fromTheme("go-down") import_icon = icon("chevron-down")
imported_by_icon = QIcon.fromTheme("go-up") imported_by_icon = icon("chevron-up")
# Sektion: "Importiert" (forward dependencies) # Sektion: "Importiert" (forward dependencies)
deps = self._full_graph.get(xsl_file, set()) deps = self._full_graph.get(xsl_file, set())
+4
View File
@@ -1,5 +1,6 @@
from PySide6.QtWidgets import QDialog, QTableWidgetItem, QMessageBox from PySide6.QtWidgets import QDialog, QTableWidgetItem, QMessageBox
from PySide6.QtCore import Qt from PySide6.QtCore import Qt
from icons import icon
class XsltParamsEditDialog(QDialog): class XsltParamsEditDialog(QDialog):
@@ -14,6 +15,9 @@ class XsltParamsEditDialog(QDialog):
self.node = node self.node = node
self.parent_params = parent_params or {} self.parent_params = parent_params or {}
self.ui.addParamButton.setIcon(icon("plus-circle"))
self.ui.removeParamButton.setIcon(icon("minus-circle"))
self.ui.addParamButton.clicked.connect(self.add_parameter) self.ui.addParamButton.clicked.connect(self.add_parameter)
self.ui.removeParamButton.clicked.connect(self.remove_parameter) self.ui.removeParamButton.clicked.connect(self.remove_parameter)
+25 -43
View File
@@ -15,7 +15,7 @@ from enum import Enum, auto
from pathlib import Path from pathlib import Path
from PySide6.QtCore import Qt from PySide6.QtCore import Qt
from PySide6.QtGui import QAction, QIcon from PySide6.QtGui import QAction
from PySide6.QtWidgets import ( from PySide6.QtWidgets import (
QMenu, QMenu,
QTreeWidgetItem, QTreeWidgetItem,
@@ -28,6 +28,7 @@ from PySide6.QtWidgets import (
) )
from conf import TreeNode, XslFile, XmlFile from conf import TreeNode, XslFile, XmlFile
from icons import icon
from ui.TreeNodeEditDialog import TreeNodeEditDialog from ui.TreeNodeEditDialog import TreeNodeEditDialog
from ui.XslFileEditDialog import XslFileEditDialog from ui.XslFileEditDialog import XslFileEditDialog
from ui.XmlToXslAssignDialog import XmlToXslAssignDialog from ui.XmlToXslAssignDialog import XmlToXslAssignDialog
@@ -319,7 +320,7 @@ class TreeManagerMixin:
if node_type == ItemType.TREE_NODE: if node_type == ItemType.TREE_NODE:
# Kontextmenü für TreeNode # Kontextmenü für TreeNode
action_edit = QAction("Bearbeiten", self) action_edit = QAction("Bearbeiten", self)
action_edit.setIcon(QIcon(QIcon.fromTheme(QIcon.ThemeIcon.DocumentProperties))) action_edit.setIcon(icon("settings"))
action_edit.triggered.connect(lambda: self._edit_tree_node(item)) action_edit.triggered.connect(lambda: self._edit_tree_node(item))
font = action_edit.font() font = action_edit.font()
font.setBold(True) font.setBold(True)
@@ -330,12 +331,12 @@ class TreeManagerMixin:
menu.addSeparator() menu.addSeparator()
action_add_child = QAction("Unterknoten hinzufügen", self) action_add_child = QAction("Unterknoten hinzufügen", self)
action_add_child.setIcon(QIcon(QIcon.fromTheme("folder-new"))) action_add_child.setIcon(icon("folder-plus"))
action_add_child.triggered.connect(lambda: self._add_tree_node_child(item)) action_add_child.triggered.connect(lambda: self._add_tree_node_child(item))
menu.addAction(action_add_child) menu.addAction(action_add_child)
action_add_xsl = QAction("XSL-Datei hinzufügen", self) action_add_xsl = QAction("XSL-Datei hinzufügen", self)
action_add_xsl.setIcon(QIcon(QIcon.fromTheme("document-new"))) action_add_xsl.setIcon(icon("file-plus"))
action_add_xsl.triggered.connect(lambda: self._add_xsl_file_to_node(item)) action_add_xsl.triggered.connect(lambda: self._add_xsl_file_to_node(item))
menu.addAction(action_add_xsl) menu.addAction(action_add_xsl)
@@ -346,13 +347,13 @@ class TreeManagerMixin:
has_xml_files = bool(tree_node_obj and self._has_xml_files_recursive(tree_node_obj)) has_xml_files = bool(tree_node_obj and self._has_xml_files_recursive(tree_node_obj))
action_transform = QAction("Alle XML-Dateien transformieren", self) action_transform = QAction("Alle XML-Dateien transformieren", self)
action_transform.setIcon(QIcon(QIcon.fromTheme("system-run"))) action_transform.setIcon(icon("play-circle"))
action_transform.triggered.connect(lambda: self._transform_tree_node(item)) action_transform.triggered.connect(lambda: self._transform_tree_node(item))
action_transform.setEnabled(has_xml_files) action_transform.setEnabled(has_xml_files)
menu.addAction(action_transform) menu.addAction(action_transform)
action_transform_force = QAction("Alle XML-Dateien neu transformieren (force)", self) action_transform_force = QAction("Alle XML-Dateien neu transformieren (force)", self)
action_transform_force.setIcon(QIcon(QIcon.fromTheme("view-refresh"))) action_transform_force.setIcon(icon("refresh-cw"))
action_transform_force.triggered.connect(lambda: self._transform_tree_node(item, force=True)) action_transform_force.triggered.connect(lambda: self._transform_tree_node(item, force=True))
action_transform_force.setEnabled(has_xml_files) action_transform_force.setEnabled(has_xml_files)
menu.addAction(action_transform_force) menu.addAction(action_transform_force)
@@ -364,7 +365,7 @@ class TreeManagerMixin:
has_diff_pdfs = len(diff_pdfs) > 0 has_diff_pdfs = len(diff_pdfs) > 0
action_accept_all = QAction("Alle Änderungen übernehmen", self) action_accept_all = QAction("Alle Änderungen übernehmen", self)
action_accept_all.setIcon(QIcon(QIcon.fromTheme("emblem-default"))) action_accept_all.setIcon(icon("check-circle"))
action_accept_all.triggered.connect(lambda: self._accept_all_changes_under_node(item)) action_accept_all.triggered.connect(lambda: self._accept_all_changes_under_node(item))
action_accept_all.setEnabled(has_diff_pdfs) action_accept_all.setEnabled(has_diff_pdfs)
menu.addAction(action_accept_all) menu.addAction(action_accept_all)
@@ -372,14 +373,14 @@ class TreeManagerMixin:
menu.addSeparator() menu.addSeparator()
action_delete = QAction("Löschen", self) action_delete = QAction("Löschen", self)
action_delete.setIcon(QIcon(QIcon.fromTheme(QIcon.ThemeIcon.EditDelete))) action_delete.setIcon(icon("trash-2"))
action_delete.triggered.connect(lambda: self._delete_tree_node(item)) action_delete.triggered.connect(lambda: self._delete_tree_node(item))
menu.addAction(action_delete) menu.addAction(action_delete)
elif node_type == ItemType.XSL_FILE: elif node_type == ItemType.XSL_FILE:
# Kontextmenü für XslFile # Kontextmenü für XslFile
action_edit = QAction("Bearbeiten", self) action_edit = QAction("Bearbeiten", self)
action_edit.setIcon(QIcon(QIcon.fromTheme(QIcon.ThemeIcon.DocumentProperties))) action_edit.setIcon(icon("settings"))
action_edit.triggered.connect(lambda: self._edit_xsl_file(item)) action_edit.triggered.connect(lambda: self._edit_xsl_file(item))
font = action_edit.font() font = action_edit.font()
font.setBold(True) font.setBold(True)
@@ -390,7 +391,7 @@ class TreeManagerMixin:
menu.addSeparator() menu.addSeparator()
action_add_xml = QAction("XML-Datei hinzufügen", self) action_add_xml = QAction("XML-Datei hinzufügen", self)
action_add_xml.setIcon(QIcon(QIcon.fromTheme("document-new"))) action_add_xml.setIcon(icon("file-plus"))
action_add_xml.triggered.connect(lambda: self._add_xml_file_to_xsl(item)) action_add_xml.triggered.connect(lambda: self._add_xml_file_to_xsl(item))
menu.addAction(action_add_xml) menu.addAction(action_add_xml)
@@ -401,13 +402,13 @@ class TreeManagerMixin:
has_xml_files = bool(xsl_file_obj and xsl_file_obj.xmls) has_xml_files = bool(xsl_file_obj and xsl_file_obj.xmls)
action_transform = QAction("Alle XML-Dateien transformieren", self) action_transform = QAction("Alle XML-Dateien transformieren", self)
action_transform.setIcon(QIcon(QIcon.fromTheme("system-run"))) action_transform.setIcon(icon("play-circle"))
action_transform.triggered.connect(lambda: self._transform_xsl_file(item)) action_transform.triggered.connect(lambda: self._transform_xsl_file(item))
action_transform.setEnabled(has_xml_files) action_transform.setEnabled(has_xml_files)
menu.addAction(action_transform) menu.addAction(action_transform)
action_transform_force = QAction("Alle XML-Dateien neu transformieren (force)", self) action_transform_force = QAction("Alle XML-Dateien neu transformieren (force)", self)
action_transform_force.setIcon(QIcon(QIcon.fromTheme("view-refresh"))) action_transform_force.setIcon(icon("refresh-cw"))
action_transform_force.triggered.connect(lambda: self._transform_xsl_file(item, force=True)) action_transform_force.triggered.connect(lambda: self._transform_xsl_file(item, force=True))
action_transform_force.setEnabled(has_xml_files) action_transform_force.setEnabled(has_xml_files)
menu.addAction(action_transform_force) menu.addAction(action_transform_force)
@@ -419,7 +420,7 @@ class TreeManagerMixin:
has_diff_pdfs = len(diff_pdfs) > 0 has_diff_pdfs = len(diff_pdfs) > 0
action_accept_all = QAction("Alle Änderungen übernehmen", self) action_accept_all = QAction("Alle Änderungen übernehmen", self)
action_accept_all.setIcon(QIcon(QIcon.fromTheme("emblem-default"))) action_accept_all.setIcon(icon("check-circle"))
action_accept_all.triggered.connect(lambda: self._accept_all_changes_under_node(item)) action_accept_all.triggered.connect(lambda: self._accept_all_changes_under_node(item))
action_accept_all.setEnabled(has_diff_pdfs) action_accept_all.setEnabled(has_diff_pdfs)
menu.addAction(action_accept_all) menu.addAction(action_accept_all)
@@ -427,21 +428,21 @@ class TreeManagerMixin:
menu.addSeparator() menu.addSeparator()
action_deps = QAction("Abhängigkeiten anzeigen", self) action_deps = QAction("Abhängigkeiten anzeigen", self)
action_deps.setIcon(QIcon(QIcon.fromTheme("view-list-tree"))) action_deps.setIcon(icon("git-branch"))
action_deps.triggered.connect(lambda: self._show_xsl_dependencies(item)) action_deps.triggered.connect(lambda: self._show_xsl_dependencies(item))
menu.addAction(action_deps) menu.addAction(action_deps)
menu.addSeparator() menu.addSeparator()
action_delete = QAction("Löschen", self) action_delete = QAction("Löschen", self)
action_delete.setIcon(QIcon(QIcon.fromTheme(QIcon.ThemeIcon.EditDelete))) action_delete.setIcon(icon("trash-2"))
action_delete.triggered.connect(lambda: self._delete_xsl_file(item)) action_delete.triggered.connect(lambda: self._delete_xsl_file(item))
menu.addAction(action_delete) menu.addAction(action_delete)
elif node_type == ItemType.XML_FILE: elif node_type == ItemType.XML_FILE:
# Kontextmenü für XmlFile # Kontextmenü für XmlFile
action_edit = QAction("Bearbeiten", self) action_edit = QAction("Bearbeiten", self)
action_edit.setIcon(QIcon(QIcon.fromTheme(QIcon.ThemeIcon.DocumentProperties))) action_edit.setIcon(icon("settings"))
action_edit.triggered.connect(lambda: self._edit_xml_file(item)) action_edit.triggered.connect(lambda: self._edit_xml_file(item))
font = action_edit.font() font = action_edit.font()
font.setBold(True) font.setBold(True)
@@ -453,26 +454,26 @@ class TreeManagerMixin:
# Transformations-Aktionen # Transformations-Aktionen
action_transform = QAction("Transformieren", self) action_transform = QAction("Transformieren", self)
action_transform.setIcon(QIcon(QIcon.fromTheme("system-run"))) action_transform.setIcon(icon("play-circle"))
action_transform.triggered.connect(lambda: self._transform_xml_file(item)) action_transform.triggered.connect(lambda: self._transform_xml_file(item))
menu.addAction(action_transform) menu.addAction(action_transform)
action_transform_force = QAction("Neu transformieren (force)", self) action_transform_force = QAction("Neu transformieren (force)", self)
action_transform_force.setIcon(QIcon(QIcon.fromTheme("view-refresh"))) action_transform_force.setIcon(icon("refresh-cw"))
action_transform_force.triggered.connect(lambda: self._transform_xml_file(item, force=True)) action_transform_force.triggered.connect(lambda: self._transform_xml_file(item, force=True))
menu.addAction(action_transform_force) menu.addAction(action_transform_force)
menu.addSeparator() menu.addSeparator()
action_delete = QAction("Löschen", self) action_delete = QAction("Löschen", self)
action_delete.setIcon(QIcon(QIcon.fromTheme(QIcon.ThemeIcon.EditDelete))) action_delete.setIcon(icon("trash-2"))
action_delete.triggered.connect(lambda: self._delete_xml_file(item)) action_delete.triggered.connect(lambda: self._delete_xml_file(item))
menu.addAction(action_delete) menu.addAction(action_delete)
else: else:
# Unbekannter Typ oder leerer Bereich - Menü für Root-Elemente # Unbekannter Typ oder leerer Bereich - Menü für Root-Elemente
action_add_tree_node = QAction("Unterknoten hinzufügen", self) action_add_tree_node = QAction("Unterknoten hinzufügen", self)
action_add_tree_node.setIcon(QIcon(QIcon.fromTheme("folder-new"))) action_add_tree_node.setIcon(icon("folder-plus"))
action_add_tree_node.triggered.connect(lambda: self._add_root_tree_node()) action_add_tree_node.triggered.connect(lambda: self._add_root_tree_node())
menu.addAction(action_add_tree_node) menu.addAction(action_add_tree_node)
@@ -656,17 +657,9 @@ class TreeManagerMixin:
# Setze Icon basierend auf Node-Typ # Setze Icon basierend auf Node-Typ
if isinstance(node, TreeNode): if isinstance(node, TreeNode):
# TreeNode: Ordner-Icon item.setIcon(0, icon("folder"))
folder_icon = QIcon.fromTheme(QIcon.ThemeIcon.FolderOpen)
if folder_icon.isNull():
folder_icon = QIcon.fromTheme("folder")
item.setIcon(0, folder_icon)
elif isinstance(node, XslFile): elif isinstance(node, XslFile):
# XslFile: Code/Script-Icon für XSL-Dateien item.setIcon(0, icon("file-text"))
xsl_icon = QIcon.fromTheme("text-x-script")
if xsl_icon.isNull():
xsl_icon = QIcon.fromTheme("text-x-generic")
item.setIcon(0, xsl_icon)
if isinstance(node, TreeNode): if isinstance(node, TreeNode):
# Speichere zusätzlich die Node-ID in UserRole+1 für Kompatibilität # Speichere zusätzlich die Node-ID in UserRole+1 für Kompatibilität
@@ -729,12 +722,7 @@ class TreeManagerMixin:
xml_item.setData(0, Qt.ItemDataRole.UserRole + 2, xsl_id_str) xml_item.setData(0, Qt.ItemDataRole.UserRole + 2, xsl_id_str)
# Setze XML-Icon # Setze XML-Icon
xml_icon = QIcon.fromTheme("text-xml") xml_item.setIcon(0, icon("code"))
if xml_icon.isNull():
xml_icon = QIcon.fromTheme("application-xml")
if xml_icon.isNull():
xml_icon = QIcon.fromTheme("text-x-generic")
xml_item.setIcon(0, xml_icon)
# Prüfe ob XML-Datei existiert und deaktiviere Knoten falls nicht # Prüfe ob XML-Datei existiert und deaktiviere Knoten falls nicht
# Wenn XSL-Datei fehlt, deaktiviere auch alle untergeordneten XML-Knoten # Wenn XSL-Datei fehlt, deaktiviere auch alle untergeordneten XML-Knoten
@@ -812,13 +800,7 @@ class TreeManagerMixin:
# Icon-Label # Icon-Label
icon_label = QLabel() icon_label = QLabel()
# Icon für Diff-View mit Fallbacks icon_label.setPixmap(icon("columns").pixmap(16, 16))
icon = QIcon.fromTheme("view-split-left-right")
if icon.isNull():
icon = QIcon.fromTheme("vcs-diff")
if icon.isNull():
icon = QIcon.fromTheme("system-search") # Letzter Fallback
icon_label.setPixmap(icon.pixmap(16, 16))
icon_label.setToolTip("Diff-PDF vorhanden (wird automatisch geladen bei Selektion)") icon_label.setToolTip("Diff-PDF vorhanden (wird automatisch geladen bei Selektion)")
layout.addWidget(icon_label) layout.addWidget(icon_label)
Generated
+1 -1
View File
@@ -39,7 +39,7 @@ wheels = [
[[package]] [[package]]
name = "documentor" name = "documentor"
version = "1.6.6" version = "1.7.0"
source = { virtual = "." } source = { virtual = "." }
dependencies = [ dependencies = [
{ name = "connectorx" }, { name = "connectorx" },