2 Commits

Author SHA1 Message Date
info d19c36191c Version 1.7.3: Fehlende Menü-Icons ergänzt
- MainWindow: Icons für drei bislang icon-lose Menü-Aktionen gesetzt
  - "Alle XML-Dateien transformieren" → play-circle
  - "Aus Datenbank laden" → database (neu)
  - "Worker-Pool-Metriken" → activity (neu)
- Zwei neue Feather-Icons (database, activity) ergänzt: Download-Skript,
  resources.qrc und resources_rc.py (via pyside6-rcc) aktualisiert

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 12:45:25 +02:00
info 3e20b186c7 Version 1.7.2: Icon-System – Theme-Reaktivität generalisiert, Render vereinfacht
- icons.py: IconRefreshMixin ergänzt – reagiert auf PaletteChange/StyleChange
  und färbt Icons nur bei tatsächlichem Textfarb-Wechsel neu ein (farb-gegated)
- icons.py: Render auf einen einzelnen 64px-Pixmap vereinfacht (Qt skaliert),
  statt drei fixe Größen (16/24/32)
- MainWindow: nutzt IconRefreshMixin; hasattr-Guards in _setup_icons entfernt
  (läuft jetzt nur im fertig initialisierten Zustand); change_theme entschlackt –
  Icon-/Baum-Aktualisierung erfolgt über changeEvent statt unbedingtem Aufruf
- XslDependencyDialog: nutzt IconRefreshMixin, färbt Button- und Baum-Icons bei
  Theme-Wechsel neu ein (bislang blieben offene non-modale Dialoge stale)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 12:36:58 +02:00
13 changed files with 793 additions and 659 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.7.1" Version="1.7.3"
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"
+1 -1
View File
@@ -263,5 +263,5 @@ HINWEISE
================================================================================ ================================================================================
Stand: Mai 2026 Stand: Mai 2026
Erstellt für: DocuMentor v1.7.1 Erstellt für: DocuMentor v1.7.3
================================================================================ ================================================================================
+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.7.1" #define MyAppVersion "1.7.3"
#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.7.1" version = "1.7.3"
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"}
+2
View File
@@ -29,6 +29,8 @@ ICONS = [
"file-plus", "file-plus",
"columns", "columns",
"sliders", "sliders",
"database",
"activity",
] ]
BASE_URL = "https://raw.githubusercontent.com/feathericons/feather/master/icons/{name}.svg" BASE_URL = "https://raw.githubusercontent.com/feathericons/feather/master/icons/{name}.svg"
+57 -9
View File
@@ -1,5 +1,5 @@
import logging import logging
from PySide6.QtCore import QByteArray, QFile, Qt from PySide6.QtCore import QByteArray, QEvent, QFile, Qt
from PySide6.QtGui import QIcon, QPainter, QPixmap, QPalette from PySide6.QtGui import QIcon, QPainter, QPixmap, QPalette
from PySide6.QtSvg import QSvgRenderer from PySide6.QtSvg import QSvgRenderer
from PySide6.QtWidgets import QApplication from PySide6.QtWidgets import QApplication
@@ -7,6 +7,10 @@ import res.resources_rc # noqa: F401 # registriert die Qt-Ressourcen (Icons) b
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# Basisgröße für das einmalige Rendern; Qt skaliert daraus die benötigten Icon-Größen
# (16/24/32 px in Menüs, Bäumen, Buttons). 64 px bietet genug Reserve auch für HiDPI.
_RENDER_SIZE = 64
# Cache: (Icon-Name, Theme-Textfarbe) → fertig gerendertes QIcon. # Cache: (Icon-Name, Theme-Textfarbe) → fertig gerendertes QIcon.
# Der Farb-Anteil im Schlüssel sorgt dafür, dass ein Theme-Wechsel automatisch # Der Farb-Anteil im Schlüssel sorgt dafür, dass ein Theme-Wechsel automatisch
# neue Einträge erzeugt, ohne dass der Cache explizit geleert werden muss. # neue Einträge erzeugt, ohne dass der Cache explizit geleert werden muss.
@@ -44,14 +48,58 @@ def icon(name: str) -> QIcon:
f.close() f.close()
renderer = QSvgRenderer(svg_data) renderer = QSvgRenderer(svg_data)
result = QIcon() pixmap = QPixmap(_RENDER_SIZE, _RENDER_SIZE)
for size in (16, 24, 32): pixmap.fill(Qt.GlobalColor.transparent)
pixmap = QPixmap(size, size) painter = QPainter(pixmap)
pixmap.fill(Qt.GlobalColor.transparent) renderer.render(painter)
painter = QPainter(pixmap) painter.end()
renderer.render(painter)
painter.end()
result.addPixmap(pixmap)
result = QIcon(pixmap)
_ICON_CACHE[cache_key] = result _ICON_CACHE[cache_key] = result
return result return result
class IconRefreshMixin:
"""
Mischklasse für Top-Level-Widgets, deren Icons sich beim Theme-Wechsel automatisch neu einfärben.
Voraussetzungen für die nutzende Klasse:
- Sie stellt eine Methode ``_setup_icons()`` bereit, die alle ihre Icons neu setzt.
- Nach abgeschlossener Initialisierung setzt sie ``self._icons_ready = True``
(idealerweise zusammen mit ``self._last_icon_color``, siehe ``mark_icons_ready()``).
Bei einem Style-/Palette-Wechsel wird nur wenn sich die Theme-Textfarbe tatsächlich
geändert hat ``_on_icon_theme_changed()`` aufgerufen (Standard: ``_setup_icons()``).
Unterklassen können ``_on_icon_theme_changed()`` überschreiben, um zusätzlich z.B.
Baum-Icons neu zu zeichnen.
Hinweis: ``IconRefreshMixin`` muss in der Klassenbasis VOR der Qt-Basisklasse
(``QMainWindow``/``QDialog``) stehen, damit das überschriebene ``changeEvent`` greift.
"""
_icons_ready: bool = False
_last_icon_color: str | None = None
@staticmethod
def _current_text_color() -> str | None:
app = QApplication.instance()
if app is None:
return None
return app.palette().color(QPalette.ColorRole.WindowText).name()
def mark_icons_ready(self):
"""Schaltet die Theme-Reaktivität scharf (nach dem ersten ``_setup_icons()`` aufrufen)."""
self._last_icon_color = self._current_text_color()
self._icons_ready = True
def changeEvent(self, event):
if event.type() in (QEvent.Type.PaletteChange, QEvent.Type.StyleChange) and self._icons_ready:
color = self._current_text_color()
if color is not None and color != self._last_icon_color:
self._last_icon_color = color
self._on_icon_theme_changed()
super().changeEvent(event)
def _on_icon_theme_changed(self):
"""Reaktion auf eine geänderte Theme-Textfarbe. Standard: alle Icons neu setzen."""
self._setup_icons()
+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="22 12 18 12 15 21 9 3 6 12 2 12"/></svg>

After

Width:  |  Height:  |  Size: 239 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"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"/><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"/></svg>

After

Width:  |  Height:  |  Size: 318 B

+2
View File
@@ -21,5 +21,7 @@
<file>icons/file-plus.svg</file> <file>icons/file-plus.svg</file>
<file>icons/columns.svg</file> <file>icons/columns.svg</file>
<file>icons/sliders.svg</file> <file>icons/sliders.svg</file>
<file>icons/database.svg</file>
<file>icons/activity.svg</file>
</qresource> </qresource>
</RCC> </RCC>
+85 -34
View File
@@ -168,6 +168,28 @@ h d=\x22M3.51 9a9 9\
4 4.36A9 9 0 0 0\ 4 4.36A9 9 0 0 0\
20.49 15\x22/></sv\ 20.49 15\x22/></sv\
g>\ 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><ellipse cx=\
\x2212\x22 cy=\x225\x22 rx=\x22\
9\x22 ry=\x223\x22/><path\
d=\x22M21 12c0 1.6\
6-4 3-9 3s-9-1.3\
4-9-3\x22/><path d=\
\x22M3 5v14c0 1.66 \
4 3 9 3s9-1.34 9\
-3V5\x22/></svg>\
\x00\x00\x01\x12\ \x00\x00\x01\x12\
<\ <\
svg xmlns=\x22http:\ svg xmlns=\x22http:\
@@ -395,6 +417,23 @@ y2=\x2217\x22/><polyli\
ne points=\x2210 9 \ ne points=\x2210 9 \
9 9 8 9\x22/></svg>\ 9 9 8 9\x22/></svg>\
\ \
\x00\x00\x00\xef\
<\
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=\x2222 12 18 1\
2 15 21 9 3 6 12\
2 12\x22/></svg>\
\x00\x00\x01q\ \x00\x00\x01q\
<\ <\
svg xmlns=\x22http:\ svg xmlns=\x22http:\
@@ -524,6 +563,10 @@ qt_resource_name = b"\
\x04\x1b\xd7\x87\ \x04\x1b\xd7\x87\
\x00r\ \x00r\
\x00e\x00f\x00r\x00e\x00s\x00h\x00-\x00c\x00w\x00.\x00s\x00v\x00g\ \x00e\x00f\x00r\x00e\x00s\x00h\x00-\x00c\x00w\x00.\x00s\x00v\x00g\
\x00\x0c\
\x05\xc9\x15\xc7\
\x00d\
\x00a\x00t\x00a\x00b\x00a\x00s\x00e\x00.\x00s\x00v\x00g\
\x00\x0a\ \x00\x0a\
\x0a\xc8\xf6\x87\ \x0a\xc8\xf6\x87\
\x00f\ \x00f\
@@ -560,6 +603,10 @@ qt_resource_name = b"\
\x06\xf2R'\ \x06\xf2R'\
\x00f\ \x00f\
\x00i\x00l\x00e\x00-\x00t\x00e\x00x\x00t\x00.\x00s\x00v\x00g\ \x00i\x00l\x00e\x00-\x00t\x00e\x00x\x00t\x00.\x00s\x00v\x00g\
\x00\x0c\
\x0cQ;g\
\x00a\
\x00c\x00t\x00i\x00v\x00i\x00t\x00y\x00.\x00s\x00v\x00g\
\x00\x0d\ \x00\x0d\
\x09\xc3S\x87\ \x09\xc3S\x87\
\x00f\ \x00f\
@@ -581,48 +628,52 @@ qt_resource_name = b"\
qt_resource_struct = b"\ qt_resource_struct = b"\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ \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\x00\x00\x00\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x14\x00\x00\x00\x02\ \x00\x00\x00\x00\x00\x02\x00\x00\x00\x16\x00\x00\x00\x02\
\x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\xb6\x00\x00\x00\x00\x00\x01\x00\x00\x06\xa5\ \x00\x00\x00\xb6\x00\x00\x00\x00\x00\x01\x00\x00\x06\xa5\
\x00\x00\x01\x9ey\x0c6\xfa\ \x00\x00\x01\x9ez2\xf1\x12\
\x00\x00\x01L\x00\x00\x00\x00\x00\x01\x00\x00\x0e\xe4\ \x00\x00\x01j\x00\x00\x00\x00\x00\x01\x00\x00\x10&\
\x00\x00\x01\x9ey\x0c3\x89\ \x00\x00\x01\x9ez2\xf1\x12\
\x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ \x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
\x00\x00\x01\x9ey\x0c4\x94\ \x00\x00\x01\x9ez2\xf1\x12\
\x00\x00\x00\xcc\x00\x00\x00\x00\x00\x01\x00\x00\x07\xcd\ \x00\x00\x00\xcc\x00\x00\x00\x00\x00\x01\x00\x00\x07\xcd\
\x00\x00\x01\x9ey\x0c2\xb4\ \x00\x00\x01\x9ez2\xf1\x12\
\x00\x00\x02\x5c\x00\x00\x00\x00\x00\x01\x00\x00\x1a\x0c\ \x00\x00\x02\x98\x00\x00\x00\x00\x00\x01\x00\x00\x1cA\
\x00\x00\x01\x9ey\x0c:\x95\ \x00\x00\x01\x9ez2\xf1\x12\
\x00\x00\x00v\x00\x00\x00\x00\x00\x01\x00\x00\x04\x1e\ \x00\x00\x00v\x00\x00\x00\x00\x00\x01\x00\x00\x04\x1e\
\x00\x00\x01\x9ey\x0cB\x90\ \x00\x00\x01\x9ez2\xf1\x11\
\x00\x00\x01\xb2\x00\x00\x00\x00\x00\x01\x00\x00\x12c\ \x00\x00\x01\xd0\x00\x00\x00\x00\x00\x01\x00\x00\x13\xa5\
\x00\x00\x01\x9ey\x0c9c\ \x00\x00\x01\x9ez2\xf1\x12\
\x00\x00\x02*\x00\x00\x00\x00\x00\x01\x00\x00\x17~\ \x00\x00\x02f\x00\x00\x00\x00\x00\x01\x00\x00\x19\xb3\
\x00\x00\x01\x9ey\x0c<\x93\ \x00\x00\x01\x9ez2\xf1\x11\
\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\x00\xee\x00\x00\x00\x00\x00\x01\x00\x00\x09$\
\x00\x00\x01\x9ey\x0c1c\ \x00\x00\x01\x9e}\xa1\x91F\
\x00\x00\x01\x8e\x00\x00\x00\x00\x00\x01\x00\x00\x11Q\
\x00\x00\x01\x9ez2\xf1\x12\
\x00\x00\x00\x92\x00\x00\x00\x00\x00\x01\x00\x00\x05B\
\x00\x00\x01\x9ez2\xf1\x12\
\x00\x00\x02\x08\x00\x00\x00\x00\x00\x01\x00\x00\x15\xb6\
\x00\x00\x01\x9ez2\xf1\x11\
\x00\x00\x01\xe6\x00\x00\x00\x00\x00\x01\x00\x00\x14\xd3\
\x00\x00\x01\x9ez2\xf1\x11\
\x00\x00\x02F\x00\x00\x00\x00\x00\x01\x00\x00\x18>\
\x00\x00\x01\x9ez2\xf1\x11\
\x00\x00\x01\x0c\x00\x00\x00\x00\x00\x01\x00\x00\x0af\
\x00\x00\x01\x9ez2\xf1\x12\
\x00\x00\x00R\x00\x00\x00\x00\x00\x01\x00\x00\x03\x16\ \x00\x00\x00R\x00\x00\x00\x00\x00\x01\x00\x00\x03\x16\
\x00\x00\x01\x9ey\x0c5\xc9\ \x00\x00\x01\x9ez2\xf1\x12\
\x00\x00\x01.\x00\x00\x00\x00\x00\x01\x00\x00\x0b\x1c\ \x00\x00\x01L\x00\x00\x00\x00\x00\x01\x00\x00\x0c^\
\x00\x00\x01\x9ey\x0c00\ \x00\x00\x01\x9ez2\xf1\x12\
\x00\x00\x02@\x00\x00\x00\x00\x00\x01\x00\x00\x18\x84\ \x00\x00\x02|\x00\x00\x00\x00\x00\x01\x00\x00\x1a\xb9\
\x00\x00\x01\x9ey\x0c?\xdf\ \x00\x00\x01\x9ez2\xf1\x12\
\x00\x00\x02(\x00\x00\x00\x00\x00\x01\x00\x00\x17K\
\x00\x00\x01\x9e}\xa1\x92!\
\x00\x00\x006\x00\x00\x00\x00\x00\x01\x00\x00\x01\x05\ \x00\x00\x006\x00\x00\x00\x00\x00\x01\x00\x00\x01\x05\
\x00\x00\x01\x9ey\x0cC\xc7\ \x00\x00\x01\x9ez2\xf1\x12\
\x00\x00\x01\x8c\x00\x00\x00\x00\x00\x01\x00\x00\x11L\ \x00\x00\x01\xaa\x00\x00\x00\x00\x00\x01\x00\x00\x12\x8e\
\x00\x00\x01\x9ey\x0c8.\ \x00\x00\x01\x9ez2\xf1\x11\
\x00\x00\x01\x08\x00\x00\x00\x00\x00\x01\x00\x00\x0a:\ \x00\x00\x01&\x00\x00\x00\x00\x00\x01\x00\x00\x0b|\
\x00\x00\x01\x9ey\x0c=\xc8\ \x00\x00\x01\x9ez2\xf1\x11\
" "
def qInitResources(): def qInitResources():
+19 -9
View File
@@ -25,7 +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 icons import icon, IconRefreshMixin
from pathlib import Path from pathlib import Path
@@ -33,6 +33,7 @@ logger = logging.getLogger(__name__)
class MainWindow( class MainWindow(
IconRefreshMixin,
QMainWindow, QMainWindow,
TreeManagerMixin, TreeManagerMixin,
PdfViewerMixin, PdfViewerMixin,
@@ -141,8 +142,11 @@ 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) # Icons setzen (überschreibt fromTheme()-Icons aus _ui.py). Läuft nach
# _connect_signals(), daher existieren auch die programmatisch erzeugten Aktionen.
self._setup_icons() self._setup_icons()
# Ab hier reagiert das Fenster auf Theme-Wechsel (siehe IconRefreshMixin)
self.mark_icons_ready()
# Gespeicherte UI-Zustände wiederherstellen # Gespeicherte UI-Zustände wiederherstellen
self._restore_ui_state() self._restore_ui_state()
@@ -153,14 +157,21 @@ class MainWindow(
self.ui.actionBeenden.setIcon(icon("log-out")) self.ui.actionBeenden.setIcon(icon("log-out"))
self.ui.actionEinstellungen.setIcon(icon("settings")) self.ui.actionEinstellungen.setIcon(icon("settings"))
self.ui.actionVorhandene_Projekte.setIcon(icon("folder")) self.ui.actionVorhandene_Projekte.setIcon(icon("folder"))
self.ui.actionAlle_XML_Dateien_transformieren.setIcon(icon("play-circle"))
self.ui.actionAlle_XML_Dateien_neu_transformieren_force.setIcon(icon("refresh-cw")) self.ui.actionAlle_XML_Dateien_neu_transformieren_force.setIcon(icon("refresh-cw"))
self.ui.actionAus_Datenbank_laden.setIcon(icon("database"))
self.ui.view_ref_pdf.setIcon(icon("file")) self.ui.view_ref_pdf.setIcon(icon("file"))
self.ui.view_new_pdf.setIcon(icon("file")) self.ui.view_new_pdf.setIcon(icon("file"))
self.ui.accept_changes.setIcon(icon("check-circle")) self.ui.accept_changes.setIcon(icon("check-circle"))
if hasattr(self, "action_xsl_dependencies"): self.action_worker_metrics.setIcon(icon("activity"))
self.action_xsl_dependencies.setIcon(icon("git-branch")) self.action_xsl_dependencies.setIcon(icon("git-branch"))
if hasattr(self, "action_info"): self.action_info.setIcon(icon("info"))
self.action_info.setIcon(icon("info"))
def _on_icon_theme_changed(self):
"""Theme-Wechsel: Icons neu einfärben und falls ein Projekt offen ist die Baum-Icons."""
self._setup_icons()
if getattr(self, "pdf_project", None):
self._load_nodes_to_tree()
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)."""
@@ -358,9 +369,8 @@ 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() # Icons/Baum werden über changeEvent (PaletteChange/StyleChange) neu eingefärbt,
if hasattr(self, "pdf_project") and self.pdf_project: # siehe IconRefreshMixin._on_icon_theme_changed()
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")
+21 -2
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 icons import icon from icons import icon, IconRefreshMixin
from PySide6.QtWidgets import ( from PySide6.QtWidgets import (
QComboBox, QComboBox,
QDialog, QDialog,
@@ -120,7 +120,7 @@ except ImportError:
logger.warning("PySide6-WebEngine nicht verfügbar — Netzwerkgraph-Tab deaktiviert") logger.warning("PySide6-WebEngine nicht verfügbar — Netzwerkgraph-Tab deaktiviert")
class XslDependencyDialog(QDialog): class XslDependencyDialog(IconRefreshMixin, QDialog):
"""Dialog zur Anzeige des vollständigen XSL-Abhängigkeitsgraphen.""" """Dialog zur Anzeige des vollständigen XSL-Abhängigkeitsgraphen."""
def __init__( def __init__(
@@ -185,6 +185,25 @@ class XslDependencyDialog(QDialog):
self._build_layout_controls() self._build_layout_controls()
self._restore_graph_layout_settings() self._restore_graph_layout_settings()
# Ab hier auf Theme-Wechsel reagieren (siehe IconRefreshMixin)
self.mark_icons_ready()
def _setup_icons(self):
"""Färbt alle Icons gemäß aktuellem Theme neu ein (Button und Baum-Icons)."""
self.ui.settingsButton.setIcon(icon("sliders"))
# Datei-Baum neu einfärben, dabei die aktuelle Auswahl erhalten
current = self.ui.fileTree.currentItem()
current_path = current.data(0, Qt.ItemDataRole.UserRole) if current else None
self._populate_file_tree()
if current_path is not None:
for i in range(self.ui.fileTree.topLevelItemCount()):
item = self.ui.fileTree.topLevelItem(i)
if item.data(0, Qt.ItemDataRole.UserRole) == current_path:
# Setzt die Auswahl → _on_file_selected zeichnet den Abhängigkeitsbaum neu ein
self.ui.fileTree.setCurrentItem(item)
break
def reject(self): def reject(self):
"""Speichert Layout-Einstellungen und räumt temporäre Dateien und QWebEngineView auf.""" """Speichert Layout-Einstellungen und räumt temporäre Dateien und QWebEngineView auf."""
self._save_graph_layout_settings() self._save_graph_layout_settings()
Generated
+1 -1
View File
@@ -39,7 +39,7 @@ wheels = [
[[package]] [[package]]
name = "documentor" name = "documentor"
version = "1.7.1" version = "1.7.3"
source = { virtual = "." } source = { virtual = "." }
dependencies = [ dependencies = [
{ name = "connectorx" }, { name = "connectorx" },