"""TTW installer management methods for InstallTTWScreen (Mixin).""" from pathlib import Path from PySide6.QtCore import QTimer import logging import os # Runtime imports to avoid circular dependencies from jackify.frontends.gui.services.message_service import MessageService # Runtime import logger = logging.getLogger(__name__) def debug_print(message): """Print debug message only if debug mode is enabled""" from jackify.backend.handlers.config_handler import ConfigHandler config_handler = ConfigHandler() if config_handler.get('debug_mode', False): print(message) class TTWInstallerMixin: """Mixin providing TTW installer management methods for InstallTTWScreen.""" def check_requirements(self): """Check and display requirements status""" from jackify.backend.handlers.path_handler import PathHandler from jackify.backend.handlers.filesystem_handler import FileSystemHandler from jackify.backend.handlers.config_handler import ConfigHandler from jackify.backend.models.configuration import SystemInfo path_handler = PathHandler() # Check game detection detected_games = path_handler.find_vanilla_game_paths() # Fallout 3 if 'Fallout 3' in detected_games: self.fallout3_status.setText("Fallout 3: Detected") self.fallout3_status.setStyleSheet("color: #3fd0ea;") else: self.fallout3_status.setText("Fallout 3: Not Found - Install from Steam") self.fallout3_status.setStyleSheet("color: #f44336;") # Fallout New Vegas if 'Fallout New Vegas' in detected_games: self.fnv_status.setText("Fallout New Vegas: Detected") self.fnv_status.setStyleSheet("color: #3fd0ea;") else: self.fnv_status.setText("Fallout New Vegas: Not Found - Install from Steam") self.fnv_status.setStyleSheet("color: #f44336;") # Update Start button state after checking requirements self._update_start_button_state() def _check_ttw_installer_status(self): """Check TTW_Linux_Installer installation status and update UI""" try: from jackify.backend.handlers.ttw_installer_handler import TTWInstallerHandler from jackify.backend.handlers.filesystem_handler import FileSystemHandler from jackify.backend.handlers.config_handler import ConfigHandler from jackify.backend.models.configuration import SystemInfo # Create handler instances filesystem_handler = FileSystemHandler() config_handler = ConfigHandler() system_info = SystemInfo(is_steamdeck=False) ttw_installer_handler = TTWInstallerHandler( steamdeck=False, verbose=False, filesystem_handler=filesystem_handler, config_handler=config_handler ) # Check if TTW_Linux_Installer is installed ttw_installer_handler._check_installation() if ttw_installer_handler.ttw_installer_installed: # Check version against latest update_available, installed_v, latest_v = ttw_installer_handler.is_ttw_installer_update_available() if update_available: version_text = f"Out of date (v{installed_v} → v{latest_v})" if installed_v and latest_v else "Out of date" self.ttw_installer_status.setText(version_text) self.ttw_installer_status.setStyleSheet("color: #f44336;") self.ttw_installer_btn.setText("Update now") self.ttw_installer_btn.setEnabled(True) self.ttw_installer_btn.setVisible(True) else: version_text = f"Ready (v{installed_v})" if installed_v else "Ready" self.ttw_installer_status.setText(version_text) self.ttw_installer_status.setStyleSheet("color: #3fd0ea;") self.ttw_installer_btn.setText("Update now") self.ttw_installer_btn.setEnabled(False) # Greyed out when ready self.ttw_installer_btn.setVisible(True) else: self.ttw_installer_status.setText("Not Found") self.ttw_installer_status.setStyleSheet("color: #f44336;") self.ttw_installer_btn.setText("Install now") self.ttw_installer_btn.setEnabled(True) self.ttw_installer_btn.setVisible(True) except Exception as e: self.ttw_installer_status.setText("Check Failed") self.ttw_installer_status.setStyleSheet("color: #f44336;") self.ttw_installer_btn.setText("Install now") self.ttw_installer_btn.setEnabled(True) self.ttw_installer_btn.setVisible(True) debug_print(f"DEBUG: TTW_Linux_Installer status check failed: {e}") def install_ttw_installer(self): """Install or update TTW_Linux_Installer""" # If not detected, show info dialog try: current_status = self.ttw_installer_status.text().strip() except Exception: current_status = "" if current_status == "Not Found": MessageService.information( self, "TTW_Linux_Installer Installation", ( "TTW_Linux_Installer is a native Linux installer for TTW and other MPI packages.

" "Project: github.com/SulfurNitride/TTW_Linux_Installer
" "Please star the repository and thank the developer.

" "Jackify will now download and install the pinned TTW_Linux_Installer version (0.0.7)." ), safety_level="low", ) # Update button to show installation in progress self.ttw_installer_btn.setText("Installing...") self.ttw_installer_btn.setEnabled(False) self.console.append("Installing/updating TTW_Linux_Installer...") # Create background thread for installation from PySide6.QtCore import QThread, Signal class InstallerDownloadThread(QThread): finished = Signal(bool, str) # success, message progress = Signal(str) # progress message def run(self): try: from jackify.backend.handlers.ttw_installer_handler import TTWInstallerHandler from jackify.backend.handlers.filesystem_handler import FileSystemHandler from jackify.backend.handlers.config_handler import ConfigHandler from jackify.backend.models.configuration import SystemInfo # Create handler instances filesystem_handler = FileSystemHandler() config_handler = ConfigHandler() system_info = SystemInfo(is_steamdeck=False) ttw_installer_handler = TTWInstallerHandler( steamdeck=False, verbose=False, filesystem_handler=filesystem_handler, config_handler=config_handler ) # Install TTW_Linux_Installer (this will download and extract) self.progress.emit("Downloading TTW_Linux_Installer...") success, message = ttw_installer_handler.install_ttw_installer() if success: install_path = ttw_installer_handler.ttw_installer_dir self.progress.emit(f"Installation complete: {install_path}") else: self.progress.emit(f"Installation failed: {message}") self.finished.emit(success, message) except Exception as e: error_msg = f"Error installing TTW_Linux_Installer: {str(e)}" self.progress.emit(error_msg) debug_print(f"DEBUG: TTW_Linux_Installer installation error: {e}") self.finished.emit(False, error_msg) # Create and start thread self.installer_download_thread = InstallerDownloadThread() self.installer_download_thread.progress.connect(self._on_installer_download_progress) self.installer_download_thread.finished.connect(self._on_installer_download_finished) self.installer_download_thread.start() # Update Activity window to show download in progress self.file_progress_list.clear() self.file_progress_list.update_or_add_item( item_id="ttw_installer_download", label="Downloading TTW_Linux_Installer...", progress=0 ) def _on_installer_download_progress(self, message): """Handle installer download progress updates""" self.console.append(message) # Update Activity window based on progress message if "Downloading" in message: self.file_progress_list.update_or_add_item( item_id="ttw_installer_download", label="Downloading TTW_Linux_Installer...", progress=0 # Indeterminate progress ) elif "Extracting" in message or "extracting" in message.lower(): self.file_progress_list.update_or_add_item( item_id="ttw_installer_download", label="Extracting TTW_Linux_Installer...", progress=50 ) elif "complete" in message.lower() or "successfully" in message.lower(): self.file_progress_list.update_or_add_item( item_id="ttw_installer_download", label="TTW_Linux_Installer ready", progress=100 ) def _on_installer_download_finished(self, success, message): """Handle installer download completion""" if success: self.console.append("TTW_Linux_Installer installed successfully") # Clear Activity window after successful installation self.file_progress_list.clear() # Re-check status after installation (this will update button state correctly) self._check_ttw_installer_status() self._update_start_button_state() else: self.console.append(f"Installation failed: {message}") # Clear Activity window on failure self.file_progress_list.clear() # Re-enable button on failure so user can retry self.ttw_installer_btn.setText("Install now") self.ttw_installer_btn.setEnabled(True) def _check_ttw_requirements(self): """Check TTW requirements before installation""" from jackify.backend.handlers.path_handler import PathHandler path_handler = PathHandler() # Check game detection detected_games = path_handler.find_vanilla_game_paths() missing_games = [] if 'Fallout 3' not in detected_games: missing_games.append("Fallout 3") if 'Fallout New Vegas' not in detected_games: missing_games.append("Fallout New Vegas") if missing_games: MessageService.warning( self, "Missing Required Games", f"TTW requires both Fallout 3 and Fallout New Vegas to be installed.\n\nMissing: {', '.join(missing_games)}" ) return False # Check TTW_Linux_Installer using the status we already checked status_text = self.ttw_installer_status.text() if status_text in ("Not Found", "Check Failed"): MessageService.warning( self, "TTW_Linux_Installer Required", "TTW_Linux_Installer is required for TTW installation but is not installed.\n\nPlease install TTW_Linux_Installer using the 'Install now' button." ) return False return True # Now collect all actionable controls after UI is fully built self._collect_actionable_controls() # Check if all requirements are met and enable/disable Start button self._update_start_button_state() def _update_start_button_state(self): """Enable/disable Start button based on requirements and file selection""" # Check if all requirements are met requirements_met = self._check_ttw_requirements() # Check if .mpi file is selected mpi_file_selected = bool(self.file_edit.text().strip()) # Enable Start button only if both requirements are met and file is selected self.start_btn.setEnabled(requirements_met and mpi_file_selected) # Update button text to indicate what's missing if not requirements_met: self.start_btn.setText("Requirements Not Met") elif not mpi_file_selected: self.start_btn.setText("Select TTW .mpi File") else: self.start_btn.setText("Start Installation")