from PyQt6.QtWidgets import (
QApplication, QDialog, QWidget, QPushButton, QLabel, QVBoxLayout, QHBoxLayout
)
from PyQt6.QtGui import QFont, QGuiApplication
from PyQt6.QtCore import Qt, QTimer
class TicketDataLossPopup(QDialog):
def __init__(self, parent=None, ticket_number="", billing_code=""):
super().__init__(parent)
self.parent_window = parent
self._use_parent_local_geometry = QGuiApplication.platformName().lower().startswith("wayland")
self.ticket_number = str(ticket_number)
self.billing_code = str(billing_code)
self.initUI()
def initUI(self):
self.setFixedSize(640, 380)
if self._use_parent_local_geometry:
if self.parent_window is not None:
self.setParent(self.parent_window)
self.setWindowFlags(Qt.WindowType.Widget)
else:
self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.FramelessWindowHint)
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
outer = QVBoxLayout(self)
outer.setContentsMargins(0, 0, 0, 0)
bg = QWidget(self)
bg.setStyleSheet("""
background-color: white;
border-radius: 12px;
border: 2px solid #ff4d4d;
""")
outer.addWidget(bg)
content = QVBoxLayout(bg)
content.setContentsMargins(24, 10, 24, 14)
content.setSpacing(8)
top_row = QHBoxLayout()
top_row.setContentsMargins(0, 0, 0, 0)
header = QLabel("Critical Error")
header.setFont(QFont("Arial", 18, QFont.Weight.Bold))
header.setStyleSheet(
"color: #ff3333; border: none; background: transparent;")
header.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter)
top_row.addWidget(header)
top_row.addStretch()
close_button = QPushButton("✕")
close_button.setStyleSheet("""
QPushButton {
background-color: transparent;
color: #888888;
font-size: 18px;
font-weight: bold;
border: none;
}
QPushButton:hover { color: #ff4d4d; }
""")
close_button.setFixedSize(28, 28)
close_button.clicked.connect(self.close)
top_row.addWidget(close_button)
content.addLayout(top_row)
ticket_html = (
f""
f"#{self.ticket_number}"
)
code_html = (
f""
f"{self.billing_code}"
)
message_html = (
"
"
f"
There was a serious error. "
f"You used up ticket {ticket_html}, but the subscription code you "
f"received {code_html} is invalid.
"
"
Please contact customer support "
"immediately with this data.
"
"
Do not hit Enable on this "
"profile again until this is resolved — every retry burns another "
"ticket.
"
"
"
)
message_label = QLabel(message_html)
message_label.setFont(QFont("Arial", 11))
message_label.setTextFormat(Qt.TextFormat.RichText)
message_label.setWordWrap(True)
message_label.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignTop)
message_label.setStyleSheet("border: none; background: transparent;")
content.addWidget(message_label, 1)
copy_row = QHBoxLayout()
copy_row.addStretch()
self.copy_button = QPushButton("Copy Billing Code")
self.copy_button.setFixedSize(200, 36)
self.copy_button.setFont(QFont("Arial", 10, QFont.Weight.Bold))
self.copy_button.setCursor(Qt.CursorShape.PointingHandCursor)
self._copy_button_default_style = """
QPushButton {
background-color: #ffffff;
border: 2px solid #ff4d4d;
color: #ff4d4d;
border-radius: 6px;
padding: 0 12px;
}
QPushButton:hover {
background-color: #fff0f0;
}
"""
self._copy_button_copied_style = """
QPushButton {
background-color: #28a745;
border: 2px solid #28a745;
color: white;
border-radius: 6px;
padding: 0 12px;
}
"""
self.copy_button.setStyleSheet(self._copy_button_default_style)
self.copy_button.clicked.connect(self._on_copy_billing_code)
copy_row.addWidget(self.copy_button)
copy_row.addStretch()
content.addLayout(copy_row)
button_row = QHBoxLayout()
button_row.addStretch()
action_button = QPushButton("Acknowledge")
action_button.setFixedSize(160, 40)
action_button.setFont(QFont("Arial", 11, QFont.Weight.Bold))
action_button.setStyleSheet("""
QPushButton {
background-color: #ff4d4d;
border: none;
color: white;
border-radius: 6px;
font-weight: bold;
}
QPushButton:hover { background-color: #ff3333; }
""")
action_button.clicked.connect(self._on_acknowledge)
button_row.addWidget(action_button)
button_row.addStretch()
content.addLayout(button_row)
if not self._use_parent_local_geometry:
self.setWindowModality(Qt.WindowModality.ApplicationModal)
def _on_acknowledge(self):
self.accept()
def _on_copy_billing_code(self):
QApplication.clipboard().setText(self.billing_code)
self.copy_button.setText("Copied!")
self.copy_button.setStyleSheet(self._copy_button_copied_style)
QTimer.singleShot(1500, self._reset_copy_button)
def _reset_copy_button(self):
self.copy_button.setText("Copy Billing Code")
self.copy_button.setStyleSheet(self._copy_button_default_style)
def show(self):
self._center_on_parent()
super().show()
def showEvent(self, event):
super().showEvent(event)
self._center_on_parent()
QTimer.singleShot(0, self._center_on_parent)
def _center_on_parent(self):
parent = self.parent_window
if parent is None:
return
try:
if not hasattr(parent, 'mapToGlobal') or not hasattr(parent, 'rect'):
return
parent_local_rect = parent.rect()
if parent_local_rect.isEmpty():
return
my_size = self.size()
if my_size.isEmpty() or my_size.width() <= 0 or my_size.height() <= 0:
my_size = self.sizeHint()
if self._use_parent_local_geometry:
target_x = parent_local_rect.x() + (parent_local_rect.width() - my_size.width()) // 2
target_y = parent_local_rect.y() + (parent_local_rect.height() - my_size.height()) // 2
target_x = max(parent_local_rect.left(), min(target_x, parent_local_rect.right() - my_size.width() + 1))
target_y = max(parent_local_rect.top(), min(target_y, parent_local_rect.bottom() - my_size.height() + 1))
else:
parent_center = parent.mapToGlobal(parent_local_rect.center())
target_x = parent_center.x() - my_size.width() // 2
target_y = parent_center.y() - my_size.height() // 2
screen = None
if hasattr(parent, 'screen'):
try:
screen = parent.screen()
except Exception:
screen = None
if screen is not None:
avail = screen.availableGeometry()
target_x = max(avail.left(), min(target_x, avail.right() - my_size.width()))
target_y = max(avail.top(), min(target_y, avail.bottom() - my_size.height()))
self.setGeometry(target_x, target_y, my_size.width(), my_size.height())
if self._use_parent_local_geometry:
self.raise_()
self.setFocus(Qt.FocusReason.PopupFocusReason)
except Exception:
pass
def mousePressEvent(self, event):
self.oldPos = event.globalPosition().toPoint()
def mouseMoveEvent(self, event):
delta = event.globalPosition().toPoint() - self.oldPos
self.move(self.x() + delta.x(), self.y() + delta.y())
self.oldPos = event.globalPosition().toPoint()