-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
150 lines (125 loc) · 5.03 KB
/
main.py
File metadata and controls
150 lines (125 loc) · 5.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
"""
Aura — Main Entry Point
Initializes the application, database, and launches either the setup wizard
or the main window depending on first_run_complete status.
"""
import sys
import os
# Ensure the app directory is in the Python path
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from PySide6.QtWidgets import QApplication
from PySide6.QtGui import QFontDatabase, QFont
from PySide6.QtCore import Qt
from config import APP_NAME, FONTS_DIR
from database.db_manager import DatabaseManager
from core.key_vault import KeyVault
from utils.logger import get_logger
logger = get_logger("main")
def load_fonts():
"""Load custom fonts from the assets directory."""
if FONTS_DIR.exists():
for font_file in FONTS_DIR.glob("*.ttf"):
font_id = QFontDatabase.addApplicationFont(str(font_file))
if font_id >= 0:
families = QFontDatabase.applicationFontFamilies(font_id)
logger.debug(f"Loaded font: {families}")
else:
logger.warning(f"Failed to load font: {font_file}")
def main():
"""Application entry point."""
# Enable high-DPI scaling
QApplication.setHighDpiScaleFactorRoundingPolicy(
Qt.HighDpiScaleFactorRoundingPolicy.PassThrough
)
app = QApplication(sys.argv)
app.setApplicationName(APP_NAME)
app.setStyle("Fusion") # Consistent cross-platform base style
# Load custom fonts
load_fonts()
# Set default font
default_font = QFont("Inter", 10)
default_font.setHintingPreference(QFont.HintingPreference.PreferFullHinting)
app.setFont(default_font)
# Initialize database
logger.info(f"Starting {APP_NAME}...")
db_manager = DatabaseManager()
db_manager.init_db()
db_manager.migrate_schema()
db_manager.seed_defaults()
db_manager.seed_default_agents()
logger.info("Database initialized.")
# Initialize key vault
key_vault = KeyVault()
# Migrate any keys still encrypted with the legacy salt
_settings_for_migration = db_manager.get_settings()
if _settings_for_migration:
_enc_fields = [f for f in dir(_settings_for_migration) if f.endswith("_enc") and getattr(_settings_for_migration, f, None)]
_migrated = False
for _field in _enc_fields:
_old_ct = getattr(_settings_for_migration, _field)
_new_ct = key_vault.migrate_ciphertext(_old_ct)
if _new_ct:
from database.schema import Settings
with db_manager.session_scope() as session:
s = session.query(Settings).first()
setattr(s, _field, _new_ct)
_migrated = True
if _migrated:
logger.info("Migrated encrypted keys to new per-install salt")
# Detect hardware change (all encrypted keys fail to decrypt)
_hardware_change = False
_settings_check = db_manager.get_settings()
if _settings_check:
_enc_fields_check = [f for f in dir(_settings_check) if f.endswith("_enc") and getattr(_settings_check, f, None)]
if _enc_fields_check:
_all_failed = all(
not key_vault.decrypt(getattr(_settings_check, f))
for f in _enc_fields_check
)
if _all_failed:
logger.warning("All encrypted keys failed to decrypt — possible hardware change")
_hardware_change = True
# Check first-run status
settings = db_manager.get_settings()
if settings and not settings.first_run_complete:
# Show setup wizard
logger.info("First run detected — launching setup wizard.")
from ui.setup_wizard import SetupWizard
wizard = SetupWizard(db_manager, key_vault)
result = wizard.exec()
if result != SetupWizard.DialogCode.Accepted:
# User closed wizard without finishing — exit app
logger.info("Setup wizard cancelled. Exiting.")
sys.exit(0)
# Determine theme
settings = db_manager.get_settings()
theme = settings.theme if settings else "light"
# Launch main window
from ui.main_window import MainWindow
window = MainWindow(db_manager=db_manager, key_vault=key_vault)
window._apply_theme(theme)
window.show()
logger.info("Main window launched.")
if _hardware_change:
from ui.components.toast_notification import show_toast
show_toast(
window,
"Hardware change detected. Your API keys could not be decrypted. "
"Please re-enter them in Settings → API Keys.",
toast_type="warning",
duration=8000,
)
sys.exit(app.exec())
if __name__ == "__main__":
# Handle browser installation subprocess for frozen app
if "--install-browser" in sys.argv:
try:
from playwright.__main__ import main as pw_main
sys.argv = [sys.argv[0], "install", "chromium"]
pw_main()
except SystemExit:
pass
except Exception as e:
print(f"Failed to install browser: {e}")
sys.exit(0)
main()