diff --git a/DocuMentor.wxs b/DocuMentor.wxs index 4533845..babbb0e 100644 --- a/DocuMentor.wxs +++ b/DocuMentor.wxs @@ -4,7 +4,7 @@ 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 diff --git a/src/main.py b/src/main.py index 86f3809..1b7cdcd 100644 --- a/src/main.py +++ b/src/main.py @@ -98,6 +98,9 @@ def main(): if icon_path.exists(): app.setWindowIcon(QIcon(str(icon_path))) + # Qt-Ressourcen registrieren (Icons) + import res.resources_rc # noqa: F401 + # Hauptfenster erstellen window = MainWindow() diff --git a/src/res/icons/check-circle.svg b/src/res/icons/check-circle.svg new file mode 100644 index 0000000..f66d6fa --- /dev/null +++ b/src/res/icons/check-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/res/icons/chevron-down.svg b/src/res/icons/chevron-down.svg new file mode 100644 index 0000000..ae614b7 --- /dev/null +++ b/src/res/icons/chevron-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/res/icons/chevron-up.svg b/src/res/icons/chevron-up.svg new file mode 100644 index 0000000..37e10d0 --- /dev/null +++ b/src/res/icons/chevron-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/res/icons/code.svg b/src/res/icons/code.svg new file mode 100644 index 0000000..a793ffc --- /dev/null +++ b/src/res/icons/code.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/res/icons/columns.svg b/src/res/icons/columns.svg new file mode 100644 index 0000000..ac7c82b --- /dev/null +++ b/src/res/icons/columns.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/res/icons/file-plus.svg b/src/res/icons/file-plus.svg new file mode 100644 index 0000000..3f8e712 --- /dev/null +++ b/src/res/icons/file-plus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/res/icons/file-text.svg b/src/res/icons/file-text.svg new file mode 100644 index 0000000..8784d9f --- /dev/null +++ b/src/res/icons/file-text.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/res/icons/file.svg b/src/res/icons/file.svg new file mode 100644 index 0000000..2e2ae1d --- /dev/null +++ b/src/res/icons/file.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/res/icons/folder-plus.svg b/src/res/icons/folder-plus.svg new file mode 100644 index 0000000..50b3116 --- /dev/null +++ b/src/res/icons/folder-plus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/res/icons/folder.svg b/src/res/icons/folder.svg new file mode 100644 index 0000000..3caa511 --- /dev/null +++ b/src/res/icons/folder.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/res/icons/git-branch.svg b/src/res/icons/git-branch.svg new file mode 100644 index 0000000..126c9c5 --- /dev/null +++ b/src/res/icons/git-branch.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/res/icons/info.svg b/src/res/icons/info.svg new file mode 100644 index 0000000..4d99c59 --- /dev/null +++ b/src/res/icons/info.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/res/icons/log-out.svg b/src/res/icons/log-out.svg new file mode 100644 index 0000000..f19790d --- /dev/null +++ b/src/res/icons/log-out.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/res/icons/minus-circle.svg b/src/res/icons/minus-circle.svg new file mode 100644 index 0000000..d732c66 --- /dev/null +++ b/src/res/icons/minus-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/res/icons/play-circle.svg b/src/res/icons/play-circle.svg new file mode 100644 index 0000000..8ed76b4 --- /dev/null +++ b/src/res/icons/play-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/res/icons/plus-circle.svg b/src/res/icons/plus-circle.svg new file mode 100644 index 0000000..6b8f548 --- /dev/null +++ b/src/res/icons/plus-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/res/icons/refresh-cw.svg b/src/res/icons/refresh-cw.svg new file mode 100644 index 0000000..5c51425 --- /dev/null +++ b/src/res/icons/refresh-cw.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/res/icons/settings.svg b/src/res/icons/settings.svg new file mode 100644 index 0000000..aa78712 --- /dev/null +++ b/src/res/icons/settings.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/res/icons/sliders.svg b/src/res/icons/sliders.svg new file mode 100644 index 0000000..cc9c1f6 --- /dev/null +++ b/src/res/icons/sliders.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/res/icons/trash-2.svg b/src/res/icons/trash-2.svg new file mode 100644 index 0000000..2d9e9f5 --- /dev/null +++ b/src/res/icons/trash-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/res/resources.qrc b/src/res/resources.qrc new file mode 100644 index 0000000..ea218f5 --- /dev/null +++ b/src/res/resources.qrc @@ -0,0 +1,25 @@ + + + + icons/folder-plus.svg + icons/log-out.svg + icons/settings.svg + icons/folder.svg + icons/refresh-cw.svg + icons/plus-circle.svg + icons/minus-circle.svg + icons/play-circle.svg + icons/file.svg + icons/check-circle.svg + icons/info.svg + icons/git-branch.svg + icons/file-text.svg + icons/code.svg + icons/chevron-down.svg + icons/chevron-up.svg + icons/trash-2.svg + icons/file-plus.svg + icons/columns.svg + icons/sliders.svg + + diff --git a/src/res/resources_rc.py b/src/res/resources_rc.py new file mode 100644 index 0000000..96469e9 --- /dev/null +++ b/src/res/resources_rc.py @@ -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>\ +\ +\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=\x2217\x22 y1=\ +\x2216\x22 x2=\x2223\x22 y2=\ +\x2216\x22/>\ +\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>\ +\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>\ +\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>\ +\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>\ +\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>\ +\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>\ +\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>\ +\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>\ +\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>\ +\ +\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>\ +\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>\ +\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>\ +\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>\ +\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>\ +\ +\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>\ +\ +\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>\ +\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><\ +line x1=\x2210\x22 y1=\ +\x2211\x22 x2=\x2210\x22 y2=\ +\x2217\x22/>\ +\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>\ +" + +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() diff --git a/src/ui/AppSettings.py b/src/ui/AppSettings.py index a4b6a31..a789961 100644 --- a/src/ui/AppSettings.py +++ b/src/ui/AppSettings.py @@ -1,6 +1,7 @@ from PySide6.QtWidgets import QDialog, QTableWidgetItem, QHeaderView, QAbstractItemView from PySide6.QtCore import Qt from pathlib import Path +from icons import icon from ui.AppSettings_ui import Ui_Dialog from ui.JavaVmConfigDialog import JavaVmConfigDialog @@ -36,11 +37,21 @@ class AppSettingsDlg(QDialog): self.temp_pdf_projects = self.settings.pdf_projects.copy() self.temp_postgresql_dbs = self.settings.postgresql_dbs.copy() + self._setup_icons() self._connect_signals() self._setup_tables() self._populate_tables() 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 --- def _update_remove_button(self, table, button): diff --git a/src/ui/MainWindow.py b/src/ui/MainWindow.py index ef693bb..0d389f2 100644 --- a/src/ui/MainWindow.py +++ b/src/ui/MainWindow.py @@ -25,6 +25,7 @@ from ui.mixins import ( TransformationMixin, ) from conf import app_settings, Project, ProjectData, TreeNode, XslFile +from icons import icon from pathlib import Path @@ -140,9 +141,27 @@ class MainWindow( # Zoom per Mausrad (STRG+Mausrad) für PDF-Viewer aktivieren self._setup_scroll_area_zoom() + # Icons setzen (überschreibt fromTheme()-Icons aus _ui.py) + self._setup_icons() + # Gespeicherte UI-Zustände wiederherstellen 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): """Stellt die gespeicherten UI-Zustände wieder her (Fenstergeometrie, Splitter, TreeWidget-Spalten).""" global app_settings @@ -339,6 +358,9 @@ class MainWindow( logger.info(f"Theme erfolgreich gewechselt zu: {theme_name}") app_settings.theme = theme_name app_settings.save() + self._setup_icons() + if hasattr(self, "pdf_project") and self.pdf_project: + self._load_nodes_to_tree() else: 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) # 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.setIcon(_QIcon(_QIcon.fromTheme("view-list-tree"))) self.action_xsl_dependencies.triggered.connect(self._show_xsl_dependency_dialog) self.ui.menuAktion.addSeparator() self.ui.menuAktion.addAction(self.action_xsl_dependencies) @@ -406,7 +425,6 @@ class MainWindow( # Hilfe-Menü programmatisch erstellen self.menu_hilfe = QMenu("Hilfe", 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.menu_hilfe.addAction(self.action_info) self.ui.menubar.addMenu(self.menu_hilfe) diff --git a/src/ui/ProjectXsltParamsDialog.py b/src/ui/ProjectXsltParamsDialog.py index e44a09d..e29e366 100644 --- a/src/ui/ProjectXsltParamsDialog.py +++ b/src/ui/ProjectXsltParamsDialog.py @@ -1,5 +1,6 @@ from PySide6.QtWidgets import QDialog, QTableWidgetItem from ui.ProjectXsltParamsDialog_ui import Ui_ProjectXsltParamsDialog +from icons import icon class ProjectXsltParamsDialog(QDialog): @@ -11,6 +12,9 @@ class ProjectXsltParamsDialog(QDialog): self.ui = Ui_ProjectXsltParamsDialog() 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.removeParamButton.clicked.connect(self._remove_parameter) diff --git a/src/ui/XslDependencyDialog.py b/src/ui/XslDependencyDialog.py index 304b508..442233b 100644 --- a/src/ui/XslDependencyDialog.py +++ b/src/ui/XslDependencyDialog.py @@ -12,7 +12,7 @@ import tempfile from pathlib import Path from PySide6.QtCore import QUrl, Qt -from PySide6.QtGui import QIcon +from icons import icon from PySide6.QtWidgets import ( QComboBox, QDialog, @@ -154,6 +154,7 @@ class XslDependencyDialog(QDialog): # Sidebar initial ausblenden self.ui.sidebarWidget.setVisible(False) self.ui.mainSplitter.setSizes([1000, 0]) + self.ui.settingsButton.setIcon(icon("sliders")) self.ui.settingsButton.clicked.connect(self._toggle_sidebar) # 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.""" 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()): deps_count = len(self._full_graph.get(xsl_file, set())) @@ -260,8 +261,8 @@ class XslDependencyDialog(QDialog): rel_name = self._rel_path(xsl_file) self.ui.rightLabel.setText(f"Abhängigkeiten: {rel_name}") - import_icon = QIcon.fromTheme("go-down") - imported_by_icon = QIcon.fromTheme("go-up") + import_icon = icon("chevron-down") + imported_by_icon = icon("chevron-up") # Sektion: "Importiert" (forward dependencies) deps = self._full_graph.get(xsl_file, set()) diff --git a/src/ui/XsltParamsEditDialog.py b/src/ui/XsltParamsEditDialog.py index 02c5be9..42bcf57 100644 --- a/src/ui/XsltParamsEditDialog.py +++ b/src/ui/XsltParamsEditDialog.py @@ -1,5 +1,6 @@ from PySide6.QtWidgets import QDialog, QTableWidgetItem, QMessageBox from PySide6.QtCore import Qt +from icons import icon class XsltParamsEditDialog(QDialog): @@ -14,6 +15,9 @@ class XsltParamsEditDialog(QDialog): self.node = node 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.removeParamButton.clicked.connect(self.remove_parameter) diff --git a/src/ui/mixins/tree_manager.py b/src/ui/mixins/tree_manager.py index 1c8f531..acfdc55 100644 --- a/src/ui/mixins/tree_manager.py +++ b/src/ui/mixins/tree_manager.py @@ -15,7 +15,7 @@ from enum import Enum, auto from pathlib import Path from PySide6.QtCore import Qt -from PySide6.QtGui import QAction, QIcon +from PySide6.QtGui import QAction from PySide6.QtWidgets import ( QMenu, QTreeWidgetItem, @@ -28,6 +28,7 @@ from PySide6.QtWidgets import ( ) from conf import TreeNode, XslFile, XmlFile +from icons import icon from ui.TreeNodeEditDialog import TreeNodeEditDialog from ui.XslFileEditDialog import XslFileEditDialog from ui.XmlToXslAssignDialog import XmlToXslAssignDialog @@ -319,7 +320,7 @@ class TreeManagerMixin: if node_type == ItemType.TREE_NODE: # Kontextmenü für TreeNode 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)) font = action_edit.font() font.setBold(True) @@ -330,12 +331,12 @@ class TreeManagerMixin: menu.addSeparator() 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)) menu.addAction(action_add_child) 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)) 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)) 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.setEnabled(has_xml_files) menu.addAction(action_transform) 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.setEnabled(has_xml_files) menu.addAction(action_transform_force) @@ -364,7 +365,7 @@ class TreeManagerMixin: has_diff_pdfs = len(diff_pdfs) > 0 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.setEnabled(has_diff_pdfs) menu.addAction(action_accept_all) @@ -372,14 +373,14 @@ class TreeManagerMixin: menu.addSeparator() 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)) menu.addAction(action_delete) elif node_type == ItemType.XSL_FILE: # Kontextmenü für XslFile 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)) font = action_edit.font() font.setBold(True) @@ -390,7 +391,7 @@ class TreeManagerMixin: menu.addSeparator() 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)) menu.addAction(action_add_xml) @@ -401,13 +402,13 @@ class TreeManagerMixin: has_xml_files = bool(xsl_file_obj and xsl_file_obj.xmls) 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.setEnabled(has_xml_files) menu.addAction(action_transform) 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.setEnabled(has_xml_files) menu.addAction(action_transform_force) @@ -419,7 +420,7 @@ class TreeManagerMixin: has_diff_pdfs = len(diff_pdfs) > 0 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.setEnabled(has_diff_pdfs) menu.addAction(action_accept_all) @@ -427,21 +428,21 @@ class TreeManagerMixin: menu.addSeparator() 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)) menu.addAction(action_deps) menu.addSeparator() 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)) menu.addAction(action_delete) elif node_type == ItemType.XML_FILE: # Kontextmenü für XmlFile 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)) font = action_edit.font() font.setBold(True) @@ -453,26 +454,26 @@ class TreeManagerMixin: # Transformations-Aktionen 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)) menu.addAction(action_transform) 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)) menu.addAction(action_transform_force) menu.addSeparator() 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)) menu.addAction(action_delete) else: # Unbekannter Typ oder leerer Bereich - Menü für Root-Elemente 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()) menu.addAction(action_add_tree_node) @@ -656,17 +657,9 @@ class TreeManagerMixin: # Setze Icon basierend auf Node-Typ if isinstance(node, TreeNode): - # TreeNode: Ordner-Icon - folder_icon = QIcon.fromTheme(QIcon.ThemeIcon.FolderOpen) - if folder_icon.isNull(): - folder_icon = QIcon.fromTheme("folder") - item.setIcon(0, folder_icon) + item.setIcon(0, icon("folder")) elif isinstance(node, XslFile): - # XslFile: Code/Script-Icon für XSL-Dateien - xsl_icon = QIcon.fromTheme("text-x-script") - if xsl_icon.isNull(): - xsl_icon = QIcon.fromTheme("text-x-generic") - item.setIcon(0, xsl_icon) + item.setIcon(0, icon("file-text")) if isinstance(node, TreeNode): # 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) # Setze XML-Icon - xml_icon = QIcon.fromTheme("text-xml") - 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) + xml_item.setIcon(0, icon("code")) # Prüfe ob XML-Datei existiert und deaktiviere Knoten falls nicht # Wenn XSL-Datei fehlt, deaktiviere auch alle untergeordneten XML-Knoten @@ -812,13 +800,7 @@ class TreeManagerMixin: # Icon-Label icon_label = QLabel() - # Icon für Diff-View mit Fallbacks - 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.setPixmap(icon("columns").pixmap(16, 16)) icon_label.setToolTip("Diff-PDF vorhanden (wird automatisch geladen bei Selektion)") layout.addWidget(icon_label) diff --git a/uv.lock b/uv.lock index 27ea208..6a63f99 100644 --- a/uv.lock +++ b/uv.lock @@ -39,7 +39,7 @@ wheels = [ [[package]] name = "documentor" -version = "1.6.6" +version = "1.7.0" source = { virtual = "." } dependencies = [ { name = "connectorx" },