Files
Jackify/jackify/frontends/gui/dialogs/warning_dialog.py
2025-12-06 20:09:55 +00:00

251 lines
8.7 KiB
Python

"""
Warning Dialog
Custom warning dialog for destructive actions (e.g., deleting directory contents).
Matches Jackify theming and requires explicit user confirmation.
"""
from pathlib import Path
from PySide6.QtWidgets import (
QDialog, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QLineEdit, QFrame, QSizePolicy, QTextEdit
)
from PySide6.QtCore import Qt
from PySide6.QtGui import QPixmap, QIcon, QFont
from .. import shared_theme
class WarningDialog(QDialog):
"""
Jackify-themed warning dialog for dangerous/destructive actions.
Requires user to type 'DELETE' to confirm.
"""
def __init__(self, warning_message: str, parent=None):
super().__init__(parent)
self.setWindowTitle("Warning!")
self.setModal(True)
# Increased height for better text display, scalable for 800p screens
self.setFixedSize(500, 460)
self.confirmed = False
self._failed_attempts = 0
self._max_attempts = 3
self._setup_ui(warning_message)
def _setup_ui(self, warning_message):
layout = QVBoxLayout(self)
layout.setSpacing(0)
layout.setContentsMargins(0, 0, 0, 0)
# Card background
card = QFrame(self)
card.setObjectName("warningCard")
card.setFrameShape(QFrame.StyledPanel)
card.setFrameShadow(QFrame.Raised)
card.setMinimumWidth(440)
card.setMinimumHeight(320)
card.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
card_layout = QVBoxLayout(card)
card_layout.setSpacing(16)
card_layout.setContentsMargins(28, 28, 28, 28)
card.setStyleSheet(
"QFrame#warningCard { "
" background: #2d2323; "
" border-radius: 12px; "
" border: 2px solid #e67e22; "
"}"
)
# Warning icon
icon_label = QLabel()
icon_label.setAlignment(Qt.AlignCenter)
icon_label.setText("!")
icon_label.setStyleSheet(
"QLabel { "
" font-size: 36px; "
" font-weight: bold; "
" color: #e67e22; "
" margin-bottom: 4px; "
"}"
)
card_layout.addWidget(icon_label)
# Warning title
title_label = QLabel("Potentially Destructive Action!")
title_label.setAlignment(Qt.AlignCenter)
title_label.setStyleSheet(
"QLabel { "
" font-size: 20px; "
" font-weight: 600; "
" color: #e67e22; "
" margin-bottom: 2px; "
"}"
)
card_layout.addWidget(title_label)
# Warning message (use a scrollable text area for long messages)
message_text = QTextEdit()
message_text.setReadOnly(True)
message_text.setPlainText(warning_message)
message_text.setMinimumHeight(80)
message_text.setMaximumHeight(160)
message_text.setStyleSheet(
"QTextEdit { "
" font-size: 15px; "
" color: #e0e0e0; "
" background: transparent; "
" border: none; "
" line-height: 1.3; "
" margin-bottom: 6px; "
" max-width: 400px; "
" min-width: 200px; "
"}"
)
card_layout.addWidget(message_text)
# Confirmation entry
self.confirm_label = QLabel("Type 'DELETE' to confirm (all caps):")
self.confirm_label.setAlignment(Qt.AlignCenter)
self.confirm_label.setStyleSheet(
"QLabel { "
" font-size: 13px; "
" color: #e67e22; "
" margin-bottom: 2px; "
"}"
)
card_layout.addWidget(self.confirm_label)
self.confirm_edit = QLineEdit()
self.confirm_edit.setAlignment(Qt.AlignCenter)
self.confirm_edit.setPlaceholderText("DELETE")
self._default_lineedit_style = (
"QLineEdit { "
" font-size: 15px; "
" border: 1px solid #e67e22; "
" border-radius: 6px; "
" padding: 6px; "
" background: #23272e; "
" color: #e67e22; "
"}"
)
self.confirm_edit.setStyleSheet(self._default_lineedit_style)
self.confirm_edit.textChanged.connect(self._on_text_changed)
self.confirm_edit.returnPressed.connect(self._on_confirm) # Handle Enter key
card_layout.addWidget(self.confirm_edit)
# Action buttons
button_layout = QHBoxLayout()
button_layout.setSpacing(12)
button_layout.addStretch()
cancel_btn = QPushButton("Cancel")
cancel_btn.setFixedSize(120, 36)
cancel_btn.clicked.connect(self.reject)
cancel_btn.setStyleSheet(
"QPushButton { "
" background-color: #95a5a6; "
" color: white; "
" border: none; "
" border-radius: 4px; "
" font-weight: bold; "
" padding: 8px 16px; "
"} "
"QPushButton:hover { "
" background-color: #7f8c8d; "
"} "
"QPushButton:pressed { "
" background-color: #6c7b7d; "
"}"
)
button_layout.addWidget(cancel_btn)
confirm_btn = QPushButton("Proceed")
confirm_btn.setFixedSize(120, 36)
confirm_btn.clicked.connect(self._on_confirm)
confirm_btn.setStyleSheet(
"QPushButton { "
" background-color: #e67e22; "
" color: white; "
" border: none; "
" border-radius: 4px; "
" font-weight: bold; "
" padding: 8px 16px; "
"} "
"QPushButton:hover { "
" background-color: #d35400; "
"} "
"QPushButton:pressed { "
" background-color: #b34700; "
"}"
)
button_layout.addWidget(confirm_btn)
button_layout.addStretch()
card_layout.addLayout(button_layout)
layout.addStretch()
layout.addWidget(card, alignment=Qt.AlignCenter)
layout.addStretch()
def _on_text_changed(self):
"""Reset error styling when user starts typing again."""
# Only reset if currently showing error state (darker background)
if "#3b2323" in self.confirm_edit.styleSheet():
self.confirm_edit.setStyleSheet(self._default_lineedit_style)
self.confirm_edit.setPlaceholderText("DELETE")
# Reset label but keep attempt counter if attempts were made
if self._failed_attempts > 0:
remaining = self._max_attempts - self._failed_attempts
self.confirm_label.setText(f"Type 'DELETE' to confirm (all caps) - {remaining} attempt(s) remaining:")
else:
self.confirm_label.setText("Type 'DELETE' to confirm (all caps):")
self.confirm_label.setStyleSheet(
"QLabel { "
" font-size: 13px; "
" color: #e67e22; "
" margin-bottom: 2px; "
"}"
)
def _on_confirm(self):
entered_text = self.confirm_edit.text().strip()
if entered_text == "DELETE":
# Correct - proceed
self.confirmed = True
self.accept()
else:
# Wrong text entered
self._failed_attempts += 1
if self._failed_attempts >= self._max_attempts:
# Too many failed attempts - cancel automatically
self.confirmed = False
self.reject()
return
# Still have attempts remaining - clear field and show error feedback
self.confirm_edit.clear()
# Update label to show remaining attempts
remaining = self._max_attempts - self._failed_attempts
self.confirm_label.setText(f"Wrong! Type 'DELETE' exactly (all caps) - {remaining} attempt(s) remaining:")
self.confirm_label.setStyleSheet(
"QLabel { "
" font-size: 13px; "
" color: #c0392b; " # Red for error
" margin-bottom: 2px; "
" font-weight: bold; "
"}"
)
# Show error state in text field
self.confirm_edit.setPlaceholderText(f"Type DELETE ({remaining} attempts left)")
self.confirm_edit.setStyleSheet(
"QLineEdit { "
" font-size: 15px; "
" border: 2px solid #c0392b; " # Red border for error
" border-radius: 6px; "
" padding: 6px; "
" background: #3b2323; " # Darker red background
" color: #e67e22; "
"}"
)