2025-07-01 23:08:05 +05:30
|
|
|
# --- Standard Library Imports ---
|
|
|
|
|
import sys
|
|
|
|
|
import os
|
|
|
|
|
import time
|
|
|
|
|
import traceback
|
2025-06-06 05:14:07 +01:00
|
|
|
|
2025-07-01 23:08:05 +05:30
|
|
|
# --- PyQt5 Imports ---
|
|
|
|
|
from PyQt5.QtWidgets import QApplication, QDialog
|
|
|
|
|
from PyQt5.QtCore import QCoreApplication
|
2025-05-24 10:36:15 +05:30
|
|
|
|
2025-07-01 23:08:05 +05:30
|
|
|
# --- Local Application Imports ---
|
|
|
|
|
from src.ui.main_window import DownloaderApp
|
|
|
|
|
from src.ui.dialogs.TourDialog import TourDialog
|
|
|
|
|
from src.config.constants import CONFIG_ORGANIZATION_NAME, CONFIG_APP_NAME_MAIN
|
2025-05-24 10:36:15 +05:30
|
|
|
|
2025-07-05 06:02:21 +05:30
|
|
|
# --- Define APP_BASE_DIR globally and make available early ---
|
|
|
|
|
if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
|
|
|
|
|
APP_BASE_DIR = sys._MEIPASS
|
|
|
|
|
else:
|
|
|
|
|
APP_BASE_DIR = os.path.abspath(os.path.dirname(__file__))
|
|
|
|
|
|
|
|
|
|
# Optional: Set a global variable or pass it into modules if needed
|
|
|
|
|
# Or re-export it via constants.py for cleaner imports
|
2025-05-24 10:36:15 +05:30
|
|
|
|
2025-07-01 23:08:05 +05:30
|
|
|
def handle_uncaught_exception(exc_type, exc_value, exc_traceback):
|
|
|
|
|
"""
|
|
|
|
|
Handles uncaught exceptions by logging them to a file for easier debugging,
|
|
|
|
|
especially for bundled applications.
|
|
|
|
|
"""
|
2025-07-05 06:02:21 +05:30
|
|
|
# Use APP_BASE_DIR to determine logging location
|
|
|
|
|
log_dir = os.path.join(APP_BASE_DIR, "logs")
|
2025-07-01 23:08:05 +05:30
|
|
|
log_file_path = os.path.join(log_dir, "uncaught_exceptions.log")
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
os.makedirs(os.path.dirname(log_file_path), exist_ok=True)
|
|
|
|
|
with open(log_file_path, "a", encoding="utf-8") as f:
|
|
|
|
|
f.write(f"Timestamp: {time.strftime('%Y-%m-%d %H:%M:%S')}\n")
|
|
|
|
|
traceback.print_exception(exc_type, exc_value, exc_traceback, file=f)
|
|
|
|
|
f.write("-" * 80 + "\n\n")
|
|
|
|
|
except Exception as log_ex:
|
|
|
|
|
# Fallback to stderr if logging to file fails
|
|
|
|
|
print(f"CRITICAL: Failed to write to uncaught_exceptions.log: {log_ex}", file=sys.stderr)
|
|
|
|
|
traceback.print_exception(exc_type, exc_value, exc_traceback, file=sys.stderr)
|
|
|
|
|
|
|
|
|
|
# Also call the default excepthook
|
|
|
|
|
sys.__excepthook__(exc_type, exc_value, exc_traceback)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
|
"""Main entry point for the Kemono Downloader application."""
|
|
|
|
|
|
|
|
|
|
# Set up global exception handling
|
|
|
|
|
sys.excepthook = handle_uncaught_exception
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
# Set up application metadata for QSettings
|
|
|
|
|
QCoreApplication.setOrganizationName(CONFIG_ORGANIZATION_NAME)
|
|
|
|
|
QCoreApplication.setApplicationName(CONFIG_APP_NAME_MAIN)
|
2025-06-24 16:31:28 +01:00
|
|
|
|
2025-07-01 23:08:05 +05:30
|
|
|
qt_app = QApplication(sys.argv)
|
2025-06-06 05:14:07 +01:00
|
|
|
|
2025-07-05 06:02:21 +05:30
|
|
|
# Create the main application window
|
2025-07-01 23:08:05 +05:30
|
|
|
downloader_app_instance = DownloaderApp()
|
2025-06-06 05:14:07 +01:00
|
|
|
|
2025-07-01 23:08:05 +05:30
|
|
|
# --- Window Sizing and Positioning ---
|
|
|
|
|
primary_screen = QApplication.primaryScreen()
|
|
|
|
|
if not primary_screen:
|
|
|
|
|
downloader_app_instance.resize(1024, 768)
|
2025-06-24 16:31:28 +01:00
|
|
|
else:
|
2025-07-01 23:08:05 +05:30
|
|
|
available_geo = primary_screen.availableGeometry()
|
|
|
|
|
screen_width = available_geo.width()
|
|
|
|
|
screen_height = available_geo.height()
|
2025-06-24 16:31:28 +01:00
|
|
|
|
2025-07-01 23:08:05 +05:30
|
|
|
min_app_width, min_app_height = 960, 680
|
|
|
|
|
desired_width_ratio, desired_height_ratio = 0.80, 0.85
|
2025-06-06 05:14:07 +01:00
|
|
|
|
2025-07-01 23:08:05 +05:30
|
|
|
app_width = max(min_app_width, int(screen_width * desired_width_ratio))
|
|
|
|
|
app_height = max(min_app_height, int(screen_height * desired_height_ratio))
|
2025-06-06 05:14:07 +01:00
|
|
|
|
2025-07-01 23:08:05 +05:30
|
|
|
app_width = min(app_width, screen_width)
|
|
|
|
|
app_height = min(app_height, screen_height)
|
|
|
|
|
|
|
|
|
|
downloader_app_instance.resize(app_width, app_height)
|
|
|
|
|
|
2025-07-05 06:02:21 +05:30
|
|
|
# Show and center the main window
|
2025-07-01 23:08:05 +05:30
|
|
|
downloader_app_instance.show()
|
|
|
|
|
if hasattr(downloader_app_instance, '_center_on_screen'):
|
|
|
|
|
downloader_app_instance._center_on_screen()
|
|
|
|
|
|
|
|
|
|
# --- First-Run Welcome Tour ---
|
|
|
|
|
if TourDialog.should_show_tour():
|
|
|
|
|
tour_dialog = TourDialog(parent_app=downloader_app_instance)
|
|
|
|
|
tour_dialog.exec_()
|
|
|
|
|
|
|
|
|
|
# --- Start Application ---
|
|
|
|
|
exit_code = qt_app.exec_()
|
|
|
|
|
print(f"Application finished with exit code: {exit_code}")
|
|
|
|
|
sys.exit(exit_code)
|
|
|
|
|
|
|
|
|
|
except SystemExit:
|
|
|
|
|
pass
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print("--- CRITICAL APPLICATION STARTUP ERROR ---")
|
|
|
|
|
print(f"An unhandled exception occurred during application startup: {e}")
|
|
|
|
|
traceback.print_exc()
|
|
|
|
|
print("--- END CRITICAL ERROR ---")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
2025-09-07 05:24:54 -07:00
|
|
|
main()
|