mirror of
https://github.com/Omni-guides/Jackify.git
synced 2026-06-08 00:07:45 +02:00
209 lines
9.1 KiB
Python
209 lines
9.1 KiB
Python
"""VNV automation methods for InstallModlistScreen (Mixin)."""
|
|
from pathlib import Path
|
|
from PySide6.QtCore import QTimer
|
|
import logging
|
|
import os
|
|
from typing import Optional
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class VNVAutomationMixin:
|
|
"""Mixin providing VNV automation methods for InstallModlistScreen."""
|
|
|
|
def _check_and_run_vnv_automation(self, modlist_name: str, install_dir: str) -> bool:
|
|
"""Check if VNV automation should run and execute if applicable in background thread
|
|
|
|
Args:
|
|
modlist_name: Name of the installed modlist
|
|
install_dir: Installation directory path
|
|
|
|
Returns:
|
|
True if VNV automation is starting (success dialog should be deferred)
|
|
False if no VNV automation needed (show success dialog immediately)
|
|
"""
|
|
try:
|
|
from jackify.backend.services.vnv_integration_helper import should_offer_vnv_automation
|
|
from jackify.backend.handlers.path_handler import PathHandler
|
|
from jackify.backend.services.vnv_post_install_service import VNVPostInstallService
|
|
from jackify.backend.services.automated_prefix_service import AutomatedPrefixService
|
|
|
|
# Get paths first (needed for VNV detection)
|
|
install_path = Path(install_dir)
|
|
|
|
# Quick check before importing more (pass install location for ModOrganizer.ini check)
|
|
if not should_offer_vnv_automation(modlist_name, install_path):
|
|
return False
|
|
|
|
game_paths = PathHandler().find_vanilla_game_paths()
|
|
game_root = game_paths.get('Fallout New Vegas')
|
|
|
|
if not game_root:
|
|
from .install_modlist import debug_print
|
|
debug_print("DEBUG: VNV automation skipped - FNV game root not found")
|
|
return False
|
|
|
|
# Initialize service to check completion status
|
|
vnv_service = VNVPostInstallService(
|
|
modlist_install_location=install_path,
|
|
game_root=game_root,
|
|
ttw_installer_path=AutomatedPrefixService.get_ttw_installer_path()
|
|
)
|
|
|
|
# Check what's already done
|
|
completed = vnv_service.check_already_completed()
|
|
# Only skip if ALL three steps are completed
|
|
if completed['root_mods'] and completed['4gb_patch'] and completed['bsa_decompressed']:
|
|
logger.info("VNV automation steps already completed")
|
|
return False
|
|
|
|
# Get automation description for confirmation
|
|
description = vnv_service.get_automation_description()
|
|
|
|
# Show confirmation dialog ON MAIN THREAD (not in worker thread!)
|
|
from ..services.message_service import MessageService
|
|
from PySide6.QtWidgets import QMessageBox
|
|
reply = MessageService.question(
|
|
self,
|
|
"VNV Post-Install Automation",
|
|
description,
|
|
critical=False,
|
|
safety_level="medium"
|
|
)
|
|
|
|
if reply != QMessageBox.Yes:
|
|
logger.info("User declined VNV automation")
|
|
return False
|
|
|
|
# Enable post-install progress tracking for VNV automation
|
|
self._begin_post_install_feedback()
|
|
|
|
# User confirmed - start automation in background thread
|
|
# Note: manual_file_callback is not passed because Qt GUI operations
|
|
# cannot be called from a background thread. If downloads fail,
|
|
# the service will return instructions for manual download instead.
|
|
self._run_vnv_automation_threaded(
|
|
modlist_name,
|
|
install_path,
|
|
game_root
|
|
)
|
|
|
|
return True # VNV automation is running, defer success dialog
|
|
|
|
except Exception as e:
|
|
from .install_modlist import debug_print
|
|
debug_print(f"ERROR: Failed to start VNV automation: {e}")
|
|
import traceback
|
|
debug_print(f"Traceback: {traceback.format_exc()}")
|
|
return False # Error - show success dialog anyway
|
|
|
|
def _run_vnv_automation_threaded(self, modlist_name, install_path, game_root):
|
|
"""Run VNV automation in a background thread with progress updates
|
|
|
|
Note: User confirmation should already be obtained before calling this method.
|
|
Manual file selection is not supported from background threads - if downloads
|
|
fail, the service will return instructions for manual download.
|
|
"""
|
|
from PySide6.QtCore import QThread, Signal
|
|
from jackify.backend.services.vnv_integration_helper import run_vnv_automation_if_applicable
|
|
from jackify.backend.services.automated_prefix_service import AutomatedPrefixService
|
|
|
|
class VNVAutomationWorker(QThread):
|
|
progress_update = Signal(str)
|
|
completed = Signal(bool, str) # (success, error_message)
|
|
|
|
def __init__(self, modlist_name, install_path, game_root, ttw_installer_path):
|
|
super().__init__()
|
|
self.modlist_name = modlist_name
|
|
self.install_path = install_path
|
|
self.game_root = game_root
|
|
self.ttw_installer_path = ttw_installer_path
|
|
|
|
def run(self):
|
|
try:
|
|
# User already confirmed, pass lambda that always returns True
|
|
# manual_file_callback is None - downloads that fail will return
|
|
# instructions for manual download instead of showing Qt dialogs
|
|
automation_ran, error = run_vnv_automation_if_applicable(
|
|
modlist_name=self.modlist_name,
|
|
modlist_install_location=self.install_path,
|
|
game_root=self.game_root,
|
|
ttw_installer_path=self.ttw_installer_path,
|
|
progress_callback=self.progress_update.emit,
|
|
manual_file_callback=None,
|
|
confirmation_callback=lambda desc: True # Already confirmed on main thread
|
|
)
|
|
self.completed.emit(error is None, error or "")
|
|
except Exception as e:
|
|
import traceback
|
|
self.completed.emit(False, f"Exception: {str(e)}\n{traceback.format_exc()}")
|
|
|
|
# Create and start worker
|
|
self.vnv_worker = VNVAutomationWorker(
|
|
modlist_name,
|
|
install_path,
|
|
game_root,
|
|
AutomatedPrefixService.get_ttw_installer_path()
|
|
)
|
|
|
|
# Connect signals
|
|
self.vnv_worker.progress_update.connect(self._on_vnv_progress)
|
|
self.vnv_worker.completed.connect(self._on_vnv_complete)
|
|
self.vnv_worker.finished.connect(self.vnv_worker.deleteLater)
|
|
|
|
# Start worker
|
|
self.vnv_worker.start()
|
|
|
|
def _on_vnv_progress(self, message: str):
|
|
"""Handle VNV automation progress updates"""
|
|
self._safe_append_text(message)
|
|
# Also update progress indicator, Activity window, and Details window
|
|
self._handle_post_install_progress(message)
|
|
|
|
def _on_vnv_complete(self, success: bool, error: str):
|
|
"""Handle VNV automation completion and show deferred success dialog"""
|
|
# End post-install feedback now that VNV automation is complete
|
|
self._end_post_install_feedback(True)
|
|
|
|
if not success and error:
|
|
from ..services.message_service import MessageService
|
|
MessageService.warning(
|
|
self,
|
|
"VNV Automation Failed",
|
|
f"VNV post-install automation encountered an error:\n\n{error}\n\n"
|
|
"You can complete these steps manually by following the guide at:\n"
|
|
"https://vivanewvegas.moddinglinked.com/wabbajack.html"
|
|
)
|
|
elif success:
|
|
self._safe_append_text("VNV post-install automation completed successfully")
|
|
|
|
# Show the deferred success dialog now that VNV automation is complete
|
|
if hasattr(self, '_pending_success_dialog_params'):
|
|
params = self._pending_success_dialog_params
|
|
del self._pending_success_dialog_params # Clean up
|
|
|
|
# Clear Activity window before showing success dialog
|
|
self.file_progress_list.clear()
|
|
|
|
# Show success dialog
|
|
from ..dialogs import SuccessDialog
|
|
success_dialog = SuccessDialog(
|
|
modlist_name=params['modlist_name'],
|
|
workflow_type="install",
|
|
time_taken=params['time_taken'],
|
|
game_name=params['game_name'],
|
|
parent=self
|
|
)
|
|
success_dialog.show()
|
|
|
|
# Show ENB Proton dialog if ENB was detected
|
|
if params.get('enb_detected'):
|
|
try:
|
|
from ..dialogs.enb_proton_dialog import ENBProtonDialog
|
|
enb_dialog = ENBProtonDialog(modlist_name=params['modlist_name'], parent=self)
|
|
enb_dialog.exec() # Modal dialog - blocks until user clicks OK
|
|
except Exception as e:
|
|
# Non-blocking: if dialog fails, just log and continue
|
|
logger.warning(f"Failed to show ENB dialog: {e}")
|
|
|