Restore accidentally deleted popup files

This commit is contained in:
JOhn 2026-07-01 11:25:03 -04:00
parent 7a8c4ded60
commit 42e06b71c2
2 changed files with 340 additions and 0 deletions

View file

@ -0,0 +1,290 @@
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 Section. ##############
# First which messages to display,
if check["status"] == "version_mismatch":
error_title = "Database Compatibility"
error_subtitle = "Your App version and Database don't match"
else:
error_title = "Database Error"
error_subtitle = "The Database can't properly start"
# then display them:
title_layout = QVBoxLayout()
title_layout.setSpacing(5)
title = QLabel(error_title)
title.setFont(QFont("Segoe UI", 18, QFont.Weight.Bold))
title.setStyleSheet("color: white;")
title_layout.addWidget(title)
subtitle = QLabel(error_subtitle)
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

View file

@ -0,0 +1,50 @@
import shutil
import sys
from pathlib import Path
from PyQt6.QtWidgets import QApplication, QFileDialog
def move_database_file(original_filepath: str) -> bool:
"""
Prompts the user to select a destination for a .db file and moves it there.
Args:
original_filepath: The current path to the .db file
Returns:
True if the move was successful, False otherwise
"""
# Create a QApplication if one doesn't already exist
app = QApplication.instance()
if app is None:
app = QApplication(sys.argv)
# Validate that the original file exists
if not Path(original_filepath).exists():
print(f"Error: File not found at {original_filepath}")
return False
# Open the file save dialog
destination, _ = QFileDialog.getSaveFileName(
None,
"Select destination for database file",
str(Path(original_filepath).parent), # Start in the original file's directory
"Database Files (*.db);;All Files (*)"
)
# If the user cancelled the dialog
if not destination:
print("Operation cancelled by user")
return False
try:
# Move the file
shutil.move(original_filepath, destination)
print(f"File successfully moved to: {destination}")
return True
except Exception as e:
print(f"Error moving file: {e}")
return False
def launch_file_picker(original_path):
move_database_file(original_path)