from core.Constants import Constants from PyQt6.QtWidgets import QApplication, QDialog, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QFrame, QScrollArea from PyQt6.QtCore import Qt, QSize from PyQt6.QtGui import QIcon, QFont, QColor, QPalette, QPixmap, QPainter import sys APP_VERSION = Constants.DB_VERSION_THIS_APP_WANTS class DatabaseConflictDialog(QDialog): WIPE = 1 MOVE_DB = 2 EXIT = 3 def __init__(self, check: dict, parent=None): super().__init__(parent) self.setWindowTitle("Database Recovery") self.setModal(True) self.user_choice = self.EXIT self.setMinimumWidth(550) self.setMinimumHeight(400) self.setMaximumWidth(750) self.setMaximumHeight(600) # Modern dark theme self.setStyleSheet(""" DatabaseConflictDialog { background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #0f172a, stop:1 #1e293b); } """) main_layout = QVBoxLayout() main_layout.setContentsMargins(0, 0, 0, 0) main_layout.setSpacing(0) # Header with gradient and icon header = QFrame() header.setStyleSheet(""" QFrame { background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #3b82f6, stop:1 #1e40af); border: none; } """) header.setFixedHeight(100) header_layout = QHBoxLayout() header_layout.setContentsMargins(30, 20, 30, 20) # Warning icon (using unicode) icon_label = QLabel("⚠️") icon_label.setFont(QFont("Segoe UI", 48)) header_layout.addWidget(icon_label, 0, Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter) # Title title_layout = QVBoxLayout() title_layout.setSpacing(5) title = QLabel("Database Compatibility") title.setFont(QFont("Segoe UI", 18, QFont.Weight.Bold)) title.setStyleSheet("color: white;") title_layout.addWidget(title) subtitle = QLabel("Your App version and Database don't match") subtitle.setFont(QFont("Segoe UI", 11)) subtitle.setStyleSheet("color: rgba(255, 255, 255, 0.8);") title_layout.addWidget(subtitle) header_layout.addLayout(title_layout, 1) header.setLayout(header_layout) main_layout.addWidget(header) # Content area with scroll support content = QFrame() content.setStyleSheet(""" QFrame { background: #1e293b; border: none; } """) content_layout = QVBoxLayout() content_layout.setContentsMargins(0, 0, 0, 0) content_layout.setSpacing(0) # Scrollable area for dynamic content scroll_area = QScrollArea() scroll_area.setWidgetResizable(True) scroll_area.setStyleSheet(""" QScrollArea { background: #1e293b; border: none; } QScrollBar:vertical { background: #1e293b; width: 12px; } QScrollBar::handle:vertical { background: #475569; border-radius: 6px; min-height: 20px; } QScrollBar::handle:vertical:hover { background: #64748b; } QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical { border: none; } """) # Inner scrollable widget scroll_widget = QFrame() scroll_widget.setStyleSheet("background: #1e293b; border: none;") scroll_layout = QVBoxLayout() scroll_layout.setContentsMargins(40, 30, 40, 30) scroll_layout.setSpacing(15) # Main message message = QLabel(check["message"]) message.setFont(QFont("Segoe UI", 12)) message.setStyleSheet("color: #e2e8f0; line-height: 1.6;") message.setWordWrap(True) scroll_layout.addWidget(message) # Version info if check.get("db_version"): info_frame = QFrame() info_frame.setStyleSheet(""" QFrame { background: rgba(59, 130, 246, 0.1); border: 1px solid rgba(59, 130, 246, 0.3); border-radius: 6px; } """) info_layout = QVBoxLayout() info_layout.setContentsMargins(15, 12, 15, 12) info_layout.setSpacing(5) app_ver = QLabel(f"App is looking for database version: {APP_VERSION}") app_ver.setFont(QFont("Segoe UI", 10)) app_ver.setStyleSheet("color: #94a3b8;") info_layout.addWidget(app_ver) db_ver = QLabel(f"Your Actual Database version: {check['db_version']}") db_ver.setFont(QFont("Segoe UI", 10)) db_ver.setStyleSheet("color: #94a3b8;") info_layout.addWidget(db_ver) info_frame.setLayout(info_layout) scroll_layout.addWidget(info_frame) scroll_layout.addStretch() scroll_widget.setLayout(scroll_layout) scroll_area.setWidget(scroll_widget) content_layout.addWidget(scroll_area, 1) content.setLayout(content_layout) main_layout.addWidget(content, 1) # Button area button_area = QFrame() button_area.setStyleSheet(""" QFrame { background: #0f172a; border-top: 1px solid #334155; } """) button_layout = QVBoxLayout() button_layout.setContentsMargins(40, 20, 40, 20) button_layout.setSpacing(12) if check["status"] == "version_mismatch": btn_backup = self._create_button( "Create a Fresh Database. Then restart (recommended)", "primary", "✅" ) btn_backup.clicked.connect(self.on_wipe_create) button_layout.addWidget(btn_backup) btn_different = self._create_button( "Move the Stale Database for Debug Purposes", "secondary", "📁" ) btn_different.clicked.connect(self.on_move_db) button_layout.addWidget(btn_different) btn_exit = self._create_button( "Exit App without action.", "danger", "❌" ) btn_exit.clicked.connect(self.on_exit) button_layout.addWidget(btn_exit) button_area.setLayout(button_layout) main_layout.addWidget(button_area) self.setLayout(main_layout) def _create_button(self, text, style_type, icon): """Create a styled button""" btn = QPushButton(f" {icon} {text}") btn.setFont(QFont("Segoe UI", 11, QFont.Weight.Medium)) btn.setFixedHeight(45) btn.setCursor(Qt.CursorShape.PointingHandCursor) if style_type == "primary": btn.setStyleSheet(""" QPushButton { background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #3b82f6, stop:1 #2563eb); color: white; border: none; border-radius: 6px; font-weight: 600; } QPushButton:hover { background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #2563eb, stop:1 #1d4ed8); } QPushButton:pressed { background: #1d4ed8; } """) elif style_type == "secondary": btn.setStyleSheet(""" QPushButton { background: #334155; color: #e2e8f0; border: 1px solid #475569; border-radius: 6px; font-weight: 600; } QPushButton:hover { background: #475569; border: 1px solid #64748b; } QPushButton:pressed { background: #1e293b; } """) elif style_type == "danger": btn.setStyleSheet(""" QPushButton { background: #64748b; color: #e2e8f0; border: 1px solid #475569; border-radius: 6px; font-weight: 600; } QPushButton:hover { background: #ef4444; border: 1px solid #dc2626; } QPushButton:pressed { background: #dc2626; } """) return btn def on_wipe_create(self): self.user_choice = self.WIPE self.accept() def on_move_db(self): self.user_choice = self.MOVE_DB self.accept() def on_exit(self): self.user_choice = self.EXIT self.reject() def show_recovery_dialog(check: dict): """Show recovery dialog as standalone app and return user choice""" app = QApplication.instance() or QApplication(sys.argv) dialog = DatabaseConflictDialog(check) dialog.exec() return dialog.user_choice