Build: Vollständige Windows-Distribution-Infrastruktur

Implementiert ein professionelles Build-System für Windows-Benutzer ohne Python-Installation:

PyInstaller-Integration:
- DocuMentor.spec mit automatischer Icon/Version-Einbindung
- Unterstützung für alle PySide6-UI-Dateien und Dependencies
- UPX-Kompression für kleinere Executable-Größe

Icon-System:
- create_icon.py generiert Standard-Icon oder konvertiert PNG zu ICO
- Multi-Size ICO (16x16 bis 256x256) für alle Windows-Kontexte
- Automatische Integration in Build-Prozess
- Prompts für Bild-KIs (Gemini, DALL-E, etc.)

Versionsinformationen:
- create_version_info.py liest Version aus pyproject.toml
- Windows-Datei-Eigenschaften (Rechtsklick → Details)
- Automatische Generierung bei jedem Build

Build-Automatisierung:
- build_windows.py orchestriert gesamten Build-Prozess
- Erstellt Icon und Versionsinformationen automatisch
- Generiert ZIP-Archiv für Distribution
- Cleanup alter Builds

Inno Setup-Integration:
- installer.iss für professionelle Setup.exe
- GUID-Generator (generate_guid.py)
- Desktop-Verknüpfungen und Start-Menü-Integration

Dokumentation:
- BUILD.md - Schnellstart-Anleitung
- docs/windows_distribution.md - Detaillierte Distribution-Dokumentation
- docs/icon_and_version_info.md - Icon- und Versions-System
- resources/icon_prompt.md - KI-Prompts für Icon-Generierung

Dependencies:
- pyinstaller>=6.0.0 für Executable-Erstellung
- pillow>=10.0.0 für Icon-Generierung

Externe Abhängigkeiten (Java, FOP, Saxon, diff-pdf) bleiben separat installierbar.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-04 20:37:30 +01:00
parent 6976d21768
commit bb7cad9204
18 changed files with 1903 additions and 1 deletions
+9
View File
@@ -6,5 +6,14 @@ dist/
wheels/ wheels/
*.egg-info *.egg-info
# PyInstaller
*.spec.bak
*.manifest
*.log
version_info.txt
# Generierte Icons (optional - entfernen falls Icons versioniert werden sollen)
# resources/icon.ico
# Virtual environments # Virtual environments
.venv .venv
+305
View File
@@ -0,0 +1,305 @@
# DocuMentor Build-Anleitung
## Schnellstart: Windows-Distribution erstellen
### Voraussetzungen
```bash
# Dependencies installieren (inkl. Pillow für Icon-Generierung)
uv sync --all-groups
```
### Build ausführen
```bash
# Automatischer Build (empfohlen)
uv run python build_windows.py
```
Dies erstellt automatisch:
1. **Icon** (falls nicht vorhanden): `resources/icon.ico`
2. **Versionsinformationen**: `version_info.txt`
3. **Executable**: `dist/DocuMentor/DocuMentor.exe` (mit Icon und Versionsinformationen)
4. **ZIP-Archiv**: `dist/DocuMentor-YYYYMMDD-Windows.zip`
### Icon anpassen (optional)
```bash
# Standard-Icon generieren
uv run python create_icon.py
# Oder eigenes PNG-Icon konvertieren
uv run python create_icon.py mein-logo.png
```
### Manuelle Build-Schritte
```bash
# 1. Cleanup
rm -rf build/ dist/
# 2. PyInstaller ausführen
uv run pyinstaller --clean DocuMentor.spec
# 3. Testen
# Auf Windows: dist/DocuMentor/DocuMentor.exe
# Mit Wine: wine dist/DocuMentor/DocuMentor.exe
```
## Setup.exe erstellen (optional)
### Mit Inno Setup
1. **Inno Setup installieren**: https://jrsoftware.org/isdl.php
2. **GUID generieren** für `installer.iss` (nur beim ersten Mal!):
```bash
uv run python generate_guid.py
```
Kopiere die generierte GUID und füge sie in `installer.iss` bei `AppId` ein (Zeile ~22).
**WICHTIG**: Die GUID nur EINMAL generieren! Bei Updates dieselbe GUID verwenden.
3. **Windows-Build erstellen**:
```bash
uv run python build_windows.py
```
Dies erstellt automatisch das Icon und kopiert es nach `dist/DocuMentor/`.
4. **Installer kompilieren**:
```bash
iscc installer.iss
```
5. **Ergebnis**:
- `dist/installer/DocuMentor-Setup-0.1.0.exe` (mit Icon und Versionsinformationen)
## MSI erstellen (optional)
Mit WiX Toolset - noch zu implementieren.
## Konfiguration anpassen
### Icon anpassen
**Option 1: Standard-Icon generieren**
```bash
uv run python create_icon.py
```
**Option 2: Eigenes Icon aus PNG erstellen**
```bash
uv run python create_icon.py ihr-logo.png
```
**Option 3: Manuell ICO-Datei platzieren**
1. Icon erstellen oder downloaden (`.ico` Format mit mehreren Größen)
2. Als `resources/icon.ico` speichern
3. Beim nächsten Build wird es automatisch verwendet
Das Icon wird automatisch verwendet für:
- Windows-Executable (DocuMentor.exe)
- Inno Setup Installer
- Desktop-Verknüpfungen
**Anforderungen:**
- Multi-Size ICO (16x16 bis 256x256 Pixel)
- Das `create_icon.py` Skript erstellt alle Größen automatisch
### Versionsinformationen
**Automatische Generierung:**
Versionsinformationen werden automatisch aus `pyproject.toml` generiert:
```bash
uv run python create_version_info.py
```
Dies liest die Version aus `pyproject.toml` und erstellt `version_info.txt`.
**Version ändern:**
In `pyproject.toml`:
```toml
version = "0.2.0"
```
Auch aktualisieren in:
- `installer.iss` (Zeile 13: `#define MyAppVersion`)
Dann Versionsinformationen neu generieren:
```bash
uv run python create_version_info.py
```
**Was enthalten die Versionsinformationen:**
- Dateiversion und Produktversion
- Beschreibung und Copyright
- Anwendungsname
- Wird in Windows Explorer angezeigt (Rechtsklick → Eigenschaften → Details)
### Build-Größe reduzieren
In `DocuMentor.spec` Module ausschließen:
```python
excludes=[
'tkinter',
'matplotlib',
'test',
'unittest',
],
```
### One-File Build (alles in einer .exe)
In `DocuMentor.spec` ändern:
```python
exe = EXE(
pyz,
a.scripts,
a.binaries, # Uncomment
a.zipfiles, # Uncomment
a.datas, # Uncomment
[], # Comment out
exclude_binaries=False, # Ändern
# ...
name='DocuMentor',
onefile=True, # Hinzufügen
)
# COLLECT auskommentieren oder entfernen
```
**Achtung**: One-File ist langsamer beim Start (3-5 Sekunden).
## Testing
### Lokales Testing
```bash
# Build erstellen
uv run python build_windows.py
# Mit Wine testen (Linux/WSL)
wine dist/DocuMentor/DocuMentor.exe
```
### Testing auf Windows
1. ZIP-Datei auf Windows-System kopieren
2. Entpacken
3. `DocuMentor.exe` starten
4. Features testen:
- [ ] Programmstart
- [ ] Einstellungsdialog öffnet beim ersten Start
- [ ] Projekt öffnen/erstellen
- [ ] Tree-Navigation
- [ ] XSL/XML-Dateien hinzufügen
- [ ] PDF-Generierung (mit konfigurierten Tools)
- [ ] PDF-Vergleich
## Troubleshooting
### "Module not found" beim Start
**Lösung**: Hidden imports in `DocuMentor.spec` ergänzen:
```python
hiddenimports=[
'missing.module',
]
```
### Antivirus blockiert die .exe
**Ursache**: Unsigned executables werden oft als verdächtig eingestuft.
**Lösungen**:
1. Code-Signing-Zertifikat kaufen und verwenden
2. Bei Microsoft SmartScreen einreichen
3. Exception in Antivirus eintragen (für Tests)
### Executable ist zu groß (>200 MB)
**Lösungen**:
1. UPX-Kompression ist bereits aktiv
2. Ungenutzte Module excluden (siehe oben)
3. Virtual Environment aufräumen: `uv sync --no-dev`
### UI-Dateien nicht gefunden
**Problem**: `.ui` Dateien werden nicht gefunden.
**Lösung**: In `DocuMentor.spec` prüfen:
```python
datas=ui_files, # Muss gesetzt sein
```
## Automatisierung
### GitHub Actions (CI/CD)
Siehe `docs/windows_distribution.md` für vollständiges Beispiel.
### Lokales Release-Skript
```bash
#!/bin/bash
# release.sh - Erstellt vollständiges Release
VERSION="0.1.0"
echo "Building DocuMentor v$VERSION..."
# 1. Build
uv run python build_windows.py
# 2. Installer (falls Inno Setup installiert)
if command -v iscc &> /dev/null; then
iscc installer.iss
echo "✓ Installer erstellt"
fi
echo ""
echo "Release v$VERSION fertig!"
echo " • ZIP: dist/DocuMentor-*-Windows.zip"
echo " • Setup: dist/installer/DocuMentor-Setup-$VERSION.exe"
```
## Distribution
### ZIP-Archiv
**Vorteile:**
- Einfach, portable
- Keine Installation nötig
- USB-Stick-fähig
**Verwendung:**
- Auf GitHub Releases hochladen
- Per E-Mail versenden
- Auf Webserver bereitstellen
### Setup.exe
**Vorteile:**
- Professionell
- Start-Menü-Integration
- Deinstallation
**Verwendung:**
- Primäre Distributions-Methode
- Auf Website zum Download anbieten
## Dokumentation für Endbenutzer
Die `dist/DocuMentor/README.txt` wird automatisch erstellt und enthält:
- Installationsanweisungen
- Liste der externen Abhängigkeiten
- Konfigurationshinweise
## Weitere Informationen
Siehe `docs/windows_distribution.md` für detaillierte Dokumentation.
+79
View File
@@ -0,0 +1,79 @@
# -*- mode: python ; coding: utf-8 -*-
"""
PyInstaller Konfiguration für DocuMentor
Erstellt eine eigenständige Windows-Executable ohne Python-Installation
"""
import sys
from pathlib import Path
block_cipher = None
# Projektpfad
project_root = Path(SPECPATH)
src_path = project_root / 'src'
# Alle UI-Dateien sammeln
ui_files = []
for ui_file in (src_path / 'ui').glob('*.ui'):
ui_files.append((str(ui_file), 'ui'))
a = Analysis(
[str(src_path / 'main.py')],
pathex=[str(src_path)],
binaries=[],
datas=ui_files, # UI-Dateien einbinden
hiddenimports=[
'PySide6.QtCore',
'PySide6.QtGui',
'PySide6.QtWidgets',
'pydantic',
'pydantic_settings',
'pydantic_yaml',
'polars',
'pyarrow',
'connectorx',
'pyqtdarktheme',
],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
exe = EXE(
pyz,
a.scripts,
[],
exclude_binaries=True,
name='DocuMentor',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=False, # Keine Konsole anzeigen (GUI-Anwendung)
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon=str(project_root / 'resources' / 'icon.ico') if (project_root / 'resources' / 'icon.ico').exists() else None,
version=str(project_root / 'version_info.txt') if (project_root / 'version_info.txt').exists() else None,
)
coll = COLLECT(
exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='DocuMentor',
)
+141
View File
@@ -0,0 +1,141 @@
#!/usr/bin/env python3
"""
Build-Skript für Windows-Distribution von DocuMentor
Erstellt:
1. Eigenständige Executable mit PyInstaller
2. Optional: ZIP-Archiv für portable Distribution
"""
import shutil
import subprocess
import sys
from pathlib import Path
from datetime import datetime
def main():
project_root = Path(__file__).parent
dist_dir = project_root / "dist"
build_dir = project_root / "build"
resources_dir = project_root / "resources"
icon_path = resources_dir / "icon.ico"
version_info_path = project_root / "version_info.txt"
print("=" * 60)
print("DocuMentor Windows Build")
print("=" * 60)
# 1. Icon und Versionsinformationen generieren
print("\n[1/6] Icon und Versionsinformationen generieren...")
# Icon erstellen falls nicht vorhanden
if not icon_path.exists():
print(" Erstelle Standard-Icon...")
try:
subprocess.run([sys.executable, "create_icon.py"], check=True, cwd=project_root)
print(" ✓ Icon erstellt")
except subprocess.CalledProcessError as e:
print(f" ✗ Icon-Erstellung fehlgeschlagen: {e}")
print(" ⚠ Fahre ohne Icon fort...")
else:
print(f" ✓ Icon vorhanden: {icon_path.name}")
# Versionsinformationen erstellen
print(" Erstelle Versionsinformationen...")
try:
subprocess.run([sys.executable, "create_version_info.py"], check=True, cwd=project_root)
print(" ✓ Versionsinformationen erstellt")
except subprocess.CalledProcessError as e:
print(f" ✗ Versionsinformationen-Erstellung fehlgeschlagen: {e}")
print(" ⚠ Fahre ohne Versionsinformationen fort...")
# 2. Cleanup alter Builds
print("\n[2/6] Cleanup alter Builds...")
if dist_dir.exists():
shutil.rmtree(dist_dir)
print(" ✓ dist/ gelöscht")
if build_dir.exists():
shutil.rmtree(build_dir)
print(" ✓ build/ gelöscht")
# 3. PyInstaller ausführen
print("\n[3/6] PyInstaller Build starten...")
try:
subprocess.run(
["pyinstaller", "--clean", "DocuMentor.spec"],
check=True,
cwd=project_root
)
print(" ✓ Build erfolgreich")
except subprocess.CalledProcessError as e:
print(f" ✗ Build fehlgeschlagen: {e}")
return 1
# 4. README für Distribution erstellen
print("\n[4/6] README erstellen...")
readme_content = """DocuMentor - XSL-Transformations-Verwaltung
============================================
Installation:
1. Entpacken Sie dieses Archiv in ein Verzeichnis Ihrer Wahl
2. Führen Sie DocuMentor.exe aus
Externe Abhängigkeiten (separat zu installieren):
- Java Runtime Environment (JRE) oder JDK
- Apache FOP (für PDF-Generierung)
- Saxon XSLT-Prozessor (JAR-Datei)
- diff-pdf (für PDF-Vergleiche)
Beim ersten Start werden Sie aufgefordert, die Pfade zu diesen
Tools in den Programmeinstellungen zu konfigurieren.
Konfiguration und Logs:
- Windows: %APPDATA%\\DocuMentor\\
- Konfiguration: config.json
- Logs: logs\\
Support:
Bei Fragen oder Problemen erstellen Sie bitte ein Issue auf GitHub.
"""
readme_path = dist_dir / "DocuMentor" / "README.txt"
readme_path.write_text(readme_content, encoding='utf-8')
print(" ✓ README.txt erstellt")
# 5. Icon ins dist-Verzeichnis kopieren (für Installer)
print("\n[5/6] Icon für Installer vorbereiten...")
if icon_path.exists():
dist_icon = dist_dir / "DocuMentor" / "icon.ico"
shutil.copy2(icon_path, dist_icon)
print(" ✓ Icon kopiert")
else:
print(" ⚠ Kein Icon vorhanden")
# 6. ZIP-Archiv erstellen
print("\n[6/6] ZIP-Archiv erstellen...")
timestamp = datetime.now().strftime("%Y%m%d")
zip_name = f"DocuMentor-{timestamp}-Windows"
zip_path = dist_dir / zip_name
shutil.make_archive(
str(zip_path),
'zip',
dist_dir,
'DocuMentor'
)
print(f"{zip_name}.zip erstellt")
print("\n" + "=" * 60)
print("Build abgeschlossen!")
print("=" * 60)
print(f"\nErgebnisse:")
print(f" • Executable: dist/DocuMentor/DocuMentor.exe")
print(f" • ZIP-Archiv: dist/{zip_name}.zip")
print("\nNächste Schritte:")
print(" 1. Testen Sie DocuMentor.exe auf einem Windows-System")
print(" 2. Optional: Erstellen Sie einen Installer mit Inno Setup")
return 0
if __name__ == "__main__":
sys.exit(main())
+164
View File
@@ -0,0 +1,164 @@
#!/usr/bin/env python3
"""
Icon-Generator für DocuMentor
Erstellt ein Icon aus einem PNG oder generiert ein Standard-Icon.
Unterstützt Windows (.ico) und verschiedene Größen.
Verwendung:
python create_icon.py # Generiert Standard-Icon
python create_icon.py source.png # Konvertiert PNG zu ICO
"""
import sys
from pathlib import Path
try:
from PIL import Image, ImageDraw, ImageFont
except ImportError:
print("Fehler: Pillow ist nicht installiert.")
print("Installation: uv pip install pillow")
sys.exit(1)
def create_default_icon(output_path: Path):
"""Erstellt ein Standard-Icon mit DocuMentor-Branding."""
sizes = [256, 128, 64, 48, 32, 16]
images = []
for size in sizes:
# Neues Bild erstellen mit Farbverlauf
img = Image.new('RGB', (size, size), color='white')
draw = ImageDraw.Draw(img)
# Hintergrund: Blau-Verlauf (vereinfacht als solides Blau)
bg_color = (41, 128, 185) # Professionelles Blau
draw.rectangle([0, 0, size, size], fill=bg_color)
# Dokument-Symbol (vereinfachte Darstellung)
margin = size // 8
doc_left = margin
doc_top = margin
doc_right = size - margin
doc_bottom = size - margin
# Weißes Dokument
draw.rectangle(
[doc_left, doc_top, doc_right, doc_bottom],
fill='white',
outline=(52, 73, 94),
width=max(1, size // 64)
)
# Ecke umgeknickt (rechts oben)
fold_size = size // 6
points = [
(doc_right - fold_size, doc_top),
(doc_right, doc_top + fold_size),
(doc_right - fold_size, doc_top + fold_size),
]
draw.polygon(points, fill=(220, 220, 220), outline=(52, 73, 94))
# Text-Linien im Dokument (nur bei größeren Icons)
if size >= 32:
line_margin = doc_left + size // 12
line_width = doc_right - doc_left - size // 6
line_count = min(3, size // 32)
line_spacing = (doc_bottom - doc_top - fold_size) // (line_count + 2)
for i in range(line_count):
y = doc_top + fold_size + line_spacing * (i + 1)
draw.rectangle(
[line_margin, y, line_margin + line_width, y + max(1, size // 128)],
fill=(52, 73, 94)
)
# "M" für Mentor (nur bei großen Icons)
if size >= 64:
try:
# Versuche System-Font zu verwenden
font_size = size // 4
font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", font_size)
except:
# Fallback auf Default-Font
font = ImageFont.load_default()
text = "M"
# Zentrieren (grobe Schätzung)
bbox = draw.textbbox((0, 0), text, font=font)
text_width = bbox[2] - bbox[0]
text_height = bbox[3] - bbox[1]
text_x = (size - text_width) // 2
text_y = doc_bottom - text_height - margin // 2
draw.text((text_x, text_y), text, fill=bg_color, font=font)
images.append(img)
# Als ICO speichern
images[0].save(
output_path,
format='ICO',
sizes=[(img.width, img.height) for img in images],
append_images=images[1:]
)
print(f"✓ Standard-Icon erstellt: {output_path}")
def convert_png_to_ico(source_path: Path, output_path: Path):
"""Konvertiert ein PNG-Bild zu einem Multi-Size ICO."""
try:
img = Image.open(source_path)
# Zu RGBA konvertieren falls nötig
if img.mode != 'RGBA':
img = img.convert('RGBA')
# Verschiedene Größen erstellen
sizes = [256, 128, 64, 48, 32, 16]
images = []
for size in sizes:
resized = img.resize((size, size), Image.Resampling.LANCZOS)
images.append(resized)
# Als ICO speichern
images[0].save(
output_path,
format='ICO',
sizes=[(img.width, img.height) for img in images],
append_images=images[1:]
)
print(f"✓ Icon erstellt aus {source_path.name}: {output_path}")
except Exception as e:
print(f"✗ Fehler beim Konvertieren: {e}")
sys.exit(1)
def main():
project_root = Path(__file__).parent
resources_dir = project_root / "resources"
resources_dir.mkdir(exist_ok=True)
output_ico = resources_dir / "icon.ico"
if len(sys.argv) > 1:
# PNG zu ICO konvertieren
source_path = Path(sys.argv[1])
if not source_path.exists():
print(f"Fehler: Datei nicht gefunden: {source_path}")
sys.exit(1)
convert_png_to_ico(source_path, output_ico)
else:
# Standard-Icon generieren
print("Erstelle Standard-Icon...")
create_default_icon(output_ico)
print(f"\nIcon gespeichert: {output_ico}")
print("Das Icon wird automatisch von PyInstaller und Inno Setup verwendet.")
if __name__ == "__main__":
main()
+102
View File
@@ -0,0 +1,102 @@
#!/usr/bin/env python3
"""
Generiert Windows-Versionsinformationen für PyInstaller
Liest Version aus pyproject.toml und erstellt version_info.txt
"""
import tomllib
from pathlib import Path
from datetime import datetime
def parse_version(version_str: str) -> tuple[int, int, int, int]:
"""Parst Version-String (z.B. '0.1.0') zu Tuple (0, 1, 0, 0)."""
parts = version_str.split('.')
major = int(parts[0]) if len(parts) > 0 else 0
minor = int(parts[1]) if len(parts) > 1 else 0
patch = int(parts[2]) if len(parts) > 2 else 0
build = 0 # Könnte aus Git-Commit-Count generiert werden
return (major, minor, patch, build)
def create_version_info(project_root: Path):
"""Erstellt version_info.txt für PyInstaller."""
# pyproject.toml lesen
pyproject_path = project_root / "pyproject.toml"
with open(pyproject_path, 'rb') as f:
pyproject = tomllib.load(f)
project = pyproject['project']
version = project['version']
name = project['name']
description = project['description']
# Version parsen
file_version = parse_version(version)
product_version = file_version
# Jahr für Copyright
year = datetime.now().year
# version_info.txt Content
version_info_content = f"""# UTF-8
#
# Generiert automatisch von create_version_info.py
# NICHT manuell bearbeiten!
#
VSVersionInfo(
ffi=FixedFileInfo(
# filevers und prodvers als Tuple: (1, 0, 0, 0)
filevers={file_version},
prodvers={product_version},
# Maske für gültige Bits in filevers und prodvers
mask=0x3f,
# Flags - kann VS_FF_DEBUG, VS_FF_PRERELEASE, etc. enthalten
flags=0x0,
# Betriebssystem - VOS_NT_WINDOWS32
OS=0x40004,
# Dateityp - VFT_APP (Anwendung)
fileType=0x1,
# Subtyp (nicht verwendet für VFT_APP)
subtype=0x0,
# Datumsstempel
date=(0, 0)
),
kids=[
StringFileInfo(
[
StringTable(
'040904B0', # Deutsch (0x0409 = Englisch, 0x0407 = Deutsch), Unicode
[StringStruct('CompanyName', 'Ihr Name/Organisation'),
StringStruct('FileDescription', '{description}'),
StringStruct('FileVersion', '{version}'),
StringStruct('InternalName', '{name}'),
StringStruct('LegalCopyright', '© {year} Ihr Name. Alle Rechte vorbehalten.'),
StringStruct('OriginalFilename', '{name}.exe'),
StringStruct('ProductName', '{name}'),
StringStruct('ProductVersion', '{version}')])
]),
VarFileInfo([VarStruct('Translation', [1033, 1200])]) # Englisch, Unicode
]
)
"""
# version_info.txt schreiben
version_info_path = project_root / "version_info.txt"
version_info_path.write_text(version_info_content, encoding='utf-8')
print(f"✓ version_info.txt erstellt")
print(f" Version: {version}")
print(f" Datei: {version_info_path}")
def main():
project_root = Path(__file__).parent
create_version_info(project_root)
if __name__ == "__main__":
main()
+274
View File
@@ -0,0 +1,274 @@
# Icon und Versionsinformationen für Windows-Build
## Übersicht
DocuMentor unterstützt professionelle Windows-Builds mit:
- **Anwendungs-Icon** in allen benötigten Größen
- **Windows-Versionsinformationen** (Datei-Eigenschaften)
- Automatische Integration in Build-Prozess
## Icon-System
### Automatische Icon-Generierung
Das Build-Skript generiert automatisch ein Standard-Icon, falls keins vorhanden ist:
```bash
uv run python build_windows.py
```
Falls `resources/icon.ico` nicht existiert, wird automatisch ein Standard-Icon mit DocuMentor-Branding erstellt.
### Manuelles Icon erstellen
#### Option 1: Standard-Icon
```bash
uv run python create_icon.py
```
Erstellt ein einfaches Icon mit:
- Blauem Hintergrund (professionelles Blau: #2980B9)
- Weißem Dokument-Symbol
- "M" für Mentor (bei großen Icons)
- Umgeknickter Ecke
- Mehreren Größen (16×16 bis 256×256)
#### Option 2: Aus eigenem PNG
```bash
uv run python create_icon.py mein-logo.png
```
Konvertiert ein PNG-Bild zu einem Multi-Size Windows-Icon:
- Unterstützt Transparenz
- Erstellt alle benötigten Größen
- Optimiert für verschiedene Bildschirmauflösungen
**PNG-Anforderungen:**
- Idealerweise 256×256 Pixel oder größer
- Quadratisches Format
- PNG oder JPEG Format
- Transparenter Hintergrund empfohlen
### Icon-Größen
Das ICO-Format enthält folgende Auflösungen:
| Größe | Verwendung |
|---------|--------------------------------------|
| 256×256 | Windows 7+, Taskleiste, große Icons |
| 128×128 | Windows 7+, große Icons |
| 64×64 | Hohe DPI-Displays |
| 48×48 | Standard Desktop-Icon |
| 32×32 | Explorer Details-Ansicht |
| 16×16 | Kleinstes Icon, Titelleiste |
### Wo wird das Icon verwendet?
- **DocuMentor.exe** - Anwendungs-Icon
- **Setup.exe** - Installer-Icon (Inno Setup)
- **Desktop-Verknüpfung** - Erstellt beim Installieren
- **Start-Menü** - Windows-Programmgruppe
- **Taskleiste** - Beim Ausführen
- **Deinstallations-Programm** - System-Einstellungen
## Versionsinformationen
### Automatische Generierung
Versionsinformationen werden automatisch vom Build-Skript generiert:
```bash
uv run python build_windows.py
```
### Manuelle Generierung
```bash
uv run python create_version_info.py
```
### Inhalt der Versionsinformationen
Die `version_info.txt` enthält:
```
FileVersion: 0.1.0.0
ProductVersion: 0.1.0.0
CompanyName: Ihr Name/Organisation
FileDescription: Professionelle XSL-Transformations-Verwaltung und PDF-Generierung
InternalName: DocuMentor
LegalCopyright: © 2026 Ihr Name. Alle Rechte vorbehalten.
OriginalFilename: DocuMentor.exe
ProductName: DocuMentor
```
### Version aus pyproject.toml
Die Version wird automatisch aus `pyproject.toml` gelesen:
```toml
[project]
name = "DocuMentor"
version = "0.1.0"
description = "Professionelle XSL-Transformations-Verwaltung und PDF-Generierung"
```
### Version ändern
**Schritt 1:** Version in `pyproject.toml` ändern:
```toml
version = "0.2.0"
```
**Schritt 2:** Version in `installer.iss` ändern (Zeile 13):
```iss
#define MyAppVersion "0.2.0"
```
**Schritt 3:** Build neu ausführen:
```bash
uv run python build_windows.py
```
Die Versionsinformationen werden automatisch neu generiert.
### Versionsnummern-Schema
DocuMentor verwendet [Semantic Versioning](https://semver.org/lang/de/):
```
MAJOR.MINOR.PATCH
0.1.0 → Erste Beta-Version
1.0.0 → Erste stabile Version
1.1.0 → Neue Features
1.1.1 → Bugfixes
2.0.0 → Breaking Changes
```
### Windows-Eigenschaften anzeigen
Nach dem Build können Sie die Versionsinformationen in Windows anzeigen:
1. Rechtsklick auf `DocuMentor.exe`
2. **Eigenschaften** auswählen
3. Tab **Details** öffnen
Dort sehen Sie:
- Dateiversion
- Produktversion
- Beschreibung
- Copyright
- Produktname
- Original-Dateiname
## Integration in Build-Prozess
### DocuMentor.spec
```python
exe = EXE(
# ...
icon=str(project_root / 'resources' / 'icon.ico') if (project_root / 'resources' / 'icon.ico').exists() else None,
version=str(project_root / 'version_info.txt') if (project_root / 'version_info.txt').exists() else None,
)
```
**Automatische Erkennung:**
- Icon wird verwendet, falls vorhanden
- Versionsinformationen werden verwendet, falls vorhanden
- Build funktioniert auch ohne Icon/Version (mit Warnung)
### installer.iss
```iss
SetupIconFile=dist\DocuMentor\icon.ico
UninstallDisplayIcon={app}\DocuMentor.exe
```
Das Icon wird automatisch vom `build_windows.py` nach `dist/DocuMentor/` kopiert.
## Anpassungen
### Company Name / Copyright
In `create_version_info.py` (Zeile ~65):
```python
StringStruct('CompanyName', 'Ihr Name/Organisation'),
StringStruct('LegalCopyright', '© {year} Ihr Name. Alle Rechte vorbehalten.'),
```
Ändern Sie "Ihr Name/Organisation" auf Ihren tatsächlichen Namen oder Firmennamen.
### Icon-Design
Falls Sie das Standard-Icon anpassen möchten, bearbeiten Sie `create_icon.py`:
**Farben ändern** (Zeile ~31):
```python
bg_color = (41, 128, 185) # Blau - ändern Sie RGB-Werte
```
**Symbol ändern:**
- Bearbeiten Sie die `create_default_icon()` Funktion
- Oder erstellen Sie Ihr eigenes Icon in einem Grafikprogramm
## Best Practices
### Icon-Design
1. **Einfach und klar**: Funktioniert auch bei 16×16 Pixel
2. **Hoher Kontrast**: Gut lesbar auf hellem und dunklem Hintergrund
3. **Professionell**: Passend zum Business-Kontext
4. **Wiedererkennbar**: Symbolisiert die Anwendung
### Versionierung
1. **Semantische Versionierung**: MAJOR.MINOR.PATCH
2. **Vor jedem Release aktualisieren**
3. **Git-Tags verwenden**: `git tag v0.1.0`
4. **GUID beibehalten**: Nie die Inno Setup GUID ändern bei Updates!
## Troubleshooting
### Icon wird nicht angezeigt
**Problem**: DocuMentor.exe zeigt kein Icon
**Lösungen:**
1. Prüfen ob `resources/icon.ico` existiert
2. Build neu ausführen: `uv run python build_windows.py`
3. Windows Icon-Cache löschen und neu starten
### Versionsinformationen fehlen
**Problem**: Eigenschaften → Details zeigt keine Informationen
**Lösungen:**
1. Prüfen ob `version_info.txt` existiert
2. `uv run python create_version_info.py` ausführen
3. Build neu ausführen
### Pillow-Fehler beim Icon-Erstellen
**Problem**: `ImportError: No module named 'PIL'`
**Lösung:**
```bash
uv sync --all-groups
```
Dies installiert Pillow automatisch.
## Weiterführende Informationen
- **PyInstaller Icon-Dokumentation**: https://pyinstaller.org/en/stable/usage.html#icons
- **Windows ICO Format**: https://en.wikipedia.org/wiki/ICO_(file_format)
- **Semantic Versioning**: https://semver.org/lang/de/
- **Pillow Dokumentation**: https://pillow.readthedocs.io/
+291
View File
@@ -0,0 +1,291 @@
# Windows Distribution Guide für DocuMentor
## Überblick
Dieses Dokument beschreibt, wie DocuMentor für Windows-Benutzer ohne Python-Installation verpackt wird.
## Voraussetzungen
### Auf dem Entwicklungssystem
```bash
# Dependencies installieren (inkl. PyInstaller)
uv sync --all-groups
```
### Für Setup.exe (optional)
- **Inno Setup**: Download von https://jrsoftware.org/isdl.php
- Oder **WiX Toolset** für MSI: https://wixtoolset.org/
## Build-Prozess
### Option 1: Einfacher Build (ZIP-Distribution)
```bash
# 1. PyInstaller installieren
uv sync --all-groups
# 2. Build ausführen
uv run python build_windows.py
```
Dies erstellt:
- `dist/DocuMentor/DocuMentor.exe` - Eigenständige Executable
- `dist/DocuMentor-YYYYMMDD-Windows.zip` - Portable ZIP-Archiv
### Option 2: Professionelle Setup.exe mit Inno Setup
```bash
# 1. PyInstaller Build
uv run python build_windows.py
# 2. Inno Setup Compiler ausführen
iscc installer.iss
```
Dies erstellt:
- `dist/installer/DocuMentor-Setup-0.1.0.exe` - Professioneller Installer
### Option 3: MSI-Installer mit WiX
```bash
# TODO: WiX-Konfiguration noch zu erstellen
```
## Manuelle Schritte
### 1. PyInstaller direkt verwenden
```bash
# Cleanup
rm -rf build/ dist/
# Build
uv run pyinstaller --clean DocuMentor.spec
# Testen
dist/DocuMentor/DocuMentor.exe
```
### 2. Anpassungen vornehmen
**Icon hinzufügen:**
1. Icon-Datei (`.ico`) im Projekt speichern, z.B. `resources/icon.ico`
2. In `DocuMentor.spec` anpassen:
```python
icon='resources/icon.ico'
```
**Versionsinformationen:**
In `DocuMentor.spec` erweitern:
```python
exe = EXE(
# ...
version='version_info.txt', # Windows-Versionsinformationen
)
```
## PyInstaller .spec Konfiguration
Die Datei `DocuMentor.spec` enthält:
- **datas**: UI-Dateien (.ui) werden mitgepackt
- **hiddenimports**: Alle notwendigen PySide6/Polars-Module
- **console=False**: GUI-Anwendung ohne Konsole
- **upx=True**: Kompression der Binaries
### Wichtige Einstellungen
```python
# Ein-Datei-Build (alles in einer .exe)
exe = EXE(
pyz,
a.scripts,
a.binaries, # Diese Zeilen
a.zipfiles, # auskommentieren
a.datas, # für One-File
# ...
onefile=True, # Hinzufügen
)
```
**Achtung**: One-File-Build ist langsamer beim Start, da alles temporär entpackt werden muss.
## Distribution
### ZIP-Archive
```bash
# Automatisch durch build_windows.py erstellt
dist/DocuMentor-YYYYMMDD-Windows.zip
```
**Vorteile:**
- Einfach, portable
- Keine Installation nötig
- Kann auf USB-Stick verwendet werden
**Nachteile:**
- Keine Deinstallationsroutine
- Keine Verknüpfungen
- Keine Registry-Einträge
### Setup.exe mit Inno Setup
**Vorteile:**
- Professionell
- Deinstallation integriert
- Start-Menü und Desktop-Icons
- Update-Mechanismus möglich
**Nachteile:**
- Benötigt Administrator-Rechte (optional)
- Komplexere Konfiguration
### MSI-Installer
**Vorteile:**
- Windows-Standard
- Gruppen-Richtlinien-fähig
- Silent Installation möglich
**Nachteile:**
- Komplexe Erstellung
- Benötigt WiX Toolset
## Externe Abhängigkeiten
DocuMentor benötigt diese Tools (NICHT im Installer enthalten):
1. **Java Runtime Environment (JRE) 11+**
- Für Saxon und Apache FOP
- Download: https://adoptium.net/
2. **Apache FOP**
- XSL-FO zu PDF Konvertierung
- Download: https://xmlgraphics.apache.org/fop/
3. **Saxon XSLT Prozessor**
- XSLT 2.0/3.0 Transformationen
- Download: https://www.saxonica.com/
4. **diff-pdf**
- PDF-Vergleich
- Download: https://vslavik.github.io/diff-pdf/
### Benutzer-Anleitung
Nach der Installation:
1. DocuMentor starten
2. Beim ersten Start öffnet sich automatisch die Einstellungen
3. Pfade zu Java, Saxon, FOP und diff-pdf konfigurieren
4. Projekt-Verzeichnis wählen oder neues Projekt erstellen
## Testing
### Lokales Testing (Linux/WSL)
```bash
# Build für Windows erstellen
uv run python build_windows.py
# Executable mit Wine testen (falls verfügbar)
wine dist/DocuMentor/DocuMentor.exe
```
### Testing auf Windows
1. ZIP auf Windows-System kopieren
2. Entpacken
3. `DocuMentor.exe` ausführen
4. Alle Features testen:
- Projekt öffnen/erstellen
- Tree-Navigation
- PDF-Generierung
- Einstellungen
## Troubleshooting
### Problem: "Module not found" Fehler
**Lösung**: Hidden imports in `DocuMentor.spec` ergänzen:
```python
hiddenimports=[
# ... existing
'missing_module',
]
```
### Problem: UI-Dateien nicht gefunden
**Lösung**: Prüfen ob datas korrekt konfiguriert:
```python
datas=[
('src/ui/*.ui', 'ui'),
]
```
### Problem: Executable zu groß
**Lösungen**:
1. UPX-Kompression aktivieren (bereits aktiv)
2. Excludes hinzufügen für ungenutzte Module:
```python
excludes=['tkinter', 'matplotlib', 'test', 'unittest']
```
3. One-File-Build verwenden (langsamer Start)
### Problem: Antivirus blockiert
**Lösung**:
- Code-Signing-Zertifikat verwenden
- Bei Microsoft einreichen für SmartScreen
- README mit Hinweis erweitern
## Automatisierung mit CI/CD
### GitHub Actions Beispiel
```yaml
name: Build Windows Release
on:
push:
tags:
- 'v*'
jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
- name: Install uv
uses: astral-sh/setup-uv@v1
- name: Build
run: uv run python build_windows.py
- name: Create Release
uses: softprops/action-gh-release@v1
with:
files: dist/*.zip
```
## Versionierung
Version in folgenden Dateien aktualisieren:
1. `pyproject.toml` - `version = "X.Y.Z"`
2. `installer.iss` - `#define MyAppVersion "X.Y.Z"`
3. Optional: `src/version.py` erstellen
## Lizenz und Rechtliches
- Alle Python-Dependencies sind in der Distribution enthalten
- PySide6 (LGPL): Dynamische Verlinkung ist OK
- Polars (MIT): Unproblematisch
- Pydantic (MIT): Unproblematisch
Externe Tools (Saxon, FOP) haben eigene Lizenzen und müssen separat installiert werden.
+41
View File
@@ -0,0 +1,41 @@
#!/usr/bin/env python3
"""
GUID-Generator für Inno Setup
Generiert eine eindeutige GUID für die AppId in installer.iss
"""
import uuid
import sys
def main():
# GUID generieren
guid = uuid.uuid4()
guid_str = f"{{{{{str(guid).upper()}}}}}"
print("=" * 60)
print("GUID für Inno Setup AppId")
print("=" * 60)
print()
print("Generierte GUID:")
print(f" {guid_str}")
print()
print("Anleitung:")
print("1. Kopieren Sie die GUID oben")
print("2. Öffnen Sie installer.iss")
print("3. Suchen Sie nach 'AppId={{' (Zeile ~22)")
print("4. Ersetzen Sie die Beispiel-GUID mit Ihrer neuen GUID")
print()
print("Beispiel:")
print(f" AppId={guid_str}")
print()
print("WICHTIG:")
print("- Die GUID sollte nur EINMAL beim ersten Setup generiert werden")
print("- Ändern Sie die GUID NICHT bei Updates, sonst wird die App")
print(" als separate Anwendung installiert!")
print("=" * 60)
if __name__ == "__main__":
main()
+73
View File
@@ -0,0 +1,73 @@
; Inno Setup Konfiguration für DocuMentor
; Erstellt eine professionelle Setup.exe für Windows
;
; Installation von Inno Setup: https://jrsoftware.org/isdl.php
;
; WICHTIG: Vor dem ersten Build GUID generieren!
; python -c "import uuid; print(f'{{{{' + str(uuid.uuid4()).upper() + '}}}}')"
; Ergebnis in AppId unten einfügen
;
; Build-Befehl: iscc installer.iss
#define MyAppName "DocuMentor"
#define MyAppVersion "0.1.0"
#define MyAppPublisher "Ihr Name/Organisation"
#define MyAppURL "https://github.com/yourusername/xsl-validator"
#define MyAppExeName "DocuMentor.exe"
[Setup]
; Basis-Informationen
; WICHTIG: Ersetzen Sie die GUID mit einer eigenen generierten GUID!
; AppId={{BEISPIEL-GUID-HIER-EINFÜGEN}}
AppId={{A1B2C3D4-E5F6-4789-ABCD-EF0123456789}}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
; Installation
DefaultDirName={autopf}\{#MyAppName}
DefaultGroupName={#MyAppName}
AllowNoIcons=yes
; Output
OutputDir=dist\installer
OutputBaseFilename=DocuMentor-Setup-{#MyAppVersion}
SetupIconFile=dist\DocuMentor\icon.ico
UninstallDisplayIcon={app}\{#MyAppExeName}
; Kompression
Compression=lzma
SolidCompression=yes
; Moderne UI
WizardStyle=modern
; Rechte (normal für User-Installation, admin für System-weite Installation)
PrivilegesRequired=lowest
PrivilegesRequiredOverridesAllowed=dialog
[Languages]
Name: "german"; MessagesFile: "compiler:Languages\German.isl"
Name: "english"; MessagesFile: "compiler:Default.isl"
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
[Files]
; Alle Dateien aus dem PyInstaller-Build
Source: "dist\DocuMentor\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
[Icons]
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
[Messages]
; Deutsche Anpassungen
german.WelcomeLabel2=Dies wird [name/ver] auf Ihrem Computer installieren.%n%nBitte stellen Sie sicher, dass folgende externe Tools installiert sind:%n• Java Runtime Environment (JRE)%n• Apache FOP%n• Saxon XSLT-Prozessor%n• diff-pdf
+2
View File
@@ -26,4 +26,6 @@ extend-exclude = ["*_ui.py"]
[dependency-groups] [dependency-groups]
dev = [ dev = [
"ruff>=0.14.8", "ruff>=0.14.8",
"pyinstaller>=6.0.0",
"pillow>=10.0.0",
] ]
Binary file not shown.

After

Width:  |  Height:  |  Size: 678 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 819 KiB

+64
View File
@@ -0,0 +1,64 @@
# Resources für DocuMentor
Dieses Verzeichnis enthält Ressourcen für den Windows-Build.
## Icon (icon.ico)
Das Icon wird verwendet für:
- Windows-Executable (DocuMentor.exe)
- Inno Setup Installer
- Desktop-Verknüpfungen
- Start-Menü-Einträge
### Icon erstellen
#### Automatisch (Standard-Icon):
```bash
python create_icon.py
```
Dies erstellt ein einfaches Standard-Icon mit DocuMentor-Branding.
#### Aus eigenem PNG-Bild:
```bash
python create_icon.py mein-icon.png
```
Ihr PNG sollte idealerweise:
- Mindestens 256x256 Pixel groß sein
- Quadratisch sein
- Transparenten Hintergrund haben (optional)
### Icon-Anforderungen
Das `.ico`-Dateiformat enthält mehrere Auflösungen:
- 256x256 (Windows 7+, Taskleiste)
- 128x128
- 64x64
- 48x48 (Standard Desktop-Icon)
- 32x32 (Explorer Details)
- 16x16 (kleines Icon)
Das `create_icon.py` Skript erstellt automatisch alle diese Größen.
## Icon manuell ersetzen
1. Eigenes Icon als `resources/icon.ico` speichern
2. Oder mit einem Online-Tool PNG→ICO konvertieren
3. Build-Skript verwendet automatisch die vorhandene Datei
## Design-Richtlinien
Falls Sie ein eigenes Icon erstellen:
- **Einfach und klar**: Funktioniert auch in kleinen Größen (16x16)
- **Professionell**: Passend zum Business-Kontext
- **Wiedererkennbar**: DocuMentor steht für Dokumenten-Management
- **Kontrast**: Gut sichtbar auf hellem und dunklem Hintergrund
## Weitere Ressourcen
In diesem Verzeichnis können später weitere Ressourcen abgelegt werden:
- Splash-Screen-Bilder
- Toolbar-Icons
- Dokumentations-Bilder
- etc.
+45
View File
@@ -0,0 +1,45 @@
Erstelle ein professionelles Icon für eine Desktop-Anwendung namens "DocuMentor".
Die Anwendung wird verwendet für:
- Verwaltung von XSL-Transformationen
- Umwandlung von XML-Dokumenten zu PDF-Dateien
- Vergleich und Validierung von PDF-Dokumenten
Design-Anforderungen:
1. Stil: Minimalistisch, modern, professionell, business-orientiert
2. Farben:
- Hauptfarbe: Blau (#2980B9 oder ähnlich)
- Akzentfarbe: Weiß oder helles Grau
- Maximal 2-3 Farben insgesamt
3. Elemente (wähle eine Kombination):
- Dokument-Symbol (Papier/Seite)
- Transformation/Workflow-Element (Pfeil, Zahnrad)
- Optional: Stilisierter Buchstabe "M" oder "D"
4. Technische Anforderungen:
- Quadratisches Format
- Einfache, klare Linien
- Hoher Kontrast
- Muss auch bei 16x16 Pixel noch erkennbar sein
- Flat Design (keine 3D-Effekte)
- Keine Farbverläufe
5. Hintergrund:
- Transparent ODER
- Einfarbig (blau oder weiß)
6. Referenz-Stil:
- Ähnlich wie Microsoft Office Icons
- Ähnlich wie Visual Studio Code Icons
- Moderne SaaS-Anwendungs-Icons
Bitte erstelle ein Icon, das:
- Professionell und vertrauenswürdig wirkt
- Für technische Anwender geeignet ist
- Gut in einer Windows-Taskleiste aussieht
- Auch als Desktop-Verknüpfung funktioniert
Format: PNG oder SVG, mindestens 512x512 Pixel
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

+150
View File
@@ -0,0 +1,150 @@
# Icon-Prompt für Bild-Generierungs-KI
## DocuMentor Logo/Icon
### Deutsche Version (für deutsche KI-Tools)
```
Erstelle ein professionelles, minimalistisches SVG-Icon für eine Business-Software namens "DocuMentor".
Anwendungsbeschreibung:
DocuMentor ist eine Desktop-Anwendung zur Verwaltung und Validierung von XSL-Transformationen. Die Software wird von technischen Redakteuren und Entwicklern verwendet, um XML-Dokumente in PDF-Dateien zu transformieren und diese zu vergleichen.
Design-Anforderungen:
- Stil: Professionell, modern, technisch, business-orientiert
- Farben: Blaue Töne (z.B. #2980B9, #3498DB) kombiniert mit neutralen Grautönen oder Weiß
- Elemente: Kombination aus Dokumenten-Symbol und Transformations-/Workflow-Elementen
- Einfachheit: Muss auch in sehr kleinen Größen (16x16 Pixel) erkennbar sein
- Klare Linien und hoher Kontrast
Symbolik-Vorschläge:
- Ein Dokument mit Transformations-Pfeilen
- Gestapelte/verschachtelte Dokumente (XML → XSLT → PDF)
- Stilisiertes "D" oder "M" für DocuMentor
- Workflow-Diagramm mit Dokumenten-Symbolen
- Dokument mit Zahnrad (Verarbeitung/Transformation)
Format: Vektorgrafik (SVG), quadratisch (1:1 Verhältnis), 512x512 Pixel oder größer
Hintergrund: Transparent oder einfarbig (blau/weiß)
Stil-Referenzen: Microsoft Office Icons, Adobe Creative Cloud Icons, moderne SaaS-Anwendungen
```
### Englische Version (für internationale KI-Tools wie DALL-E, Midjourney, Stable Diffusion)
```
Create a professional, minimalist SVG icon for business software called "DocuMentor".
Application Description:
DocuMentor is a desktop application for managing and validating XSL transformations. The software is used by technical writers and developers to transform XML documents into PDF files and compare them.
Design Requirements:
- Style: Professional, modern, technical, business-oriented
- Colors: Blue tones (e.g., #2980B9, #3498DB) combined with neutral grays or white
- Elements: Combination of document symbol and transformation/workflow elements
- Simplicity: Must be recognizable even at very small sizes (16x16 pixels)
- Clean lines and high contrast
Symbolism Suggestions:
- A document with transformation arrows
- Stacked/nested documents (XML → XSLT → PDF)
- Stylized "D" or "M" for DocuMentor
- Workflow diagram with document symbols
- Document with gear icon (processing/transformation)
Format: Vector graphic (SVG), square (1:1 ratio), 512x512 pixels or larger
Background: Transparent or solid color (blue/white)
Style References: Microsoft Office icons, Adobe Creative Cloud icons, modern SaaS applications
Additional Instructions:
- Flat design, not 3D
- No gradients or complex shadows
- Maximum 3 colors
- Geometric shapes preferred
- Professional and trustworthy appearance
```
### Alternativer Prompt (detaillierter für KIs wie ChatGPT mit DALL-E)
```
Design a minimalist icon for "DocuMentor" - a professional XML/XSL transformation management software.
Concept: A clean, modern icon that combines:
1. A document/page symbol (representing XML/PDF files)
2. An element suggesting transformation or workflow (arrows, gears, or connecting lines)
3. Professional color scheme: Primary blue (#2980B9) with white/gray accents
Requirements:
- Vector style, flat design
- Must work well at 16x16, 48x48, and 256x256 pixels
- High contrast for visibility
- No text, icon only
- Square format (512x512px minimum)
- Transparent background preferred
Style inspiration: Think Microsoft Office 365 icons, VS Code icons, or modern productivity app icons - clean, professional, instantly recognizable.
Technical constraints:
- Simple enough to work as a favicon
- Clear silhouette when shown in monochrome
- Distinctive enough to stand out in a taskbar or dock
```
## Prompt für spezifische Konzepte
### Konzept 1: Dokument mit Transformation
```
A minimalist icon showing a document page with a curved arrow pointing to another document, symbolizing transformation. Blue (#2980B9) and white color scheme. Flat design, professional, suitable for business software. SVG style, 512x512px, transparent background.
```
### Konzept 2: Gestapelte Dokumente
```
An icon with three overlapping document sheets in a cascading arrangement, representing XML to XSL to PDF transformation workflow. Modern flat design, blue gradient (#3498DB to #2980B9), white accents. Professional business software icon. 512x512px SVG format.
```
### Konzept 3: Dokument + Zahnrad
```
A clean icon combining a document page with a small gear/cog symbol in the corner, representing document processing. Minimalist design, blue (#2980B9) on white background. Professional style like Microsoft Office icons. 512x512px, vector art, high contrast.
```
### Konzept 4: Stilisiertes "M"
```
A stylized letter "M" for "Mentor" integrated with document/page elements. Modern, geometric, professional. Blue (#2980B9) color scheme. Suitable for small sizes. Flat design, vector style, 512x512px, transparent background.
```
## Verwendung
1. Wähle einen der Prompts oben
2. Füge ihn in eine Bild-Generierungs-KI ein:
- **DALL-E 3** (ChatGPT Plus): Englischer Prompt empfohlen
- **Midjourney**: Englischer Prompt, evtl. kürzer
- **Adobe Firefly**: Deutscher oder englischer Prompt
- **Stable Diffusion**: Englischer Prompt mit detaillierten Tags
- **Leonardo.ai**: Englischer Prompt
3. Lade das generierte Bild herunter (idealerweise als PNG)
4. Konvertiere zu ICO:
```bash
uv run python create_icon.py generiertes-icon.png
```
## Tipps für beste Ergebnisse
- **Iteriere**: Generiere mehrere Varianten
- **Einfachheit**: Betone "minimalist", "simple", "clean"
- **Größe**: Teste das Icon in verschiedenen Größen
- **Kontrast**: Achte auf gute Sichtbarkeit auf hellem und dunklem Hintergrund
- **Professionalität**: Vermeide zu verspielte oder kindliche Designs
## Nachbearbeitung
Falls die KI kein perfektes SVG erstellt:
1. PNG exportieren (hohe Auflösung, mind. 512x512px)
2. Mit Inkscape oder Adobe Illustrator zu SVG konvertieren
3. Oder direkt als PNG verwenden und mit `create_icon.py` konvertieren
Generated
+163 -1
View File
@@ -2,6 +2,15 @@ version = 1
revision = 3 revision = 3
requires-python = ">=3.13" requires-python = ">=3.13"
[[package]]
name = "altgraph"
version = "0.17.5"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/7e/f8/97fdf103f38fed6792a1601dbc16cc8aac56e7459a9fff08c812d8ae177a/altgraph-0.17.5.tar.gz", hash = "sha256:c87b395dd12fabde9c99573a9749d67da8d29ef9de0125c7f536699b4a9bc9e7", size = 48428, upload-time = "2025-11-21T20:35:50.583Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/a9/ba/000a1996d4308bc65120167c21241a3b205464a2e0b58deda26ae8ac21d1/altgraph-0.17.5-py2.py3-none-any.whl", hash = "sha256:f3a22400bce1b0c701683820ac4f3b159cd301acab067c51c653e06961600597", size = 21228, upload-time = "2025-11-21T20:35:49.444Z" },
]
[[package]] [[package]]
name = "annotated-types" name = "annotated-types"
version = "0.7.0" version = "0.7.0"
@@ -46,6 +55,8 @@ dependencies = [
[package.dev-dependencies] [package.dev-dependencies]
dev = [ dev = [
{ name = "pillow" },
{ name = "pyinstaller" },
{ name = "ruff" }, { name = "ruff" },
] ]
@@ -59,7 +70,99 @@ requires-dist = [
] ]
[package.metadata.requires-dev] [package.metadata.requires-dev]
dev = [{ name = "ruff", specifier = ">=0.14.8" }] dev = [
{ name = "pillow", specifier = ">=10.0.0" },
{ name = "pyinstaller", specifier = ">=6.0.0" },
{ name = "ruff", specifier = ">=0.14.8" },
]
[[package]]
name = "macholib"
version = "1.16.4"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "altgraph" },
]
sdist = { url = "https://files.pythonhosted.org/packages/10/2f/97589876ea967487978071c9042518d28b958d87b17dceb7cdc1d881f963/macholib-1.16.4.tar.gz", hash = "sha256:f408c93ab2e995cd2c46e34fe328b130404be143469e41bc366c807448979362", size = 59427, upload-time = "2025-11-22T08:28:38.373Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c7/d1/a9f36f8ecdf0fb7c9b1e78c8d7af12b8c8754e74851ac7b94a8305540fc7/macholib-1.16.4-py2.py3-none-any.whl", hash = "sha256:da1a3fa8266e30f0ce7e97c6a54eefaae8edd1e5f86f3eb8b95457cae90265ea", size = 38117, upload-time = "2025-11-22T08:28:36.939Z" },
]
[[package]]
name = "packaging"
version = "25.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" },
]
[[package]]
name = "pefile"
version = "2024.8.26"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/03/4f/2750f7f6f025a1507cd3b7218691671eecfd0bbebebe8b39aa0fe1d360b8/pefile-2024.8.26.tar.gz", hash = "sha256:3ff6c5d8b43e8c37bb6e6dd5085658d658a7a0bdcd20b6a07b1fcfc1c4e9d632", size = 76008, upload-time = "2024-08-26T20:58:38.155Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/54/16/12b82f791c7f50ddec566873d5bdd245baa1491bac11d15ffb98aecc8f8b/pefile-2024.8.26-py3-none-any.whl", hash = "sha256:76f8b485dcd3b1bb8166f1128d395fa3d87af26360c2358fb75b80019b957c6f", size = 74766, upload-time = "2024-08-26T21:01:02.632Z" },
]
[[package]]
name = "pillow"
version = "12.1.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/d0/02/d52c733a2452ef1ffcc123b68e6606d07276b0e358db70eabad7e40042b7/pillow-12.1.0.tar.gz", hash = "sha256:5c5ae0a06e9ea030ab786b0251b32c7e4ce10e58d983c0d5c56029455180b5b9", size = 46977283, upload-time = "2026-01-02T09:13:29.892Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/dd/c7/2530a4aa28248623e9d7f27316b42e27c32ec410f695929696f2e0e4a778/pillow-12.1.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:7b5dd7cbae20285cdb597b10eb5a2c13aa9de6cde9bb64a3c1317427b1db1ae1", size = 4062543, upload-time = "2026-01-02T09:11:31.566Z" },
{ url = "https://files.pythonhosted.org/packages/8f/1f/40b8eae823dc1519b87d53c30ed9ef085506b05281d313031755c1705f73/pillow-12.1.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:29a4cef9cb672363926f0470afc516dbf7305a14d8c54f7abbb5c199cd8f8179", size = 4138373, upload-time = "2026-01-02T09:11:33.367Z" },
{ url = "https://files.pythonhosted.org/packages/d4/77/6fa60634cf06e52139fd0e89e5bbf055e8166c691c42fb162818b7fda31d/pillow-12.1.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:681088909d7e8fa9e31b9799aaa59ba5234c58e5e4f1951b4c4d1082a2e980e0", size = 3601241, upload-time = "2026-01-02T09:11:35.011Z" },
{ url = "https://files.pythonhosted.org/packages/4f/bf/28ab865de622e14b747f0cd7877510848252d950e43002e224fb1c9ababf/pillow-12.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:983976c2ab753166dc66d36af6e8ec15bb511e4a25856e2227e5f7e00a160587", size = 5262410, upload-time = "2026-01-02T09:11:36.682Z" },
{ url = "https://files.pythonhosted.org/packages/1c/34/583420a1b55e715937a85bd48c5c0991598247a1fd2eb5423188e765ea02/pillow-12.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:db44d5c160a90df2d24a24760bbd37607d53da0b34fb546c4c232af7192298ac", size = 4657312, upload-time = "2026-01-02T09:11:38.535Z" },
{ url = "https://files.pythonhosted.org/packages/1d/fd/f5a0896839762885b3376ff04878f86ab2b097c2f9a9cdccf4eda8ba8dc0/pillow-12.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6b7a9d1db5dad90e2991645874f708e87d9a3c370c243c2d7684d28f7e133e6b", size = 6232605, upload-time = "2026-01-02T09:11:40.602Z" },
{ url = "https://files.pythonhosted.org/packages/98/aa/938a09d127ac1e70e6ed467bd03834350b33ef646b31edb7452d5de43792/pillow-12.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6258f3260986990ba2fa8a874f8b6e808cf5abb51a94015ca3dc3c68aa4f30ea", size = 8041617, upload-time = "2026-01-02T09:11:42.721Z" },
{ url = "https://files.pythonhosted.org/packages/17/e8/538b24cb426ac0186e03f80f78bc8dc7246c667f58b540bdd57c71c9f79d/pillow-12.1.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e115c15e3bc727b1ca3e641a909f77f8ca72a64fff150f666fcc85e57701c26c", size = 6346509, upload-time = "2026-01-02T09:11:44.955Z" },
{ url = "https://files.pythonhosted.org/packages/01/9a/632e58ec89a32738cabfd9ec418f0e9898a2b4719afc581f07c04a05e3c9/pillow-12.1.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6741e6f3074a35e47c77b23a4e4f2d90db3ed905cb1c5e6e0d49bff2045632bc", size = 7038117, upload-time = "2026-01-02T09:11:46.736Z" },
{ url = "https://files.pythonhosted.org/packages/c7/a2/d40308cf86eada842ca1f3ffa45d0ca0df7e4ab33c83f81e73f5eaed136d/pillow-12.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:935b9d1aed48fcfb3f838caac506f38e29621b44ccc4f8a64d575cb1b2a88644", size = 6460151, upload-time = "2026-01-02T09:11:48.625Z" },
{ url = "https://files.pythonhosted.org/packages/f1/88/f5b058ad6453a085c5266660a1417bdad590199da1b32fb4efcff9d33b05/pillow-12.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5fee4c04aad8932da9f8f710af2c1a15a83582cfb884152a9caa79d4efcdbf9c", size = 7164534, upload-time = "2026-01-02T09:11:50.445Z" },
{ url = "https://files.pythonhosted.org/packages/19/ce/c17334caea1db789163b5d855a5735e47995b0b5dc8745e9a3605d5f24c0/pillow-12.1.0-cp313-cp313-win32.whl", hash = "sha256:a786bf667724d84aa29b5db1c61b7bfdde380202aaca12c3461afd6b71743171", size = 6332551, upload-time = "2026-01-02T09:11:52.234Z" },
{ url = "https://files.pythonhosted.org/packages/e5/07/74a9d941fa45c90a0d9465098fe1ec85de3e2afbdc15cc4766622d516056/pillow-12.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:461f9dfdafa394c59cd6d818bdfdbab4028b83b02caadaff0ffd433faf4c9a7a", size = 7040087, upload-time = "2026-01-02T09:11:54.822Z" },
{ url = "https://files.pythonhosted.org/packages/88/09/c99950c075a0e9053d8e880595926302575bc742b1b47fe1bbcc8d388d50/pillow-12.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:9212d6b86917a2300669511ed094a9406888362e085f2431a7da985a6b124f45", size = 2452470, upload-time = "2026-01-02T09:11:56.522Z" },
{ url = "https://files.pythonhosted.org/packages/b5/ba/970b7d85ba01f348dee4d65412476321d40ee04dcb51cd3735b9dc94eb58/pillow-12.1.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:00162e9ca6d22b7c3ee8e61faa3c3253cd19b6a37f126cad04f2f88b306f557d", size = 5264816, upload-time = "2026-01-02T09:11:58.227Z" },
{ url = "https://files.pythonhosted.org/packages/10/60/650f2fb55fdba7a510d836202aa52f0baac633e50ab1cf18415d332188fb/pillow-12.1.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:7d6daa89a00b58c37cb1747ec9fb7ac3bc5ffd5949f5888657dfddde6d1312e0", size = 4660472, upload-time = "2026-01-02T09:12:00.798Z" },
{ url = "https://files.pythonhosted.org/packages/2b/c0/5273a99478956a099d533c4f46cbaa19fd69d606624f4334b85e50987a08/pillow-12.1.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e2479c7f02f9d505682dc47df8c0ea1fc5e264c4d1629a5d63fe3e2334b89554", size = 6268974, upload-time = "2026-01-02T09:12:02.572Z" },
{ url = "https://files.pythonhosted.org/packages/b4/26/0bf714bc2e73d5267887d47931d53c4ceeceea6978148ed2ab2a4e6463c4/pillow-12.1.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f188d580bd870cda1e15183790d1cc2fa78f666e76077d103edf048eed9c356e", size = 8073070, upload-time = "2026-01-02T09:12:04.75Z" },
{ url = "https://files.pythonhosted.org/packages/43/cf/1ea826200de111a9d65724c54f927f3111dc5ae297f294b370a670c17786/pillow-12.1.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0fde7ec5538ab5095cc02df38ee99b0443ff0e1c847a045554cf5f9af1f4aa82", size = 6380176, upload-time = "2026-01-02T09:12:06.626Z" },
{ url = "https://files.pythonhosted.org/packages/03/e0/7938dd2b2013373fd85d96e0f38d62b7a5a262af21ac274250c7ca7847c9/pillow-12.1.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0ed07dca4a8464bada6139ab38f5382f83e5f111698caf3191cb8dbf27d908b4", size = 7067061, upload-time = "2026-01-02T09:12:08.624Z" },
{ url = "https://files.pythonhosted.org/packages/86/ad/a2aa97d37272a929a98437a8c0ac37b3cf012f4f8721e1bd5154699b2518/pillow-12.1.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:f45bd71d1fa5e5749587613037b172e0b3b23159d1c00ef2fc920da6f470e6f0", size = 6491824, upload-time = "2026-01-02T09:12:10.488Z" },
{ url = "https://files.pythonhosted.org/packages/a4/44/80e46611b288d51b115826f136fb3465653c28f491068a72d3da49b54cd4/pillow-12.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:277518bf4fe74aa91489e1b20577473b19ee70fb97c374aa50830b279f25841b", size = 7190911, upload-time = "2026-01-02T09:12:12.772Z" },
{ url = "https://files.pythonhosted.org/packages/86/77/eacc62356b4cf81abe99ff9dbc7402750044aed02cfd6a503f7c6fc11f3e/pillow-12.1.0-cp313-cp313t-win32.whl", hash = "sha256:7315f9137087c4e0ee73a761b163fc9aa3b19f5f606a7fc08d83fd3e4379af65", size = 6336445, upload-time = "2026-01-02T09:12:14.775Z" },
{ url = "https://files.pythonhosted.org/packages/e7/3c/57d81d0b74d218706dafccb87a87ea44262c43eef98eb3b164fd000e0491/pillow-12.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:0ddedfaa8b5f0b4ffbc2fa87b556dc59f6bb4ecb14a53b33f9189713ae8053c0", size = 7045354, upload-time = "2026-01-02T09:12:16.599Z" },
{ url = "https://files.pythonhosted.org/packages/ac/82/8b9b97bba2e3576a340f93b044a3a3a09841170ab4c1eb0d5c93469fd32f/pillow-12.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:80941e6d573197a0c28f394753de529bb436b1ca990ed6e765cf42426abc39f8", size = 2454547, upload-time = "2026-01-02T09:12:18.704Z" },
{ url = "https://files.pythonhosted.org/packages/8c/87/bdf971d8bbcf80a348cc3bacfcb239f5882100fe80534b0ce67a784181d8/pillow-12.1.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:5cb7bc1966d031aec37ddb9dcf15c2da5b2e9f7cc3ca7c54473a20a927e1eb91", size = 4062533, upload-time = "2026-01-02T09:12:20.791Z" },
{ url = "https://files.pythonhosted.org/packages/ff/4f/5eb37a681c68d605eb7034c004875c81f86ec9ef51f5be4a63eadd58859a/pillow-12.1.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:97e9993d5ed946aba26baf9c1e8cf18adbab584b99f452ee72f7ee8acb882796", size = 4138546, upload-time = "2026-01-02T09:12:23.664Z" },
{ url = "https://files.pythonhosted.org/packages/11/6d/19a95acb2edbace40dcd582d077b991646b7083c41b98da4ed7555b59733/pillow-12.1.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:414b9a78e14ffeb98128863314e62c3f24b8a86081066625700b7985b3f529bd", size = 3601163, upload-time = "2026-01-02T09:12:26.338Z" },
{ url = "https://files.pythonhosted.org/packages/fc/36/2b8138e51cb42e4cc39c3297713455548be855a50558c3ac2beebdc251dd/pillow-12.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:e6bdb408f7c9dd2a5ff2b14a3b0bb6d4deb29fb9961e6eb3ae2031ae9a5cec13", size = 5266086, upload-time = "2026-01-02T09:12:28.782Z" },
{ url = "https://files.pythonhosted.org/packages/53/4b/649056e4d22e1caa90816bf99cef0884aed607ed38075bd75f091a607a38/pillow-12.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3413c2ae377550f5487991d444428f1a8ae92784aac79caa8b1e3b89b175f77e", size = 4657344, upload-time = "2026-01-02T09:12:31.117Z" },
{ url = "https://files.pythonhosted.org/packages/6c/6b/c5742cea0f1ade0cd61485dc3d81f05261fc2276f537fbdc00802de56779/pillow-12.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e5dcbe95016e88437ecf33544ba5db21ef1b8dd6e1b434a2cb2a3d605299e643", size = 6232114, upload-time = "2026-01-02T09:12:32.936Z" },
{ url = "https://files.pythonhosted.org/packages/bf/8f/9f521268ce22d63991601aafd3d48d5ff7280a246a1ef62d626d67b44064/pillow-12.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d0a7735df32ccbcc98b98a1ac785cc4b19b580be1bdf0aeb5c03223220ea09d5", size = 8042708, upload-time = "2026-01-02T09:12:34.78Z" },
{ url = "https://files.pythonhosted.org/packages/1a/eb/257f38542893f021502a1bbe0c2e883c90b5cff26cc33b1584a841a06d30/pillow-12.1.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c27407a2d1b96774cbc4a7594129cc027339fd800cd081e44497722ea1179de", size = 6347762, upload-time = "2026-01-02T09:12:36.748Z" },
{ url = "https://files.pythonhosted.org/packages/c4/5a/8ba375025701c09b309e8d5163c5a4ce0102fa86bbf8800eb0d7ac87bc51/pillow-12.1.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15c794d74303828eaa957ff8070846d0efe8c630901a1c753fdc63850e19ecd9", size = 7039265, upload-time = "2026-01-02T09:12:39.082Z" },
{ url = "https://files.pythonhosted.org/packages/cf/dc/cf5e4cdb3db533f539e88a7bbf9f190c64ab8a08a9bc7a4ccf55067872e4/pillow-12.1.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c990547452ee2800d8506c4150280757f88532f3de2a58e3022e9b179107862a", size = 6462341, upload-time = "2026-01-02T09:12:40.946Z" },
{ url = "https://files.pythonhosted.org/packages/d0/47/0291a25ac9550677e22eda48510cfc4fa4b2ef0396448b7fbdc0a6946309/pillow-12.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b63e13dd27da389ed9475b3d28510f0f954bca0041e8e551b2a4eb1eab56a39a", size = 7165395, upload-time = "2026-01-02T09:12:42.706Z" },
{ url = "https://files.pythonhosted.org/packages/4f/4c/e005a59393ec4d9416be06e6b45820403bb946a778e39ecec62f5b2b991e/pillow-12.1.0-cp314-cp314-win32.whl", hash = "sha256:1a949604f73eb07a8adab38c4fe50791f9919344398bdc8ac6b307f755fc7030", size = 6431413, upload-time = "2026-01-02T09:12:44.944Z" },
{ url = "https://files.pythonhosted.org/packages/1c/af/f23697f587ac5f9095d67e31b81c95c0249cd461a9798a061ed6709b09b5/pillow-12.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:4f9f6a650743f0ddee5593ac9e954ba1bdbc5e150bc066586d4f26127853ab94", size = 7176779, upload-time = "2026-01-02T09:12:46.727Z" },
{ url = "https://files.pythonhosted.org/packages/b3/36/6a51abf8599232f3e9afbd16d52829376a68909fe14efe29084445db4b73/pillow-12.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:808b99604f7873c800c4840f55ff389936ef1948e4e87645eaf3fccbc8477ac4", size = 2543105, upload-time = "2026-01-02T09:12:49.243Z" },
{ url = "https://files.pythonhosted.org/packages/82/54/2e1dd20c8749ff225080d6ba465a0cab4387f5db0d1c5fb1439e2d99923f/pillow-12.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:bc11908616c8a283cf7d664f77411a5ed2a02009b0097ff8abbba5e79128ccf2", size = 5268571, upload-time = "2026-01-02T09:12:51.11Z" },
{ url = "https://files.pythonhosted.org/packages/57/61/571163a5ef86ec0cf30d265ac2a70ae6fc9e28413d1dc94fa37fae6bda89/pillow-12.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:896866d2d436563fa2a43a9d72f417874f16b5545955c54a64941e87c1376c61", size = 4660426, upload-time = "2026-01-02T09:12:52.865Z" },
{ url = "https://files.pythonhosted.org/packages/5e/e1/53ee5163f794aef1bf84243f755ee6897a92c708505350dd1923f4afec48/pillow-12.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8e178e3e99d3c0ea8fc64b88447f7cac8ccf058af422a6cedc690d0eadd98c51", size = 6269908, upload-time = "2026-01-02T09:12:54.884Z" },
{ url = "https://files.pythonhosted.org/packages/bc/0b/b4b4106ff0ee1afa1dc599fde6ab230417f800279745124f6c50bcffed8e/pillow-12.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:079af2fb0c599c2ec144ba2c02766d1b55498e373b3ac64687e43849fbbef5bc", size = 8074733, upload-time = "2026-01-02T09:12:56.802Z" },
{ url = "https://files.pythonhosted.org/packages/19/9f/80b411cbac4a732439e629a26ad3ef11907a8c7fc5377b7602f04f6fe4e7/pillow-12.1.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bdec5e43377761c5dbca620efb69a77f6855c5a379e32ac5b158f54c84212b14", size = 6381431, upload-time = "2026-01-02T09:12:58.823Z" },
{ url = "https://files.pythonhosted.org/packages/8f/b7/d65c45db463b66ecb6abc17c6ba6917a911202a07662247e1355ce1789e7/pillow-12.1.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:565c986f4b45c020f5421a4cea13ef294dde9509a8577f29b2fc5edc7587fff8", size = 7068529, upload-time = "2026-01-02T09:13:00.885Z" },
{ url = "https://files.pythonhosted.org/packages/50/96/dfd4cd726b4a45ae6e3c669fc9e49deb2241312605d33aba50499e9d9bd1/pillow-12.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:43aca0a55ce1eefc0aefa6253661cb54571857b1a7b2964bd8a1e3ef4b729924", size = 6492981, upload-time = "2026-01-02T09:13:03.314Z" },
{ url = "https://files.pythonhosted.org/packages/4d/1c/b5dc52cf713ae46033359c5ca920444f18a6359ce1020dd3e9c553ea5bc6/pillow-12.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0deedf2ea233722476b3a81e8cdfbad786f7adbed5d848469fa59fe52396e4ef", size = 7191878, upload-time = "2026-01-02T09:13:05.276Z" },
{ url = "https://files.pythonhosted.org/packages/53/26/c4188248bd5edaf543864fe4834aebe9c9cb4968b6f573ce014cc42d0720/pillow-12.1.0-cp314-cp314t-win32.whl", hash = "sha256:b17fbdbe01c196e7e159aacb889e091f28e61020a8abeac07b68079b6e626988", size = 6438703, upload-time = "2026-01-02T09:13:07.491Z" },
{ url = "https://files.pythonhosted.org/packages/b8/0e/69ed296de8ea05cb03ee139cee600f424ca166e632567b2d66727f08c7ed/pillow-12.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27b9baecb428899db6c0de572d6d305cfaf38ca1596b5c0542a5182e3e74e8c6", size = 7182927, upload-time = "2026-01-02T09:13:09.841Z" },
{ url = "https://files.pythonhosted.org/packages/fc/f5/68334c015eed9b5cff77814258717dec591ded209ab5b6fb70e2ae873d1d/pillow-12.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:f61333d817698bdcdd0f9d7793e365ac3d2a21c1f1eb02b32ad6aefb8d8ea831", size = 2545104, upload-time = "2026-01-02T09:13:12.068Z" },
]
[[package]] [[package]]
name = "polars" name = "polars"
@@ -176,6 +279,47 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/ba/39/8d263fbcb409a8f5dd78ac8f89f1e6af1d4e4d9fbb7f856ca3245b354809/pydantic_yaml-1.6.0-py3-none-any.whl", hash = "sha256:02cb800b455b68daeeb74ad736c252a94a0b203da5fbbeef02539d468e1d98f8", size = 22511, upload-time = "2025-08-08T21:01:11.425Z" }, { url = "https://files.pythonhosted.org/packages/ba/39/8d263fbcb409a8f5dd78ac8f89f1e6af1d4e4d9fbb7f856ca3245b354809/pydantic_yaml-1.6.0-py3-none-any.whl", hash = "sha256:02cb800b455b68daeeb74ad736c252a94a0b203da5fbbeef02539d468e1d98f8", size = 22511, upload-time = "2025-08-08T21:01:11.425Z" },
] ]
[[package]]
name = "pyinstaller"
version = "6.17.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "altgraph" },
{ name = "macholib", marker = "sys_platform == 'darwin'" },
{ name = "packaging" },
{ name = "pefile", marker = "sys_platform == 'win32'" },
{ name = "pyinstaller-hooks-contrib" },
{ name = "pywin32-ctypes", marker = "sys_platform == 'win32'" },
{ name = "setuptools" },
]
sdist = { url = "https://files.pythonhosted.org/packages/01/80/9e0dad9c69a7cfd4b5aaede8c6225d762bab7247a2a6b7651e1995522001/pyinstaller-6.17.0.tar.gz", hash = "sha256:be372bd911392b88277e510940ac32a5c2a6ce4b8d00a311c78fa443f4f27313", size = 4014147, upload-time = "2025-11-24T19:43:32.109Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/35/f5/37e419d84d5284ecab11ef8b61306a3b978fe6f0fd69a9541e16bfd72e65/pyinstaller-6.17.0-py3-none-macosx_10_13_universal2.whl", hash = "sha256:4e446b8030c6e5a2f712e3f82011ecf6c7ead86008357b0d23a0ec4bcde31dac", size = 1031880, upload-time = "2025-11-24T19:42:30.862Z" },
{ url = "https://files.pythonhosted.org/packages/9e/b6/2e184879ab9cf90a1d2867fdd34d507c4d246b3cc52ca05aad00bfc70ee7/pyinstaller-6.17.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:aa9fd87aaa28239c6f0d0210114029bd03f8cac316a90bab071a5092d7c85ad7", size = 731968, upload-time = "2025-11-24T19:42:35.421Z" },
{ url = "https://files.pythonhosted.org/packages/40/76/f529de98f7e5cce7904c19b224990003fc2267eda2ee5fdd8452acb420a9/pyinstaller-6.17.0-py3-none-manylinux2014_i686.whl", hash = "sha256:060b122e43e7c0b23e759a4153be34bd70914135ab955bb18a67181e0dca85a2", size = 743217, upload-time = "2025-11-24T19:42:39.286Z" },
{ url = "https://files.pythonhosted.org/packages/a3/10/c02bfbb050cafc4c353cf69baf95407e211e1372bd286ab5ce5cbc13a30a/pyinstaller-6.17.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:cd213d1a545c97dfe4a3c40e8213ff7c5127fc115c49229f27a3fa541503444b", size = 741119, upload-time = "2025-11-24T19:42:43.12Z" },
{ url = "https://files.pythonhosted.org/packages/11/9d/69fdacfd9335695f5900a376cfe3e4aed28f0720ffc15fee81fdb9d920bc/pyinstaller-6.17.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:89c0d18ba8b62c6607abd8cf2299ae5ffa5c36d8c47f39608ce8c3f357f6099f", size = 738111, upload-time = "2025-11-24T19:42:46.97Z" },
{ url = "https://files.pythonhosted.org/packages/5e/1e/e8e36e1568f6865ac706c6e1f875c1a346ddaa9f9a8f923d66545d2240ed/pyinstaller-6.17.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:2a147b83cdebb07855bd5a663600891550062373a2ca375c58eacead33741a27", size = 737795, upload-time = "2025-11-24T19:42:50.675Z" },
{ url = "https://files.pythonhosted.org/packages/8d/15/9dc0f81ccb746c27bfa6ee53164422fe47ee079c7a717d9c4791aba78797/pyinstaller-6.17.0-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:f8cfbbfa6708e54fb936df6dd6eafaf133e84efb0d2fe25b91cfeefa793c4ca4", size = 736891, upload-time = "2025-11-24T19:42:54.458Z" },
{ url = "https://files.pythonhosted.org/packages/97/e6/bed54821c1ebe1275c559661d3e7bfa23c406673b515252dfbf89db56c65/pyinstaller-6.17.0-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:97f4c1942f7b4cd73f9e38b49cc8f5f8a6fbb44922cb60dd3073a189b77ee1ae", size = 736752, upload-time = "2025-11-24T19:42:58.144Z" },
{ url = "https://files.pythonhosted.org/packages/c7/84/897d759198676b910d69d42640b6d25d50b449f2209e18127a974cf59dbe/pyinstaller-6.17.0-py3-none-win32.whl", hash = "sha256:ce0be227a037fd4be672226db709088565484f597d6b230bceec19850fdd4c85", size = 1317851, upload-time = "2025-11-24T19:43:04.361Z" },
{ url = "https://files.pythonhosted.org/packages/2d/f5/6a122efe024433ecc34aab6f499e0bd2bbe059c639b77b0045aa2421b0bf/pyinstaller-6.17.0-py3-none-win_amd64.whl", hash = "sha256:b019940dbf7a01489d6b26f9fb97db74b504e0a757010f7ad078675befc85a82", size = 1378685, upload-time = "2025-11-24T19:43:10.395Z" },
{ url = "https://files.pythonhosted.org/packages/c4/96/14991773c9e599707a53594429ccf372f9ee638df3b7d26b65fd1a7433f0/pyinstaller-6.17.0-py3-none-win_arm64.whl", hash = "sha256:3c92a335e338170df7e615f75279cfeea97ade89e6dd7694943c8c185460f7b7", size = 1320032, upload-time = "2025-11-24T19:43:16.388Z" },
]
[[package]]
name = "pyinstaller-hooks-contrib"
version = "2025.11"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "packaging" },
{ name = "setuptools" },
]
sdist = { url = "https://files.pythonhosted.org/packages/45/2f/2c68b6722d233dae3e5243751aafc932940b836919cfaca22dd0c60d417c/pyinstaller_hooks_contrib-2025.11.tar.gz", hash = "sha256:dfe18632e06655fa88d218e0d768fd753e1886465c12a6d4bce04f1aaeec917d", size = 169183, upload-time = "2025-12-23T12:59:37.361Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/a7/c4/3a096c6e701832443b957b9dac18a163103360d0c7f5842ca41695371148/pyinstaller_hooks_contrib-2025.11-py3-none-any.whl", hash = "sha256:777e163e2942474aa41a8e6d31ac1635292d63422c3646c176d584d04d971c34", size = 449478, upload-time = "2025-12-23T12:59:35.987Z" },
]
[[package]] [[package]]
name = "pyqtdarktheme" name = "pyqtdarktheme"
version = "2.1.0" version = "2.1.0"
@@ -245,6 +389,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/5f/ed/539768cf28c661b5b068d66d96a2f155c4971a5d55684a514c1a0e0dec2f/python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc", size = 20556, upload-time = "2025-06-24T04:21:06.073Z" }, { url = "https://files.pythonhosted.org/packages/5f/ed/539768cf28c661b5b068d66d96a2f155c4971a5d55684a514c1a0e0dec2f/python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc", size = 20556, upload-time = "2025-06-24T04:21:06.073Z" },
] ]
[[package]]
name = "pywin32-ctypes"
version = "0.2.3"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/85/9f/01a1a99704853cb63f253eea009390c88e7131c67e66a0a02099a8c917cb/pywin32-ctypes-0.2.3.tar.gz", hash = "sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755", size = 29471, upload-time = "2024-08-14T10:15:34.626Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/de/3d/8161f7711c017e01ac9f008dfddd9410dff3674334c233bde66e7ba65bbf/pywin32_ctypes-0.2.3-py3-none-any.whl", hash = "sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8", size = 30756, upload-time = "2024-08-14T10:15:33.187Z" },
]
[[package]] [[package]]
name = "ruamel-yaml" name = "ruamel-yaml"
version = "0.18.15" version = "0.18.15"
@@ -300,6 +453,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/6d/63/8b41cea3afd7f58eb64ac9251668ee0073789a3bc9ac6f816c8c6fef986d/ruff-0.14.8-py3-none-win_arm64.whl", hash = "sha256:965a582c93c63fe715fd3e3f8aa37c4b776777203d8e1d8aa3cc0c14424a4b99", size = 13634522, upload-time = "2025-12-04T15:06:43.212Z" }, { url = "https://files.pythonhosted.org/packages/6d/63/8b41cea3afd7f58eb64ac9251668ee0073789a3bc9ac6f816c8c6fef986d/ruff-0.14.8-py3-none-win_arm64.whl", hash = "sha256:965a582c93c63fe715fd3e3f8aa37c4b776777203d8e1d8aa3cc0c14424a4b99", size = 13634522, upload-time = "2025-12-04T15:06:43.212Z" },
] ]
[[package]]
name = "setuptools"
version = "80.9.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/18/5d/3bf57dcd21979b887f014ea83c24ae194cfcd12b9e0fda66b957c69d1fca/setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c", size = 1319958, upload-time = "2025-05-27T00:56:51.443Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922", size = 1201486, upload-time = "2025-05-27T00:56:49.664Z" },
]
[[package]] [[package]]
name = "shiboken6" name = "shiboken6"
version = "6.9.2" version = "6.9.2"