mirror of
https://github.com/Omni-guides/Jackify.git
synced 2026-01-17 19:47:00 +01:00
Sync from development - prepare for v0.1.5.1
This commit is contained in:
@@ -884,7 +884,12 @@ class JackifyMainWindow(QMainWindow):
|
||||
self._check_protontricks_on_startup()
|
||||
|
||||
def _debug_screen_change(self, index):
|
||||
"""Debug method to track screen changes"""
|
||||
"""Handle screen changes - debug logging and state reset"""
|
||||
# Reset screen state when switching to workflow screens
|
||||
widget = self.stacked_widget.widget(index)
|
||||
if widget and hasattr(widget, 'reset_screen_to_defaults'):
|
||||
widget.reset_screen_to_defaults()
|
||||
|
||||
# Only show debug info if debug mode is enabled
|
||||
from jackify.backend.handlers.config_handler import ConfigHandler
|
||||
config_handler = ConfigHandler()
|
||||
|
||||
10
jackify/frontends/gui/mixins/__init__.py
Normal file
10
jackify/frontends/gui/mixins/__init__.py
Normal file
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
GUI Mixins Package
|
||||
Reusable mixins for GUI functionality
|
||||
"""
|
||||
|
||||
from .operation_lock_mixin import OperationLockMixin
|
||||
|
||||
__all__ = ['OperationLockMixin']
|
||||
66
jackify/frontends/gui/mixins/operation_lock_mixin.py
Normal file
66
jackify/frontends/gui/mixins/operation_lock_mixin.py
Normal file
@@ -0,0 +1,66 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Operation Lock Mixin
|
||||
Provides reliable button state management for GUI operations
|
||||
"""
|
||||
|
||||
from contextlib import contextmanager
|
||||
|
||||
|
||||
class OperationLockMixin:
|
||||
"""
|
||||
Mixin that provides reliable button state management.
|
||||
Ensures controls are always re-enabled after operations, even if exceptions occur.
|
||||
"""
|
||||
|
||||
def operation_lock(self):
|
||||
"""
|
||||
Context manager that ensures controls are always re-enabled after operations.
|
||||
|
||||
Usage:
|
||||
with self.operation_lock():
|
||||
# Perform operation that might fail
|
||||
risky_operation()
|
||||
# Controls are guaranteed to be re-enabled here
|
||||
"""
|
||||
@contextmanager
|
||||
def lock_manager():
|
||||
try:
|
||||
if hasattr(self, '_disable_controls_during_operation'):
|
||||
self._disable_controls_during_operation()
|
||||
yield
|
||||
finally:
|
||||
# Ensure controls are re-enabled even if exceptions occur
|
||||
if hasattr(self, '_enable_controls_after_operation'):
|
||||
self._enable_controls_after_operation()
|
||||
|
||||
return lock_manager()
|
||||
|
||||
def safe_operation(self, operation_func, *args, **kwargs):
|
||||
"""
|
||||
Execute an operation with automatic button state management.
|
||||
|
||||
Args:
|
||||
operation_func: Function to execute
|
||||
*args, **kwargs: Arguments to pass to operation_func
|
||||
|
||||
Returns:
|
||||
Result of operation_func or None if exception occurred
|
||||
"""
|
||||
try:
|
||||
with self.operation_lock():
|
||||
return operation_func(*args, **kwargs)
|
||||
except Exception as e:
|
||||
# Log the error but don't re-raise - controls are already re-enabled
|
||||
if hasattr(self, 'logger'):
|
||||
self.logger.error(f"Operation failed: {e}", exc_info=True)
|
||||
# Could also show user error dialog here if needed
|
||||
return None
|
||||
|
||||
def reset_screen_to_defaults(self):
|
||||
"""
|
||||
Reset the screen to default state when navigating back from main menu.
|
||||
Override this method in subclasses to implement screen-specific reset logic.
|
||||
"""
|
||||
pass # Default implementation does nothing - subclasses should override
|
||||
@@ -738,6 +738,30 @@ class ConfigureExistingModlistScreen(QWidget):
|
||||
else:
|
||||
return f"{elapsed_seconds_remainder} seconds"
|
||||
|
||||
def reset_screen_to_defaults(self):
|
||||
"""Reset the screen to default state when navigating back from main menu"""
|
||||
# Clear the shortcut selection
|
||||
self.shortcut_combo.clear()
|
||||
self.shortcut_map.clear()
|
||||
# Auto-refresh modlist list when screen is entered
|
||||
self.refresh_modlist_list()
|
||||
|
||||
# Clear console and process monitor
|
||||
self.console.clear()
|
||||
self.process_monitor.clear()
|
||||
|
||||
# Reset resolution combo to saved config preference
|
||||
saved_resolution = self.resolution_service.get_saved_resolution()
|
||||
if saved_resolution:
|
||||
combo_items = [self.resolution_combo.itemText(i) for i in range(self.resolution_combo.count())]
|
||||
resolution_index = self.resolution_service.get_resolution_index(saved_resolution, combo_items)
|
||||
self.resolution_combo.setCurrentIndex(resolution_index)
|
||||
elif self.resolution_combo.count() > 0:
|
||||
self.resolution_combo.setCurrentIndex(0) # Fallback to "Leave unchanged"
|
||||
|
||||
# Re-enable controls (in case they were disabled from previous errors)
|
||||
self._enable_controls_after_operation()
|
||||
|
||||
def cleanup(self):
|
||||
"""Clean up any running threads when the screen is closed"""
|
||||
debug_print("DEBUG: cleanup called - cleaning up ConfigurationThread")
|
||||
|
||||
@@ -1326,6 +1326,27 @@ class ConfigureNewModlistScreen(QWidget):
|
||||
btn_exit.clicked.connect(on_exit)
|
||||
dlg.exec()
|
||||
|
||||
def reset_screen_to_defaults(self):
|
||||
"""Reset the screen to default state when navigating back from main menu"""
|
||||
# Reset form fields
|
||||
self.install_dir_edit.setText("/path/to/Modlist/ModOrganizer.exe")
|
||||
|
||||
# Clear console and process monitor
|
||||
self.console.clear()
|
||||
self.process_monitor.clear()
|
||||
|
||||
# Reset resolution combo to saved config preference
|
||||
saved_resolution = self.resolution_service.get_saved_resolution()
|
||||
if saved_resolution:
|
||||
combo_items = [self.resolution_combo.itemText(i) for i in range(self.resolution_combo.count())]
|
||||
resolution_index = self.resolution_service.get_resolution_index(saved_resolution, combo_items)
|
||||
self.resolution_combo.setCurrentIndex(resolution_index)
|
||||
elif self.resolution_combo.count() > 0:
|
||||
self.resolution_combo.setCurrentIndex(0) # Fallback to "Leave unchanged"
|
||||
|
||||
# Re-enable controls (in case they were disabled from previous errors)
|
||||
self._enable_controls_after_operation()
|
||||
|
||||
def cleanup(self):
|
||||
"""Clean up any running threads when the screen is closed"""
|
||||
debug_print("DEBUG: cleanup called - cleaning up threads")
|
||||
|
||||
@@ -2023,7 +2023,10 @@ class InstallModlistScreen(QWidget):
|
||||
"""Handle configuration error on main thread"""
|
||||
self._safe_append_text(f"Configuration failed with error: {error_message}")
|
||||
MessageService.critical(self, "Configuration Error", f"Configuration failed: {error_message}")
|
||||
|
||||
|
||||
# Re-enable all controls on error
|
||||
self._enable_controls_after_operation()
|
||||
|
||||
# Clean up thread
|
||||
if hasattr(self, 'config_thread') and self.config_thread is not None:
|
||||
# Disconnect all signals to prevent "Internal C++ object already deleted" errors
|
||||
@@ -2676,6 +2679,36 @@ https://wiki.scenicroute.games/Somnium/1_Installation.html</i>"""
|
||||
self.cleanup_processes()
|
||||
self.go_back()
|
||||
|
||||
def reset_screen_to_defaults(self):
|
||||
"""Reset the screen to default state when navigating back from main menu"""
|
||||
# Reset form fields
|
||||
self.modlist_btn.setText("Select Modlist")
|
||||
self.modlist_btn.setEnabled(False)
|
||||
self.file_edit.setText("")
|
||||
self.modlist_name_edit.setText("")
|
||||
self.install_dir_edit.setText(self.config_handler.get_modlist_install_base_dir())
|
||||
# Reset game type button
|
||||
self.game_type_btn.setText("Please Select...")
|
||||
|
||||
# Clear console and process monitor
|
||||
self.console.clear()
|
||||
self.process_monitor.clear()
|
||||
|
||||
# Reset tabs to first tab (Online)
|
||||
self.source_tabs.setCurrentIndex(0)
|
||||
|
||||
# Reset resolution combo to saved config preference
|
||||
saved_resolution = self.resolution_service.get_saved_resolution()
|
||||
if saved_resolution:
|
||||
combo_items = [self.resolution_combo.itemText(i) for i in range(self.resolution_combo.count())]
|
||||
resolution_index = self.resolution_service.get_resolution_index(saved_resolution, combo_items)
|
||||
self.resolution_combo.setCurrentIndex(resolution_index)
|
||||
elif self.resolution_combo.count() > 0:
|
||||
self.resolution_combo.setCurrentIndex(0) # Fallback to "Leave unchanged"
|
||||
|
||||
# Re-enable controls (in case they were disabled from previous errors)
|
||||
self._enable_controls_after_operation()
|
||||
|
||||
def closeEvent(self, event):
|
||||
"""Handle window close event - clean up processes"""
|
||||
self.cleanup_processes()
|
||||
|
||||
Reference in New Issue
Block a user