forked from Support/sp-hydra-veil-gui
Restore accidentally deleted popup files
This commit is contained in:
parent
7a8c4ded60
commit
42e06b71c2
2 changed files with 340 additions and 0 deletions
290
gui/v2/ui/popups/Database_version.py
Normal file
290
gui/v2/ui/popups/Database_version.py
Normal 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
|
||||||
50
gui/v2/ui/popups/pick_folder_to_move.py
Normal file
50
gui/v2/ui/popups/pick_folder_to_move.py
Normal 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)
|
||||||
Loading…
Reference in a new issue