RollBack Punkt 2025-09-13

Dieser Commit ist enthalten in:
Claude Project Manager
2025-09-13 22:01:58 +02:00
Ursprung ca005ab9f0
Commit ba0ba3fcec
25 geänderte Dateien mit 140 neuen und 6194 gelöschten Zeilen

Datei anzeigen

@ -1,625 +0,0 @@
"""
Account Creation Modal V2 - Verbessertes Design mit eindringlicher Warnung
Basierend auf dem Corporate Design Styleguide
"""
import logging
from typing import Optional, List, Dict
from datetime import datetime, timedelta
from PyQt5.QtWidgets import (
QDialog, QVBoxLayout, QHBoxLayout, QLabel,
QPushButton, QFrame, QWidget, QScrollArea,
QProgressBar, QGraphicsOpacityEffect
)
from PyQt5.QtCore import (
Qt, QTimer, pyqtSignal, QPropertyAnimation,
QEasingCurve, QRect, QSize
)
from PyQt5.QtGui import QFont, QPainter, QBrush, QColor, QPen, QPixmap
logger = logging.getLogger("account_creation_modal_v2")
class AccountCreationModalV2(QDialog):
"""
Verbessertes Modal für Account-Erstellung mit:
- Prominenter Warnung
- Besserer Step-Visualisierung
- Größerem Fenster
- Klarerer Kommunikation
"""
# Signale
cancel_clicked = pyqtSignal()
process_completed = pyqtSignal()
def __init__(self, parent=None, platform: str = "Social Media"):
super().__init__(parent)
self.platform = platform
self.current_step = 0
self.total_steps = 0
self.steps = []
self.start_time = None
self.is_process_running = False
# Timer für Updates
self.update_timer = QTimer()
self.update_timer.timeout.connect(self.update_time_display)
self.update_timer.setInterval(1000) # Jede Sekunde
# Animation Timer für Warning
self.warning_animation_timer = QTimer()
self.warning_animation_timer.timeout.connect(self.animate_warning)
self.warning_animation_timer.setInterval(100) # Smooth animation
self.warning_opacity = 1.0
self.warning_direction = -0.02
self.init_ui()
def init_ui(self):
"""Initialisiert die UI mit verbessertem Design"""
# Modal-Eigenschaften
self.setModal(True)
self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
self.setAttribute(Qt.WA_TranslucentBackground)
# Größeres Fenster
self.setFixedSize(650, 700)
# Zentriere auf Parent oder Bildschirm
if self.parent():
parent_rect = self.parent().geometry()
x = parent_rect.x() + (parent_rect.width() - self.width()) // 2
y = parent_rect.y() + (parent_rect.height() - self.height()) // 2
self.move(x, y)
# Hauptlayout
main_layout = QVBoxLayout(self)
main_layout.setContentsMargins(0, 0, 0, 0)
main_layout.setSpacing(0)
# Container mit weißem Hintergrund
self.container = QFrame()
self.container.setObjectName("mainContainer")
self.container.setStyleSheet("""
QFrame#mainContainer {
background-color: #FFFFFF;
border: 1px solid #E2E8F0;
border-radius: 16px;
}
""")
container_layout = QVBoxLayout(self.container)
container_layout.setContentsMargins(0, 0, 0, 0)
container_layout.setSpacing(0)
# 1. WARNING BANNER (Sehr auffällig!)
self.warning_banner = self.create_warning_banner()
container_layout.addWidget(self.warning_banner)
# Content Area mit Padding
content_widget = QWidget()
content_layout = QVBoxLayout(content_widget)
content_layout.setContentsMargins(40, 30, 40, 40)
content_layout.setSpacing(24)
# 2. Titel-Bereich
self.title_label = QLabel(f"Account wird erstellt für {self.platform}")
self.title_label.setAlignment(Qt.AlignCenter)
self.title_label.setStyleSheet("""
QLabel {
color: #1A365D;
font-size: 28px;
font-weight: 700;
font-family: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
margin-bottom: 8px;
}
""")
content_layout.addWidget(self.title_label)
# 3. Progress-Bereich
progress_widget = self.create_progress_section()
content_layout.addWidget(progress_widget)
# 4. Steps-Liste
self.steps_widget = self.create_steps_list()
content_layout.addWidget(self.steps_widget)
# 5. Live-Status
self.status_widget = self.create_status_section()
content_layout.addWidget(self.status_widget)
# 6. Info-Box
info_box = self.create_info_box()
content_layout.addWidget(info_box)
# Spacer
content_layout.addStretch()
# Container zum Hauptlayout hinzufügen
container_layout.addWidget(content_widget)
main_layout.addWidget(self.container)
def create_warning_banner(self) -> QFrame:
"""Erstellt den auffälligen Warning Banner"""
banner = QFrame()
banner.setObjectName("warningBanner")
banner.setFixedHeight(100)
banner.setStyleSheet("""
QFrame#warningBanner {
background-color: #DC2626;
border-top-left-radius: 16px;
border-top-right-radius: 16px;
border-bottom: none;
}
""")
layout = QVBoxLayout(banner)
layout.setContentsMargins(40, 20, 40, 20)
layout.setSpacing(8)
# Warning Icon + Haupttext
main_warning = QLabel("⚠️ NICHT DEN BROWSER BERÜHREN!")
main_warning.setAlignment(Qt.AlignCenter)
main_warning.setStyleSheet("""
QLabel {
color: #FFFFFF;
font-size: 24px;
font-weight: 700;
font-family: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
letter-spacing: 1px;
}
""")
# Untertitel
subtitle = QLabel("Die Automatisierung läuft. Jede Interaktion kann den Prozess unterbrechen.")
subtitle.setAlignment(Qt.AlignCenter)
subtitle.setWordWrap(True)
subtitle.setStyleSheet("""
QLabel {
color: rgba(255, 255, 255, 0.9);
font-size: 14px;
font-weight: 400;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}
""")
layout.addWidget(main_warning)
layout.addWidget(subtitle)
return banner
def create_progress_section(self) -> QWidget:
"""Erstellt den Progress-Bereich"""
widget = QWidget()
layout = QHBoxLayout(widget)
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(24)
# Progress Bar
progress_container = QWidget()
progress_layout = QVBoxLayout(progress_container)
progress_layout.setContentsMargins(0, 0, 0, 0)
progress_layout.setSpacing(8)
self.progress_bar = QProgressBar()
self.progress_bar.setFixedHeight(12)
self.progress_bar.setStyleSheet("""
QProgressBar {
background-color: #E2E8F0;
border: none;
border-radius: 6px;
text-align: center;
}
QProgressBar::chunk {
background-color: #3182CE;
border-radius: 6px;
}
""")
self.progress_label = QLabel("Schritt 0 von 0")
self.progress_label.setStyleSheet("""
QLabel {
color: #4A5568;
font-size: 14px;
font-weight: 500;
}
""")
progress_layout.addWidget(self.progress_bar)
progress_layout.addWidget(self.progress_label)
# Zeit-Anzeige
time_container = QWidget()
time_container.setFixedWidth(180)
time_layout = QVBoxLayout(time_container)
time_layout.setContentsMargins(0, 0, 0, 0)
time_layout.setSpacing(4)
self.time_label = QLabel("~2 Min verbleibend")
self.time_label.setAlignment(Qt.AlignRight)
self.time_label.setStyleSheet("""
QLabel {
color: #1A365D;
font-size: 16px;
font-weight: 600;
font-family: 'Poppins', -apple-system, sans-serif;
}
""")
self.elapsed_label = QLabel("Verstrichene Zeit: 0:00")
self.elapsed_label.setAlignment(Qt.AlignRight)
self.elapsed_label.setStyleSheet("""
QLabel {
color: #718096;
font-size: 12px;
font-weight: 400;
}
""")
time_layout.addWidget(self.time_label)
time_layout.addWidget(self.elapsed_label)
layout.addWidget(progress_container, 1)
layout.addWidget(time_container)
return widget
def create_steps_list(self) -> QWidget:
"""Erstellt die visuelle Steps-Liste"""
container = QFrame()
container.setStyleSheet("""
QFrame {
background-color: #F8FAFC;
border: 1px solid #E2E8F0;
border-radius: 12px;
padding: 20px;
}
""")
self.steps_layout = QVBoxLayout(container)
self.steps_layout.setSpacing(12)
# Wird dynamisch befüllt
return container
def create_status_section(self) -> QWidget:
"""Erstellt den Live-Status Bereich"""
container = QFrame()
container.setStyleSheet("""
QFrame {
background-color: #1A365D;
border-radius: 12px;
padding: 20px;
min-height: 80px;
}
""")
layout = QVBoxLayout(container)
layout.setSpacing(8)
status_title = QLabel("Aktueller Status:")
status_title.setStyleSheet("""
QLabel {
color: rgba(255, 255, 255, 0.7);
font-size: 12px;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 1px;
}
""")
self.current_status_label = QLabel("Initialisiere Browser...")
self.current_status_label.setWordWrap(True)
self.current_status_label.setStyleSheet("""
QLabel {
color: #FFFFFF;
font-size: 16px;
font-weight: 400;
font-family: 'SF Mono', Monaco, 'Cascadia Code', monospace;
line-height: 1.5;
}
""")
layout.addWidget(status_title)
layout.addWidget(self.current_status_label)
return container
def create_info_box(self) -> QWidget:
"""Erstellt die Info-Box"""
container = QFrame()
container.setStyleSheet("""
QFrame {
background-color: #DBEAFE;
border: 1px solid #2563EB;
border-radius: 12px;
padding: 16px;
}
""")
layout = QHBoxLayout(container)
layout.setSpacing(16)
# Info Icon
icon_label = QLabel("")
icon_label.setStyleSheet("""
QLabel {
font-size: 24px;
color: #2563EB;
}
""")
# Info Text
info_layout = QVBoxLayout()
info_layout.setSpacing(4)
info_title = QLabel("Was passiert gerade?")
info_title.setStyleSheet("""
QLabel {
color: #1E40AF;
font-size: 14px;
font-weight: 600;
}
""")
self.info_text = QLabel("Der Browser simuliert menschliches Verhalten beim Ausfüllen des Formulars.")
self.info_text.setWordWrap(True)
self.info_text.setStyleSheet("""
QLabel {
color: #1E40AF;
font-size: 13px;
font-weight: 400;
line-height: 1.4;
}
""")
info_layout.addWidget(info_title)
info_layout.addWidget(self.info_text)
layout.addWidget(icon_label)
layout.addWidget(info_layout, 1)
return container
def set_steps(self, steps: List[str]):
"""Setzt die Steps und erstellt die visuelle Liste"""
self.steps = steps
self.total_steps = len(steps)
self.current_step = 0
# Progress Bar Setup
self.progress_bar.setMaximum(self.total_steps)
self.progress_bar.setValue(0)
# Clear existing steps
for i in reversed(range(self.steps_layout.count())):
self.steps_layout.itemAt(i).widget().setParent(None)
# Create step items
self.step_widgets = []
for i, step in enumerate(steps):
step_widget = self.create_step_item(i, step)
self.steps_layout.addWidget(step_widget)
self.step_widgets.append(step_widget)
def create_step_item(self, index: int, text: str) -> QWidget:
"""Erstellt ein einzelnes Step-Item"""
widget = QWidget()
layout = QHBoxLayout(widget)
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(12)
# Status Icon
icon_label = QLabel()
icon_label.setFixedSize(24, 24)
icon_label.setAlignment(Qt.AlignCenter)
icon_label.setObjectName(f"stepIcon_{index}")
# Text
text_label = QLabel(text)
text_label.setObjectName(f"stepText_{index}")
# Initial state (pending)
self.update_step_appearance(widget, 'pending')
layout.addWidget(icon_label)
layout.addWidget(text_label, 1)
return widget
def update_step_appearance(self, widget: QWidget, status: str):
"""Aktualisiert das Aussehen eines Steps basierend auf Status"""
icon_label = widget.findChild(QLabel, QRegExp("stepIcon_*"))
text_label = widget.findChild(QLabel, QRegExp("stepText_*"))
if status == 'completed':
icon_label.setText("")
text_label.setStyleSheet("""
QLabel {
color: #059669;
font-size: 14px;
font-weight: 500;
}
""")
elif status == 'active':
icon_label.setText("🔄")
text_label.setStyleSheet("""
QLabel {
color: #2563EB;
font-size: 14px;
font-weight: 600;
}
""")
# Rotation animation würde hier hinzugefügt
else: # pending
icon_label.setText("")
text_label.setStyleSheet("""
QLabel {
color: #718096;
font-size: 14px;
font-weight: 400;
}
""")
def start_process(self):
"""Startet den Account-Erstellungsprozess"""
self.is_process_running = True
self.start_time = datetime.now()
self.update_timer.start()
self.warning_animation_timer.start()
self.show()
def next_step(self, status_text: str = None, info_text: str = None):
"""Geht zum nächsten Schritt"""
if self.current_step < self.total_steps:
# Aktuellen Step als aktiv markieren
if self.current_step > 0:
self.update_step_appearance(self.step_widgets[self.current_step - 1], 'completed')
if self.current_step < len(self.step_widgets):
self.update_step_appearance(self.step_widgets[self.current_step], 'active')
self.current_step += 1
self.progress_bar.setValue(self.current_step)
self.progress_label.setText(f"Schritt {self.current_step} von {self.total_steps}")
# Update status
if status_text:
self.current_status_label.setText(status_text)
# Update info
if info_text:
self.info_text.setText(info_text)
# Update time estimate
self.update_time_estimate()
def update_time_estimate(self):
"""Aktualisiert die Zeitschätzung"""
if self.total_steps > 0 and self.current_step > 0:
elapsed = (datetime.now() - self.start_time).total_seconds()
avg_time_per_step = elapsed / self.current_step
remaining_steps = self.total_steps - self.current_step
estimated_remaining = remaining_steps * avg_time_per_step
if estimated_remaining < 60:
self.time_label.setText(f"~{int(estimated_remaining)}s verbleibend")
else:
minutes = int(estimated_remaining / 60)
self.time_label.setText(f"~{minutes} Min verbleibend")
def update_time_display(self):
"""Aktualisiert die verstrichene Zeit"""
if self.start_time:
elapsed = datetime.now() - self.start_time
minutes = int(elapsed.total_seconds() / 60)
seconds = int(elapsed.total_seconds() % 60)
self.elapsed_label.setText(f"Verstrichene Zeit: {minutes}:{seconds:02d}")
def animate_warning(self):
"""Animiert den Warning Banner (Pulseffekt)"""
self.warning_opacity += self.warning_direction
if self.warning_opacity <= 0.7:
self.warning_opacity = 0.7
self.warning_direction = 0.02
elif self.warning_opacity >= 1.0:
self.warning_opacity = 1.0
self.warning_direction = -0.02
# Opacity-Effekt anwenden
effect = QGraphicsOpacityEffect()
effect.setOpacity(self.warning_opacity)
self.warning_banner.setGraphicsEffect(effect)
def set_status(self, status: str, info: str = None):
"""Setzt den aktuellen Status"""
self.current_status_label.setText(status)
if info:
self.info_text.setText(info)
def complete_process(self):
"""Beendet den Prozess erfolgreich"""
self.is_process_running = False
self.update_timer.stop()
self.warning_animation_timer.stop()
# Letzten Step als completed markieren
if self.current_step > 0 and self.current_step <= len(self.step_widgets):
self.update_step_appearance(self.step_widgets[self.current_step - 1], 'completed')
# Success message
self.current_status_label.setText("✅ Account erfolgreich erstellt!")
self.info_text.setText("Der Prozess wurde erfolgreich abgeschlossen. Das Fenster schließt sich in wenigen Sekunden.")
# Auto-close nach 3 Sekunden
QTimer.singleShot(3000, self.close)
def paintEvent(self, event):
"""Custom paint event für Transparenz"""
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
# Semi-transparenter Hintergrund
painter.fillRect(self.rect(), QColor(0, 0, 0, 120))
def keyPressEvent(self, event):
"""Verhindert das Schließen mit ESC"""
if event.key() == Qt.Key_Escape:
event.ignore()
else:
super().keyPressEvent(event)
def closeEvent(self, event):
"""Verhindert das Schließen während der Prozess läuft"""
if self.is_process_running:
event.ignore()
else:
self.update_timer.stop()
self.warning_animation_timer.stop()
super().closeEvent(event)
# Beispiel-Verwendung
if __name__ == "__main__":
from PyQt5.QtWidgets import QApplication, QMainWindow
import sys
app = QApplication(sys.argv)
# Test window
main_window = QMainWindow()
main_window.setGeometry(100, 100, 800, 600)
main_window.show()
# Create and show modal
modal = AccountCreationModalV2(main_window, "Instagram")
modal.set_steps([
"Browser vorbereiten",
"Instagram-Seite laden",
"Registrierungsformular öffnen",
"Benutzerdaten eingeben",
"Account erstellen",
"E-Mail-Verifizierung",
"Profil einrichten"
])
# Simulate process
modal.start_process()
# Simulate step progression
def next_step():
modal.next_step(
f"Führe Schritt {modal.current_step + 1} aus...",
"Der Browser füllt automatisch die erforderlichen Felder aus."
)
if modal.current_step < modal.total_steps:
QTimer.singleShot(2000, next_step)
else:
modal.complete_process()
QTimer.singleShot(1000, next_step)
sys.exit(app.exec_())

Datei anzeigen

@ -1,370 +0,0 @@
"""
Forge Animation Widget V2 - Verbessertes Design mit prominenter Warnung
Angepasst an den bestehenden Code mit minimalen Änderungen
"""
from PyQt5.QtWidgets import QDialog, QWidget, QVBoxLayout, QLabel, QTextEdit, QPushButton, QHBoxLayout, QFrame
from PyQt5.QtCore import Qt, pyqtSignal, QTimer
from PyQt5.QtGui import QFont, QMovie, QPixmap
class ForgeAnimationDialog(QDialog):
"""Modal-Dialog für die Account-Erstellung mit verbessertem Design"""
# Signal wenn Abbrechen geklickt wird
cancel_clicked = pyqtSignal()
# Signal wenn Dialog geschlossen wird
closed = pyqtSignal()
def __init__(self, parent=None):
super().__init__(parent)
self.init_ui()
# Timer für das regelmäßige Nach-vorne-Holen
self.raise_timer = QTimer()
self.raise_timer.timeout.connect(self._raise_to_front)
self.raise_timer.setInterval(500) # Alle 500ms
def init_ui(self):
"""Initialisiert die UI mit verbessertem Design"""
# Nur Dialog im Vordergrund, nicht das ganze Hauptfenster
self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
self.setModal(False) # Nicht modal - blockiert nicht das Hauptfenster
self.setFixedSize(650, 600) # Größer für bessere Sichtbarkeit
# Styling für Light Theme
self.setStyleSheet("""
ForgeAnimationDialog {
background-color: #FFFFFF;
border: 1px solid #E2E8F0;
border-radius: 8px;
}
""")
# Hauptlayout
layout = QVBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(0)
# NEUE WARNUNG OBEN - Sehr auffällig!
warning_banner = QFrame()
warning_banner.setFixedHeight(80)
warning_banner.setStyleSheet("""
QFrame {
background-color: #DC2626;
border-top-left-radius: 8px;
border-top-right-radius: 8px;
padding: 15px 30px;
}
""")
warning_layout = QVBoxLayout(warning_banner)
warning_layout.setContentsMargins(0, 10, 0, 10)
# Großer Warning Text
warning_text = QLabel("⚠️ BROWSER NICHT BERÜHREN!")
warning_text.setAlignment(Qt.AlignCenter)
warning_text.setStyleSheet("""
QLabel {
color: #FFFFFF;
font-size: 22px;
font-weight: 700;
font-family: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
letter-spacing: 1px;
}
""")
warning_subtext = QLabel("Jede Interaktion kann den Prozess unterbrechen")
warning_subtext.setAlignment(Qt.AlignCenter)
warning_subtext.setStyleSheet("""
QLabel {
color: rgba(255, 255, 255, 0.9);
font-size: 13px;
font-weight: 400;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}
""")
warning_layout.addWidget(warning_text)
warning_layout.addWidget(warning_subtext)
layout.addWidget(warning_banner)
# Content Container
content_container = QWidget()
content_layout = QVBoxLayout(content_container)
content_layout.setContentsMargins(30, 25, 30, 30)
content_layout.setSpacing(20)
# Titel (etwas größer)
title_label = QLabel("Account wird erstellt")
title_label.setObjectName("titleLabel")
title_label.setAlignment(Qt.AlignCenter)
title_label.setStyleSheet("""
QLabel#titleLabel {
color: #1A365D;
font-size: 26px;
font-weight: 600;
font-family: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
padding-bottom: 10px;
border: none;
}
""")
content_layout.addWidget(title_label)
# Moderne Info-Karte (angepasst)
info_frame = QFrame()
info_frame.setStyleSheet("""
QFrame {
background: #DBEAFE;
border: 1px solid #2563EB;
border-radius: 12px;
min-height: 100px;
}
""")
info_layout = QHBoxLayout(info_frame)
info_layout.setContentsMargins(20, 15, 20, 15)
info_layout.setSpacing(15)
# Icon Container
icon_container = QFrame()
icon_container.setFixedSize(50, 50)
icon_container.setStyleSheet("""
QFrame {
background: #2563EB;
border-radius: 25px;
}
""")
icon_layout = QVBoxLayout(icon_container)
icon_layout.setContentsMargins(0, 0, 0, 0)
icon_label = QLabel("🤖")
icon_label.setAlignment(Qt.AlignCenter)
icon_label.setStyleSheet("""
QLabel {
font-size: 24px;
background: transparent;
border: none;
color: white;
}
""")
icon_layout.addWidget(icon_label)
# Text Container
text_container = QFrame()
text_layout = QVBoxLayout(text_container)
text_layout.setContentsMargins(0, 0, 0, 0)
text_layout.setSpacing(5)
# Titel
info_title = QLabel("Automatisierung läuft")
info_title.setObjectName("infoTitle")
info_title.setStyleSheet("""
QLabel#infoTitle {
color: #1E40AF;
font-size: 17px;
font-weight: 600;
font-family: 'Segoe UI', -apple-system, sans-serif;
background-color: transparent;
border: none;
}
""")
# Beschreibung (deutlicher)
info_desc = QLabel("Der Browser arbeitet automatisch. Bitte warten Sie, bis der Vorgang abgeschlossen ist.")
info_desc.setObjectName("infoDesc")
info_desc.setWordWrap(True)
info_desc.setStyleSheet("""
QLabel#infoDesc {
color: #1E40AF;
font-size: 14px;
font-weight: 500;
font-family: 'Segoe UI', -apple-system, sans-serif;
background-color: transparent;
border: none;
line-height: 20px;
}
""")
text_layout.addWidget(info_title)
text_layout.addWidget(info_desc)
text_layout.addStretch()
info_layout.addWidget(icon_container)
info_layout.addWidget(text_container, 1)
content_layout.addWidget(info_frame)
# Status Container
status_container = QFrame()
status_container.setStyleSheet("""
QFrame {
background-color: #1A365D;
border-radius: 8px;
padding: 15px;
}
""")
status_layout = QVBoxLayout(status_container)
# Status-Label (größer)
self.status_label = QLabel("Initialisiere...")
self.status_label.setObjectName("statusLabel")
self.status_label.setAlignment(Qt.AlignLeft)
self.status_label.setStyleSheet("""
QLabel#statusLabel {
color: #FFFFFF;
font-size: 16px;
padding: 5px;
font-weight: 500;
border: none;
font-family: 'SF Mono', Monaco, 'Cascadia Code', monospace;
}
""")
status_layout.addWidget(self.status_label)
content_layout.addWidget(status_container)
# Log-Ausgabe (größer)
self.log_output = QTextEdit()
self.log_output.setReadOnly(True)
self.log_output.setMaximumHeight(180) # Etwas größer
self.log_output.setStyleSheet("""
QTextEdit {
background-color: #F8FAFC;
color: #2D3748;
font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', monospace;
font-size: 12px;
border: 1px solid #CBD5E0;
border-radius: 8px;
padding: 12px;
}
""")
content_layout.addWidget(self.log_output)
# Button-Container
button_layout = QHBoxLayout()
button_layout.addStretch()
# Abbrechen-Button (weniger prominent)
self.cancel_button = QPushButton("Abbrechen")
self.cancel_button.setStyleSheet("""
QPushButton {
background-color: #F0F4F8;
color: #4A5568;
font-size: 14px;
font-weight: 500;
padding: 8px 24px;
border-radius: 24px;
border: 1px solid #E2E8F0;
min-height: 40px;
}
QPushButton:hover {
background-color: #FEE2E2;
color: #DC2626;
border-color: #DC2626;
}
QPushButton:pressed {
background-color: #DC2626;
color: #FFFFFF;
}
""")
self.cancel_button.clicked.connect(self.cancel_clicked.emit)
button_layout.addWidget(self.cancel_button)
button_layout.addStretch()
content_layout.addLayout(button_layout)
layout.addWidget(content_container)
self.setLayout(layout)
# Volle Sichtbarkeit
self.setWindowOpacity(1.0)
def start_animation(self):
"""Zeigt den Dialog an"""
self.status_label.setText("Initialisiere...")
self.raise_timer.start() # Starte Timer für Always-on-Top
def stop_animation(self):
"""Stoppt die Animation und den Timer"""
self.raise_timer.stop()
def set_status(self, status: str):
"""Aktualisiert den Status-Text"""
self.status_label.setText(status)
def add_log(self, message: str):
"""Fügt eine Log-Nachricht hinzu"""
self.log_output.append(message)
# Auto-scroll zum Ende
scrollbar = self.log_output.verticalScrollBar()
scrollbar.setValue(scrollbar.maximum())
def clear_log(self):
"""Löscht alle Log-Nachrichten"""
self.log_output.clear()
def set_progress(self, value: int):
"""Setzt den Fortschritt (0-100) - wird ignoriert da wir Spinner nutzen"""
pass
def closeEvent(self, event):
"""Wird aufgerufen wenn der Dialog geschlossen wird"""
self.stop_animation()
self.closed.emit()
event.accept()
def keyPressEvent(self, event):
"""Verhindert das Schließen mit ESC"""
if event.key() == Qt.Key_Escape:
event.ignore()
else:
super().keyPressEvent(event)
def _raise_to_front(self):
"""Holt den Dialog in den Vordergrund"""
self.raise_()
def show(self):
"""Überschreibt show() um den Dialog richtig zu positionieren"""
super().show()
self._raise_to_front() # Initial in den Vordergrund holen
# Zusätzliche Widget-Klasse für den AccountForger
class ForgeAnimationWidget(QLabel):
"""
Einfaches Animation Widget für den Progress Modal
Kann einen Spinner oder andere Animation anzeigen
"""
def __init__(self):
super().__init__()
self.setText("⚙️") # Placeholder Icon
self.setAlignment(Qt.AlignCenter)
self.setStyleSheet("""
QLabel {
font-size: 48px;
color: #3182CE;
}
""")
# Animation Timer
self.animation_timer = QTimer()
self.animation_timer.timeout.connect(self.rotate_icon)
self.rotation_state = 0
def start_animation(self):
"""Startet die Animation"""
self.animation_timer.start(100)
def stop_animation(self):
"""Stoppt die Animation"""
self.animation_timer.stop()
def rotate_icon(self):
"""Einfache Rotation Animation"""
icons = ["⚙️", "🔧", "🔨", "⚒️"]
self.setText(icons[self.rotation_state % len(icons)])
self.rotation_state += 1