Compare commits

17 Commits

Author SHA1 Message Date
René Mathieu
dc0db8496b Tests: Upload-Test hinzugefügt - prüft Server-Verfügbarkeit und Konfiguration 2026-01-17 15:09:22 +01:00
René Mathieu
b7730d908c Tests: test_dicom2pacs.py repariert - venv-Unterstützung und run_tests.sh hinzugefügt 2026-01-17 15:01:27 +01:00
René Mathieu
bc67232628 Ja/Nein-Dialog: Button-Breiten weiter reduziert (8/8/10) und Fenster kompakter (480x190) 2026-01-17 14:42:04 +01:00
René Mathieu
acaaba7758 Ja/Nein-Dialog: Button-Breiten reduziert (12/12/14) und Fenster kompakter (500x200) für bessere Lesbarkeit 2026-01-17 14:40:44 +01:00
René Mathieu
ccc764f198 Hauptfenster: Durchsuchen-Button wieder angezeigt als primärer Standard-Button 2026-01-17 14:39:05 +01:00
René Mathieu
aa12d099ae Ja/Nein-Dialog: Fenster vergrößert (600x220) und Button-Größen angepasst (width=18) 2026-01-17 14:38:14 +01:00
René Mathieu
ccf6717e92 Hauptfenster: Durchsuchen-Button bleibt versteckt, nur Abbruch-Button zentriert angezeigt 2026-01-17 14:37:18 +01:00
René Mathieu
a2ea61e0f3 Hauptfenster: Durchsuchen-Button wiederhergestellt als Standard-Button, Textgröße auf 13pt angepasst 2026-01-17 14:36:13 +01:00
René Mathieu
b8d90481bc Hauptfenster: Durchsuchen-Button entfernt, Abbruch zentriert | Ja/Nein-Dialog: Fenster vergrößert (550x200) 2026-01-17 14:35:07 +01:00
René Mathieu
2b4be16317 Bestätigungsdialog: Fenstergröße weiter erhöht (1000x680) für bessere Lesbarkeit 2026-01-17 14:33:22 +01:00
René Mathieu
5d76c6b020 Dialoge: Fenstergröße Unstimmigkeiten-Dialog angepasst, Button-Breiten im Bestätigungsdialog erhöht 2026-01-17 14:31:39 +01:00
René Mathieu
02dfb69121 macOS Buttons: Primäre Buttons markiert, Aqua Theme für natives Aussehen 2026-01-17 14:28:58 +01:00
René Mathieu
5b29837120 macOS Buttons: Aqua Theme explizit aktiviert für natives macOS-Aussehen 2026-01-17 14:24:47 +01:00
René Mathieu
c086cbd8e1 Button-Größen reduziert und Fenstergrößen angepasst für bessere Proportionen 2026-01-17 14:22:20 +01:00
René Mathieu
1f265c0e3c Alle Buttons größer und lesbarer gemacht (Schriftgröße 13, größere Breiten, mehr Padding) 2026-01-17 14:20:50 +01:00
René Mathieu
174521cd0e Dialoge: Größere Fenster (900px) und breitere Buttons für bessere Lesbarkeit 2026-01-17 14:17:14 +01:00
René Mathieu
18b0e4c254 Alle Buttons auf macOS-Style (ttk.Button) umgestellt 2026-01-17 14:15:44 +01:00
3 changed files with 250 additions and 55 deletions

150
gui.py
View File

@@ -6,6 +6,35 @@ import os
from queue import Queue from queue import Queue
import subprocess import subprocess
# Style einmalig konfigurieren (wird beim ersten Import ausgeführt)
_style_configured = False
def create_macos_button(parent, text, command=None, width=None, height=None, padx=10, pady=5, default=False):
"""Erstellt einen Button im nativen macOS-Stil (Aqua Theme)"""
global _style_configured
# Style nur einmal konfigurieren
if not _style_configured:
style = ttk.Style()
# Verwende das native macOS Aqua Theme
try:
style.theme_use('aqua') # macOS natives Theme
except:
pass # Falls aqua nicht verfügbar ist, verwende Standard
# Konfiguriere Button-Style für natives macOS-Aussehen
style.configure('TButton', font=('Helvetica', 13), padding=(10, 6))
_style_configured = True
# Verwende ttk.Button für natives macOS-Aussehen
# Das Aqua Theme stellt primäre Buttons automatisch blau dar
btn = ttk.Button(parent, text=text, command=command)
if width:
btn.config(width=width)
# Auf macOS werden Buttons automatisch im nativen Stil dargestellt
# Primäre Buttons erscheinen blau, sekundäre grau
return btn
class SettingsDialog: class SettingsDialog:
def __init__(self, parent, config): def __init__(self, parent, config):
self.config = config self.config = config
@@ -37,8 +66,9 @@ class SettingsDialog:
self.load_config() # Laden der aktuellen Konfiguration self.load_config() # Laden der aktuellen Konfiguration
# Speichern-Button # Speichern-Button (macOS-Style) - primärer Button (blau)
Button(self.top, text="Speichern", command=self.save_config).grid(row=4, column=1, pady=10) save_btn = create_macos_button(self.top, text="Speichern", command=self.save_config, width=16, default=True)
save_btn.grid(row=4, column=1, pady=12, padx=5)
def toggle_password_visibility(self): def toggle_password_visibility(self):
"""Wechselt die Sichtbarkeit des Passworteingabefelds.""" """Wechselt die Sichtbarkeit des Passworteingabefelds."""
@@ -97,8 +127,8 @@ class GUI:
self.bind_shortcuts() self.bind_shortcuts()
# Fenstergröße und -position festlegen # Fenstergröße und -position festlegen
window_width = 350 window_width = 420
window_height = 150 window_height = 180
screen_width = self.root.winfo_screenwidth() screen_width = self.root.winfo_screenwidth()
screen_height = self.root.winfo_screenheight() screen_height = self.root.winfo_screenheight()
center_x = int(screen_width / 2 - window_width / 2) center_x = int(screen_width / 2 - window_width / 2)
@@ -111,17 +141,18 @@ class GUI:
# Frame für die Buttons am unteren Rand des Fensters # Frame für die Buttons am unteren Rand des Fensters
self.button_frame = tk.Frame(self.root) self.button_frame = tk.Frame(self.root)
self.button_frame.pack(side=tk.BOTTOM, fill=tk.X, pady=10) self.button_frame.pack(side=tk.BOTTOM, fill=tk.X, pady=12)
# Durchsuchen Button # Durchsuchen Button (macOS-Style) - primärer Standard-Button (blau)
self.browse_button = tk.Button(self.button_frame, text="Durchsuchen", command=self.browse) self.browse_button = create_macos_button(self.button_frame, text="Durchsuchen", command=self.browse, width=14, default=True)
self.browse_button.pack(side=tk.LEFT, padx=10, expand=True) self.browse_button.pack(side=tk.LEFT, padx=12, expand=True, pady=4)
# Schließen Button # Schließen Button (macOS-Style) - sekundärer Button (grau)
self.close_button = tk.Button(self.button_frame, text="Abbruch", command=self.on_app_close) self.close_button = create_macos_button(self.button_frame, text="Abbruch", command=self.on_app_close, width=14)
self.close_button.pack(side=tk.RIGHT, padx=10, expand=True) self.close_button.pack(side=tk.RIGHT, padx=12, expand=True, pady=4)
self.hint_label = tk.Label(self.root, text="Bitte wählen Sie den Ordner mit den Bilddaten aus!") # Hinweis-Label mit angepasster Schriftgröße (wie Buttons: 13pt)
self.hint_label = tk.Label(self.root, text="Bitte wählen Sie den Ordner mit den Bilddaten aus!", font=('Helvetica', 13))
self.hint_label.pack(pady=5) # Pady hinzugefügt für etwas Abstand nach oben und unten self.hint_label.pack(pady=5) # Pady hinzugefügt für etwas Abstand nach oben und unten
self.root.protocol("WM_DELETE_WINDOW", self.on_close) self.root.protocol("WM_DELETE_WINDOW", self.on_close)
@@ -335,8 +366,8 @@ class JaAbbruchDialog(tk.Toplevel):
self.transfer_folder = transfer_folder self.transfer_folder = transfer_folder
self.title(title) self.title(title)
self.geometry("750x480") # Noch größeres Fenster self.geometry("950x520") # Größeres Fenster für bessere Lesbarkeit und passende Proportionen
self.minsize(700, 450) # Minimale Größe setzen self.minsize(900, 500) # Minimale Größe angepasst
# Hauptframe für besseres Layout # Hauptframe für besseres Layout
main_frame = tk.Frame(self) main_frame = tk.Frame(self)
@@ -361,7 +392,7 @@ class JaAbbruchDialog(tk.Toplevel):
tk.Label(expected_inner, text="Erwartete Daten (Tomedo):", font=italic_font, tk.Label(expected_inner, text="Erwartete Daten (Tomedo):", font=italic_font,
bg='#ffffff', fg='#0066cc', anchor="w").pack(pady=(0, 8), fill=tk.X) bg='#ffffff', fg='#0066cc', anchor="w").pack(pady=(0, 8), fill=tk.X)
expected_label = tk.Label(expected_inner, text=message.split('\n\n')[0], expected_label = tk.Label(expected_inner, text=message.split('\n\n')[0],
font=normal_font, justify=tk.LEFT, wraplength=650, font=normal_font, justify=tk.LEFT, wraplength=800,
bg='#ffffff', fg='#000000', anchor="w") bg='#ffffff', fg='#000000', anchor="w")
expected_label.pack(pady=(0, 0), fill=tk.X) expected_label.pack(pady=(0, 0), fill=tk.X)
@@ -375,32 +406,35 @@ class JaAbbruchDialog(tk.Toplevel):
tk.Label(found_inner, text="Gefundene Daten (DICOM):", font=italic_font, tk.Label(found_inner, text="Gefundene Daten (DICOM):", font=italic_font,
bg='#ffffff', fg='#cc6600', anchor="w").pack(pady=(0, 8), fill=tk.X) bg='#ffffff', fg='#cc6600', anchor="w").pack(pady=(0, 8), fill=tk.X)
found_label = tk.Label(found_inner, text=message.split('\n\n')[1], found_label = tk.Label(found_inner, text=message.split('\n\n')[1],
font=normal_font, justify=tk.LEFT, wraplength=650, font=normal_font, justify=tk.LEFT, wraplength=800,
bg='#ffffff', fg='#000000', anchor="w") bg='#ffffff', fg='#000000', anchor="w")
found_label.pack(pady=(0, 0), fill=tk.X) found_label.pack(pady=(0, 0), fill=tk.X)
# Frage # Frage
question_label = tk.Label(main_frame, question_label = tk.Label(main_frame,
text="Welche Daten sollen verwendet werden?", text="Welche Daten sollen verwendet werden?",
font=bold_font, wraplength=650) font=bold_font, wraplength=800)
question_label.pack(pady=(0, 25)) question_label.pack(pady=(0, 25))
# Button-Frame mit besserem Layout - Standard macOS Buttons # Button-Frame mit besserem Layout - Standard macOS Buttons
btn_frame = tk.Frame(main_frame) btn_frame = tk.Frame(main_frame)
btn_frame.pack(pady=15) btn_frame.pack(pady=18)
# Standard macOS Buttons (ohne spezielle Farben) - größer # Standard macOS Buttons (ttk.Button für besseres macOS-Aussehen)
yes_btn = tk.Button(btn_frame, text="Tomedo-Daten übernehmen", # Primärer Button (blau) - empfohlene Aktion
command=self.on_yes, width=25, height=2) yes_btn = create_macos_button(btn_frame, text="Tomedo-Daten übernehmen",
yes_btn.pack(side=tk.LEFT, padx=10) command=self.on_yes, width=28, default=True)
yes_btn.pack(side=tk.LEFT, padx=10, pady=6)
no_btn = tk.Button(btn_frame, text="Original-Daten behalten", # Sekundärer Button (grau)
command=self.on_no, width=25, height=2) no_btn = create_macos_button(btn_frame, text="Original-Daten behalten",
no_btn.pack(side=tk.LEFT, padx=10) command=self.on_no, width=28)
no_btn.pack(side=tk.LEFT, padx=10, pady=6)
cancel_btn = tk.Button(btn_frame, text="Abbruch", # Sekundärer Button (grau)
command=self.on_cancel, width=18, height=2) cancel_btn = create_macos_button(btn_frame, text="Abbruch",
cancel_btn.pack(side=tk.LEFT, padx=10) command=self.on_cancel, width=20)
cancel_btn.pack(side=tk.LEFT, padx=10, pady=6)
self.center_window() self.center_window()
@@ -472,8 +506,8 @@ class ConfirmKeepOriginalDialog(tk.Toplevel):
self.transfer_folder = transfer_folder self.transfer_folder = transfer_folder
self.title("Bestätigung") self.title("Bestätigung")
self.geometry("750x600") # Größeres Fenster für vollständige Datenanzeige self.geometry("1000x680") # Größeres Fenster für vollständige Datenanzeige und bessere Lesbarkeit
self.minsize(750, 600) # Minimale Größe erhöht self.minsize(950, 650) # Minimale Größe erhöht
main_frame = tk.Frame(self) main_frame = tk.Frame(self)
main_frame.pack(fill=tk.BOTH, expand=True, padx=40, pady=30) main_frame.pack(fill=tk.BOTH, expand=True, padx=40, pady=30)
@@ -503,7 +537,7 @@ class ConfirmKeepOriginalDialog(tk.Toplevel):
tk.Label(tomedo_inner, text="Erwartete Daten (Tomedo):", font=italic_font, tk.Label(tomedo_inner, text="Erwartete Daten (Tomedo):", font=italic_font,
bg='#ffffff', fg='#0066cc', anchor="w").pack(pady=(0, 8), fill=tk.X) bg='#ffffff', fg='#0066cc', anchor="w").pack(pady=(0, 8), fill=tk.X)
tomedo_label = tk.Label(tomedo_inner, text=tomedo_data, tomedo_label = tk.Label(tomedo_inner, text=tomedo_data,
font=normal_font, justify=tk.LEFT, wraplength=650, font=normal_font, justify=tk.LEFT, wraplength=800,
bg='#ffffff', fg='#000000', anchor="w") bg='#ffffff', fg='#000000', anchor="w")
tomedo_label.pack(pady=(0, 0), fill=tk.X) tomedo_label.pack(pady=(0, 0), fill=tk.X)
@@ -517,37 +551,40 @@ class ConfirmKeepOriginalDialog(tk.Toplevel):
tk.Label(original_inner, text="Gefundene Daten (DICOM):", font=italic_font, tk.Label(original_inner, text="Gefundene Daten (DICOM):", font=italic_font,
bg='#ffffff', fg='#cc6600', anchor="w").pack(pady=(0, 8), fill=tk.X) bg='#ffffff', fg='#cc6600', anchor="w").pack(pady=(0, 8), fill=tk.X)
original_label = tk.Label(original_inner, text=original_data, original_label = tk.Label(original_inner, text=original_data,
font=normal_font, justify=tk.LEFT, wraplength=650, font=normal_font, justify=tk.LEFT, wraplength=800,
bg='#ffffff', fg='#000000', anchor="w") bg='#ffffff', fg='#000000', anchor="w")
original_label.pack(pady=(0, 0), fill=tk.X) original_label.pack(pady=(0, 0), fill=tk.X)
# Frage # Frage
question_label = tk.Label(main_frame, question_label = tk.Label(main_frame,
text="Sind Sie sicher, dass Sie die Original-Daten behalten möchten?", text="Sind Sie sicher, dass Sie die Original-Daten behalten möchten?",
font=bold_font, wraplength=650, justify=tk.CENTER) font=bold_font, wraplength=800, justify=tk.CENTER)
question_label.pack(pady=(0, 10)) question_label.pack(pady=(0, 10))
info_label = tk.Label(main_frame, info_label = tk.Label(main_frame,
text="Die Tomedo-Daten sind der Standard und sollten normalerweise verwendet werden.", text="Die Tomedo-Daten sind der Standard und sollten normalerweise verwendet werden.",
font=normal_font, wraplength=650, justify=tk.CENTER, fg='#666666') font=normal_font, wraplength=800, justify=tk.CENTER, fg='#666666')
info_label.pack(pady=(0, 20)) info_label.pack(pady=(0, 20))
# Button-Frame # Button-Frame
btn_frame = tk.Frame(main_frame) btn_frame = tk.Frame(main_frame)
btn_frame.pack(pady=10) btn_frame.pack(pady=12)
# Buttons # Buttons (macOS-Style) - breiter für bessere Textlesbarkeit
tomedo_btn = tk.Button(btn_frame, text="Tomedo-Daten verwenden", # Primärer Button (blau) - empfohlene Aktion
command=self.on_use_tomedo, width=22, height=2) tomedo_btn = create_macos_button(btn_frame, text="Tomedo-Daten verwenden",
tomedo_btn.pack(side=tk.LEFT, padx=8) command=self.on_use_tomedo, width=32, default=True)
tomedo_btn.pack(side=tk.LEFT, padx=8, pady=6)
keep_btn = tk.Button(btn_frame, text="Original behalten", # Sekundärer Button (grau)
command=self.on_keep_original, width=18, height=2) keep_btn = create_macos_button(btn_frame, text="Original behalten",
keep_btn.pack(side=tk.LEFT, padx=8) command=self.on_keep_original, width=26)
keep_btn.pack(side=tk.LEFT, padx=8, pady=6)
cancel_btn = tk.Button(btn_frame, text="Abbruch", # Sekundärer Button (grau)
command=self.on_cancel, width=15, height=2) cancel_btn = create_macos_button(btn_frame, text="Abbruch",
cancel_btn.pack(side=tk.LEFT, padx=8) command=self.on_cancel, width=20)
cancel_btn.pack(side=tk.LEFT, padx=8, pady=6)
self.center_window() self.center_window()
@@ -615,20 +652,25 @@ class JaNeinAbbruchDialog(tk.Toplevel):
self.title(title) self.title(title)
self.geometry("400x175") # Größe des Dialogs self.geometry("480x190") # Kompakteres Fenster für bessere Lesbarkeit
tk.Label(self, text=self.message).pack(pady=20) self.minsize(450, 170) # Minimale Größe
tk.Label(self, text=self.message, font=('Helvetica', 13), wraplength=420).pack(pady=20)
btn_frame = tk.Frame(self) btn_frame = tk.Frame(self)
btn_frame.pack(pady=10) btn_frame.pack(pady=12)
ja_btn = tk.Button(btn_frame, text="Ja", command=self.on_ja) # Buttons (macOS-Style) - minimale Breiten für bessere Lesbarkeit
ja_btn.pack(side=tk.LEFT, padx=10, pady=20) # Primärer Button (blau) - Ja ist die primäre Aktion
ja_btn = create_macos_button(btn_frame, text="Ja", command=self.on_ja, width=8, default=True)
ja_btn.pack(side=tk.LEFT, padx=8, pady=5)
nein_btn = tk.Button(btn_frame, text="Nein", command=self.on_nein) # Sekundärer Button (grau)
nein_btn.pack(side=tk.LEFT, padx=10, pady=20) nein_btn = create_macos_button(btn_frame, text="Nein", command=self.on_nein, width=8)
nein_btn.pack(side=tk.LEFT, padx=8, pady=5)
abbruch_btn = tk.Button(btn_frame, text="Abbruch", command=self.on_abbruch) # Sekundärer Button (grau)
abbruch_btn.pack(side=tk.LEFT, padx=10, pady=20) abbruch_btn = create_macos_button(btn_frame, text="Abbruch", command=self.on_abbruch, width=10)
abbruch_btn.pack(side=tk.LEFT, padx=8, pady=5)
self.center_window() self.center_window()

14
run_tests.sh Executable file
View File

@@ -0,0 +1,14 @@
#!/bin/bash
# run_tests.sh - Führt die Python-Tests mit aktiviertem venv aus
cd "$(dirname "$0")"
# Aktiviere venv
if [ -d "venv" ]; then
source venv/bin/activate
python3 test_dicom2pacs.py
else
echo "FEHLER: venv nicht gefunden!"
echo "Bitte erstellen Sie ein venv: python3 -m venv venv"
exit 1
fi

View File

@@ -10,12 +10,46 @@ import tempfile
from pathlib import Path from pathlib import Path
# Füge Projektverzeichnis zum Python-Pfad hinzu # Füge Projektverzeichnis zum Python-Pfad hinzu
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) project_dir = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, project_dir)
# Versuche venv zu verwenden
venv_path = os.path.join(project_dir, 'venv')
python_version = f"{sys.version_info.major}.{sys.version_info.minor}"
if os.path.exists(venv_path):
# Füge venv site-packages zum Python-Pfad hinzu
site_packages = os.path.join(venv_path, 'lib', f'python{python_version}', 'site-packages')
if os.path.exists(site_packages):
sys.path.insert(0, site_packages)
# Versuche auch pydicom aus der gebauten App zu verwenden
app_path = os.path.join(project_dir, 'dist', 'dicom2pacs.app', 'Contents', 'Resources', 'lib', f'python{python_version}')
if os.path.exists(app_path):
sys.path.insert(0, app_path)
# Prüfe ob pydicom verfügbar ist, sonst gebe Hinweis
try:
import pydicom
except ImportError:
print("WARNUNG: pydicom nicht gefunden. Bitte venv aktivieren oder pydicom installieren:")
print(" source venv/bin/activate")
print(" pip install pydicom")
print("Oder Tests mit test_dicom2pacs.sh ausführen, das das venv automatisch aktiviert.\n")
def test_imports(): def test_imports():
"""Test ob alle Module importiert werden können""" """Test ob alle Module importiert werden können"""
print("Teste Imports...") print("Teste Imports...")
try: try:
# Versuche zuerst pydicom zu importieren, um zu prüfen ob es verfügbar ist
try:
import pydicom
except ImportError:
print("⚠ pydicom nicht gefunden - Tests können nicht vollständig ausgeführt werden")
print(" Bitte venv aktivieren: source venv/bin/activate")
print(" Oder Tests mit test_dicom2pacs.sh ausführen")
return False
import dicom_processing import dicom_processing
import file_management import file_management
import network_utils import network_utils
@@ -24,12 +58,20 @@ def test_imports():
return True return True
except ImportError as e: except ImportError as e:
print(f"✗ Import-Fehler: {e}") print(f"✗ Import-Fehler: {e}")
print(" Tipp: Führen Sie die Tests mit test_dicom2pacs.sh aus, um das venv automatisch zu aktivieren")
return False return False
def test_dicom_file_detection(): def test_dicom_file_detection():
"""Test DICOM-Datei-Erkennung""" """Test DICOM-Datei-Erkennung"""
print("\nTeste DICOM-Datei-Erkennung...") print("\nTeste DICOM-Datei-Erkennung...")
try: try:
# Prüfe ob pydicom verfügbar ist
try:
import pydicom
except ImportError:
print("⚠ pydicom nicht verfügbar - Test übersprungen")
return False
import dicom_processing import dicom_processing
# Suche nach Test-DICOM-Dateien # Suche nach Test-DICOM-Dateien
@@ -64,6 +106,13 @@ def test_file_management():
"""Test Dateiverwaltung""" """Test Dateiverwaltung"""
print("\nTeste Dateiverwaltung...") print("\nTeste Dateiverwaltung...")
try: try:
# Prüfe ob pydicom verfügbar ist
try:
import pydicom
except ImportError:
print("⚠ pydicom nicht verfügbar - Test übersprungen")
return False
import file_management import file_management
test_dir = os.path.expanduser("~/Downloads/test_dicom") test_dir = os.path.expanduser("~/Downloads/test_dicom")
@@ -106,6 +155,13 @@ def test_patient_name_formatting():
"""Test Patientenname-Formatierung""" """Test Patientenname-Formatierung"""
print("\nTeste Patientenname-Formatierung...") print("\nTeste Patientenname-Formatierung...")
try: try:
# Prüfe ob pydicom verfügbar ist (wird indirekt benötigt)
try:
import pydicom
except ImportError:
print("⚠ pydicom nicht verfügbar - Test übersprungen")
return False
import file_management import file_management
# Test verschiedene Formate # Test verschiedene Formate
@@ -132,6 +188,13 @@ def test_birthdate_formatting():
"""Test Geburtsdatum-Formatierung""" """Test Geburtsdatum-Formatierung"""
print("\nTeste Geburtsdatum-Formatierung...") print("\nTeste Geburtsdatum-Formatierung...")
try: try:
# Prüfe ob pydicom verfügbar ist (wird indirekt benötigt)
try:
import pydicom
except ImportError:
print("⚠ pydicom nicht verfügbar - Test übersprungen")
return False
import file_management import file_management
test_cases = [ test_cases = [
@@ -152,6 +215,81 @@ def test_birthdate_formatting():
print(f"✗ Fehler: {e}") print(f"✗ Fehler: {e}")
return False return False
def test_upload_functionality():
"""Test Upload-Funktionalität"""
print("\nTeste Upload-Funktionalität...")
try:
import asyncio
import network_utils
# Lade Konfiguration
config_path = os.path.expanduser("~/.dicom2pacs.conf")
server_url = None
server_username = None
server_pw = None
if os.path.exists(config_path):
with open(config_path, 'r') as f:
for line in f:
line = line.strip()
if line.startswith('server_url='):
server_url = line.split('=', 1)[1]
elif line.startswith('server_username='):
server_username = line.split('=', 1)[1]
elif line.startswith('server_pw='):
server_pw = line.split('=', 1)[1]
if not server_url:
print("⚠ Keine Server-URL in Konfiguration gefunden - Upload-Test übersprungen")
print(" Bitte konfigurieren Sie die Server-URL in ~/.dicom2pacs.conf")
return True # Nicht kritisch, Test überspringen
# Test 1: Server-Verfügbarkeit prüfen
print(" Prüfe Server-Verfügbarkeit...")
try:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
availability = loop.run_until_complete(network_utils.check_server_availability(server_url))
loop.close()
if availability:
print(f" ✓ Server ist erreichbar: {server_url}")
# Test 2: Prüfe ob Test-DICOM-Dateien vorhanden sind
test_dir = os.path.expanduser("~/Downloads/test_dicom")
if os.path.exists(test_dir):
import file_management
result = file_management.find_dicom_files(test_dir)
if result != 'non_found':
files, count = result
if count > 0:
print(f"{count} Test-DICOM-Dateien gefunden")
print(" ⚠ Upload-Test würde echte Dateien hochladen - wird übersprungen")
print(" (Für echten Upload-Test: Manuell mit test_dicom2pacs.sh durchführen)")
return True
else:
print(" ⚠ Keine DICOM-Dateien im Test-Ordner")
else:
print(" ⚠ Keine DICOM-Dateien im Test-Ordner")
else:
print(" ⚠ Test-Ordner nicht gefunden: ~/Downloads/test_dicom")
return True
else:
print(f" ⚠ Server ist nicht erreichbar: {server_url}")
print(" (Upload-Test kann nicht durchgeführt werden)")
return True # Nicht kritisch, Server könnte offline sein
except Exception as e:
print(f" ⚠ Fehler beim Prüfen der Server-Verfügbarkeit: {e}")
return True # Nicht kritisch
except ImportError as e:
print(f"✗ Import-Fehler: {e}")
return False
except Exception as e:
print(f"✗ Fehler: {e}")
return False
def main(): def main():
"""Hauptfunktion für alle Tests""" """Hauptfunktion für alle Tests"""
print("=== dicom2pacs Automatisierte Tests ===\n") print("=== dicom2pacs Automatisierte Tests ===\n")
@@ -163,6 +301,7 @@ def main():
("Konfiguration", test_config_loading), ("Konfiguration", test_config_loading),
("Patientenname-Formatierung", test_patient_name_formatting), ("Patientenname-Formatierung", test_patient_name_formatting),
("Geburtsdatum-Formatierung", test_birthdate_formatting), ("Geburtsdatum-Formatierung", test_birthdate_formatting),
("Upload-Funktionalität", test_upload_functionality),
] ]
results = [] results = []