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()