feat(dialogs): added controller hints
Signed-off-by: Boris Yumankulov <boria138@altlinux.org>
This commit is contained in:
@@ -91,6 +91,130 @@ def generate_thumbnail(inputfile, outfile, size=128, force_resize=True):
|
||||
logger.error(f"Ошибка при сохранении миниатюры: {e}")
|
||||
return False
|
||||
|
||||
def create_dialog_hints_widget(theme, main_window, input_manager, context='default'):
|
||||
"""
|
||||
Common function to create hints widget for all dialogs.
|
||||
Uses main_window for get_button_icon/get_nav_icon, input_manager for gamepad detection.
|
||||
"""
|
||||
theme_manager = ThemeManager()
|
||||
current_theme_name = read_theme_from_config()
|
||||
|
||||
hintsWidget = QWidget()
|
||||
hintsWidget.setStyleSheet(theme.STATUS_BAR_STYLE)
|
||||
hintsLayout = QHBoxLayout(hintsWidget)
|
||||
hintsLayout.setContentsMargins(10, 0, 10, 0)
|
||||
hintsLayout.setSpacing(20)
|
||||
|
||||
dialog_actions = []
|
||||
|
||||
# Context-specific actions (gamepad only, no keyboard)
|
||||
if context == 'file_explorer':
|
||||
dialog_actions = [
|
||||
("confirm", _("Open")), # A / Cross
|
||||
("add_game", _("Select Dir")), # X / Triangle
|
||||
("prev_dir", _("Prev Dir")), # Y / Square
|
||||
("back", _("Cancel")), # B / Circle
|
||||
("context_menu", _("Menu")), # Start / Options
|
||||
]
|
||||
elif context == 'winetricks':
|
||||
dialog_actions = [
|
||||
("confirm", _("Toggle")), # A / Cross
|
||||
("add_game", _("Install")), # X / Triangle
|
||||
("prev_dir", _("Force Install")), # Y / Square
|
||||
("back", _("Cancel")), # B / Circle
|
||||
("prev_tab", _("Prev Tab")), # LB / L1
|
||||
("next_tab", _("Next Tab")), # RB / R1
|
||||
]
|
||||
|
||||
hints_labels = [] # Store for updates (returned for class storage)
|
||||
|
||||
def make_hint(icon_name, text, action=None):
|
||||
container = QWidget()
|
||||
hlayout = QHBoxLayout(container)
|
||||
hlayout.setContentsMargins(0, 5, 0, 0)
|
||||
hlayout.setSpacing(6)
|
||||
|
||||
icon_label = QLabel()
|
||||
icon_label.setFixedSize(26, 26)
|
||||
icon_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
|
||||
pixmap = QPixmap()
|
||||
icon_path = theme_manager.get_theme_image(icon_name, current_theme_name)
|
||||
if icon_path:
|
||||
pixmap.load(str(icon_path))
|
||||
if not pixmap.isNull():
|
||||
icon_label.setPixmap(pixmap.scaled(26, 26, Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation))
|
||||
|
||||
hlayout.addWidget(icon_label)
|
||||
|
||||
text_label = QLabel(text)
|
||||
text_label.setStyleSheet(theme.LAST_LAUNCH_VALUE_STYLE)
|
||||
text_label.setAlignment(Qt.AlignmentFlag.AlignVCenter | Qt.AlignmentFlag.AlignLeft)
|
||||
hlayout.addWidget(text_label)
|
||||
|
||||
# Initially hidden; show only if gamepad connected
|
||||
container.setVisible(False)
|
||||
hints_labels.append((container, icon_label, action))
|
||||
|
||||
hintsLayout.addWidget(container)
|
||||
|
||||
# Add gamepad hints only
|
||||
for action, text in dialog_actions:
|
||||
make_hint("placeholder", text, action)
|
||||
|
||||
hintsLayout.addStretch()
|
||||
|
||||
# Return widget and labels for class storage
|
||||
return hintsWidget, hints_labels
|
||||
|
||||
def update_dialog_hints(hints_labels, main_window, input_manager, theme_manager, current_theme_name):
|
||||
"""
|
||||
Common function to update hints for any dialog.
|
||||
"""
|
||||
if not input_manager or not main_window:
|
||||
# Hide all if no input_manager or main_window
|
||||
for container, _, _ in hints_labels:
|
||||
container.setVisible(False)
|
||||
return
|
||||
|
||||
is_gamepad = input_manager.gamepad is not None
|
||||
if not is_gamepad:
|
||||
# Hide all hints if no gamepad
|
||||
for container, _, _ in hints_labels:
|
||||
container.setVisible(False)
|
||||
return
|
||||
|
||||
gtype = input_manager.gamepad_type
|
||||
gamepad_actions = ['confirm', 'back', 'context_menu', 'add_game', 'prev_dir', 'prev_tab', 'next_tab']
|
||||
|
||||
for container, icon_label, action in hints_labels:
|
||||
if action and action in gamepad_actions:
|
||||
container.setVisible(True)
|
||||
# Update icon using main_window methods
|
||||
if action in ['confirm', 'back', 'context_menu', 'add_game', 'prev_dir']:
|
||||
icon_name = main_window.get_button_icon(action, gtype)
|
||||
else: # only prev_tab/next_tab (treat as nav)
|
||||
direction = 'left' if action == 'prev_tab' else 'right'
|
||||
icon_name = main_window.get_nav_icon(direction, gtype)
|
||||
icon_path = theme_manager.get_theme_image(icon_name, current_theme_name)
|
||||
pixmap = QPixmap()
|
||||
if icon_path:
|
||||
pixmap.load(str(icon_path))
|
||||
if not pixmap.isNull():
|
||||
icon_label.setPixmap(pixmap.scaled(
|
||||
26, 26,
|
||||
Qt.AspectRatioMode.KeepAspectRatio,
|
||||
Qt.TransformationMode.SmoothTransformation
|
||||
))
|
||||
else:
|
||||
# Fallback to placeholder
|
||||
placeholder = theme_manager.get_theme_image("placeholder", current_theme_name)
|
||||
if placeholder:
|
||||
pixmap.load(str(placeholder))
|
||||
icon_label.setPixmap(pixmap.scaled(26, 26, Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation))
|
||||
else:
|
||||
container.setVisible(False)
|
||||
|
||||
class FileSelectedSignal(QObject):
|
||||
file_selected = Signal(str) # Сигнал с путем к выбранному файлу
|
||||
|
||||
@@ -185,6 +309,7 @@ class FileExplorer(QDialog):
|
||||
self.initial_path = initial_path # Store initial path if provided
|
||||
self.thumbnail_cache = {} # Cache for loaded thumbnails
|
||||
self.pending_thumbnails = set() # Track files pending thumbnail loading
|
||||
self.main_window = None # Add reference to MainWindow
|
||||
self.setup_ui()
|
||||
|
||||
# Window settings
|
||||
@@ -198,6 +323,7 @@ class FileExplorer(QDialog):
|
||||
while parent:
|
||||
if hasattr(parent, 'input_manager'):
|
||||
self.input_manager = cast("MainWindow", parent).input_manager
|
||||
self.main_window = parent
|
||||
if hasattr(parent, 'context_menu_manager'):
|
||||
self.context_menu_manager = cast("MainWindow", parent).context_menu_manager
|
||||
parent = parent.parent()
|
||||
@@ -214,6 +340,17 @@ class FileExplorer(QDialog):
|
||||
self.current_path = os.path.expanduser("~") # Fallback to home if initial path is invalid
|
||||
self.update_file_list()
|
||||
|
||||
# Create hints widget using common function
|
||||
self.current_theme_name = read_theme_from_config()
|
||||
self.hints_widget, self.hints_labels = create_dialog_hints_widget(self.theme, self.main_window, self.input_manager, context='file_explorer')
|
||||
self.main_layout.addWidget(self.hints_widget)
|
||||
|
||||
# Connect signals
|
||||
if self.input_manager:
|
||||
self.input_manager.button_event.connect(lambda *args: update_dialog_hints(self.hints_labels, self.main_window, self.input_manager, theme_manager, self.current_theme_name))
|
||||
self.input_manager.dpad_moved.connect(lambda *args: update_dialog_hints(self.hints_labels, self.main_window, self.input_manager, theme_manager, self.current_theme_name))
|
||||
update_dialog_hints(self.hints_labels, self.main_window, self.input_manager, theme_manager, self.current_theme_name)
|
||||
|
||||
class ThumbnailLoader(QRunnable):
|
||||
"""Class for asynchronous thumbnail loading in a separate thread."""
|
||||
class Signals(QObject):
|
||||
@@ -1037,8 +1174,6 @@ Icon={icon_path}
|
||||
return desktop_entry, desktop_path
|
||||
|
||||
class WinetricksDialog(QDialog):
|
||||
"""Dialog for managing Winetricks components in a prefix."""
|
||||
|
||||
def __init__(self, parent=None, theme=None, prefix_path: str | None = None, wine_use: str | None = None):
|
||||
super().__init__(parent)
|
||||
self.theme = theme if theme else theme_manager.apply_theme(read_theme_from_config())
|
||||
@@ -1071,6 +1206,36 @@ class WinetricksDialog(QDialog):
|
||||
self.setup_ui()
|
||||
self.load_lists()
|
||||
|
||||
# Find input_manager and main_window
|
||||
self.input_manager = None
|
||||
self.main_window = None
|
||||
parent = self.parent()
|
||||
while parent:
|
||||
if hasattr(parent, 'input_manager'):
|
||||
self.input_manager = cast("MainWindow", parent).input_manager
|
||||
self.main_window = parent
|
||||
parent = parent.parent()
|
||||
|
||||
self.current_theme_name = read_theme_from_config()
|
||||
|
||||
# Enable Winetricks-specific mode
|
||||
if self.input_manager:
|
||||
self.input_manager.enable_winetricks_mode(self)
|
||||
|
||||
# Create hints widget using common function
|
||||
self.hints_widget, self.hints_labels = create_dialog_hints_widget(self.theme, self.main_window, self.input_manager, context='winetricks')
|
||||
self.main_layout.addWidget(self.hints_widget)
|
||||
|
||||
# Connect signals (use self.theme_manager)
|
||||
if self.input_manager:
|
||||
self.input_manager.button_event.connect(
|
||||
lambda *args: update_dialog_hints(self.hints_labels, self.main_window, self.input_manager, theme_manager, self.current_theme_name)
|
||||
)
|
||||
self.input_manager.dpad_moved.connect(
|
||||
lambda *args: update_dialog_hints(self.hints_labels, self.main_window, self.input_manager, theme_manager, self.current_theme_name)
|
||||
)
|
||||
update_dialog_hints(self.hints_labels, self.main_window, self.input_manager, theme_manager, self.current_theme_name)
|
||||
|
||||
def update_winetricks(self):
|
||||
"""Update the winetricks script."""
|
||||
if not self.downloader.has_internet():
|
||||
@@ -1143,15 +1308,15 @@ class WinetricksDialog(QDialog):
|
||||
|
||||
def setup_ui(self):
|
||||
"""Set up the user interface with tabs and tables."""
|
||||
main_layout = QVBoxLayout(self)
|
||||
main_layout.setContentsMargins(10, 10, 10, 10)
|
||||
main_layout.setSpacing(10)
|
||||
self.main_layout = QVBoxLayout(self)
|
||||
self.main_layout.setContentsMargins(10, 10, 10, 10)
|
||||
self.main_layout.setSpacing(10)
|
||||
|
||||
# Log output
|
||||
self.log_output = QTextEdit()
|
||||
self.log_output.setReadOnly(True)
|
||||
self.log_output.setStyleSheet(self.theme.WINETRICKS_LOG_STYLE)
|
||||
main_layout.addWidget(self.log_output)
|
||||
self.main_layout.addWidget(self.log_output)
|
||||
|
||||
# Tab widget
|
||||
self.tab_widget = QTabWidget()
|
||||
@@ -1258,7 +1423,7 @@ class WinetricksDialog(QDialog):
|
||||
"settings": self.settings_container
|
||||
}
|
||||
|
||||
main_layout.addWidget(self.tab_widget)
|
||||
self.main_layout.addWidget(self.tab_widget)
|
||||
|
||||
# Buttons
|
||||
button_layout = QHBoxLayout()
|
||||
@@ -1272,7 +1437,7 @@ class WinetricksDialog(QDialog):
|
||||
button_layout.addWidget(self.cancel_button)
|
||||
button_layout.addWidget(self.force_button)
|
||||
button_layout.addWidget(self.install_button)
|
||||
main_layout.addLayout(button_layout)
|
||||
self.main_layout.addLayout(button_layout)
|
||||
|
||||
self.cancel_button.clicked.connect(self.reject)
|
||||
self.force_button.clicked.connect(lambda: self.install_selected(force=True))
|
||||
@@ -1497,3 +1662,15 @@ class WinetricksDialog(QDialog):
|
||||
"""Добавляет в лог."""
|
||||
self.log_output.append(message)
|
||||
self.log_output.moveCursor(QTextCursor.MoveOperation.End)
|
||||
|
||||
def closeEvent(self, event):
|
||||
"""Disable mode on close."""
|
||||
if self.input_manager:
|
||||
self.input_manager.disable_winetricks_mode()
|
||||
super().closeEvent(event)
|
||||
|
||||
def reject(self):
|
||||
"""Disable mode on reject."""
|
||||
if self.input_manager:
|
||||
self.input_manager.disable_winetricks_mode()
|
||||
super().reject()
|
||||
|
@@ -5,7 +5,7 @@ from typing import Protocol, cast
|
||||
from evdev import InputDevice, InputEvent, ecodes, list_devices, ff
|
||||
from enum import Enum
|
||||
from pyudev import Context, Monitor, MonitorObserver, Device
|
||||
from PySide6.QtWidgets import QWidget, QStackedWidget, QApplication, QScrollArea, QLineEdit, QDialog, QMenu, QComboBox, QListView, QMessageBox, QListWidget, QTableWidget, QAbstractItemView
|
||||
from PySide6.QtWidgets import QWidget, QStackedWidget, QApplication, QScrollArea, QLineEdit, QDialog, QMenu, QComboBox, QListView, QMessageBox, QListWidget, QTableWidget, QAbstractItemView, QTableWidgetItem
|
||||
from PySide6.QtCore import Qt, QObject, QEvent, QPoint, Signal, Slot, QTimer
|
||||
from PySide6.QtGui import QKeyEvent, QMouseEvent
|
||||
from portprotonqt.logger import get_logger
|
||||
@@ -13,7 +13,7 @@ from portprotonqt.image_utils import FullscreenDialog
|
||||
from portprotonqt.custom_widgets import NavLabel, AutoSizeButton
|
||||
from portprotonqt.game_card import GameCard
|
||||
from portprotonqt.config_utils import read_fullscreen_config, read_window_geometry, save_window_geometry, read_auto_fullscreen_gamepad, read_rumble_config, read_gamepad_type
|
||||
from portprotonqt.dialogs import AddGameDialog, WinetricksDialog
|
||||
from portprotonqt.dialogs import AddGameDialog
|
||||
from portprotonqt.virtual_keyboard import VirtualKeyboard
|
||||
|
||||
logger = get_logger(__name__)
|
||||
@@ -455,6 +455,171 @@ class InputManager(QObject):
|
||||
except Exception as e:
|
||||
logger.error("Error in FileExplorer dpad handler: %s", e)
|
||||
|
||||
def enable_winetricks_mode(self, winetricks_dialog):
|
||||
"""Setup gamepad handling for WinetricksDialog"""
|
||||
try:
|
||||
self.winetricks_dialog = winetricks_dialog
|
||||
self.original_button_handler = self.handle_button_slot
|
||||
self.original_dpad_handler = self.handle_dpad_slot
|
||||
self.original_gamepad_state = self._gamepad_handling_enabled
|
||||
self.handle_button_slot = self.handle_winetricks_button
|
||||
self.handle_dpad_slot = self.handle_winetricks_dpad
|
||||
self._gamepad_handling_enabled = True
|
||||
# Reset dpad timer for table nav
|
||||
self.dpad_timer.stop()
|
||||
self.current_dpad_code = None
|
||||
self.current_dpad_value = 0
|
||||
logger.debug("Gamepad handling successfully connected for WinetricksDialog")
|
||||
except Exception as e:
|
||||
logger.error(f"Error connecting gamepad handlers for Winetricks: {e}")
|
||||
|
||||
def disable_winetricks_mode(self):
|
||||
"""Restore original main window handlers"""
|
||||
try:
|
||||
if self.winetricks_dialog:
|
||||
self.handle_button_slot = self.original_button_handler
|
||||
self.handle_dpad_slot = self.original_dpad_handler
|
||||
self._gamepad_handling_enabled = self.original_gamepad_state
|
||||
self.winetricks_dialog = None
|
||||
self.dpad_timer.stop()
|
||||
self.current_dpad_code = None
|
||||
self.current_dpad_value = 0
|
||||
logger.debug("Gamepad handling successfully restored from Winetricks")
|
||||
except Exception as e:
|
||||
logger.error(f"Error restoring gamepad handlers from Winetricks: {e}")
|
||||
|
||||
def handle_winetricks_button(self, button_code, value):
|
||||
if self.winetricks_dialog is None:
|
||||
return
|
||||
if value == 0: # Ignore releases
|
||||
return
|
||||
try:
|
||||
# Always check for popups first, including QMessageBox
|
||||
popup = QApplication.activePopupWidget()
|
||||
if popup:
|
||||
if isinstance(popup, QMessageBox):
|
||||
if button_code in BUTTONS['confirm'] or button_code in BUTTONS['back']:
|
||||
popup.accept() # Close QMessageBox with A or B
|
||||
return
|
||||
elif isinstance(popup, QMenu):
|
||||
if button_code in BUTTONS['confirm']: # A: Select menu item
|
||||
focused = popup.activeAction()
|
||||
if focused:
|
||||
focused.trigger()
|
||||
return
|
||||
elif button_code in BUTTONS['back']: # B: Close menu
|
||||
popup.close()
|
||||
return
|
||||
|
||||
# Additional check for top-level QMessageBox (in case not active popup yet)
|
||||
for widget in QApplication.topLevelWidgets():
|
||||
if isinstance(widget, QMessageBox) and widget.isVisible():
|
||||
if button_code in BUTTONS['confirm'] or button_code in BUTTONS['back']:
|
||||
widget.accept()
|
||||
return
|
||||
|
||||
focused = QApplication.focusWidget()
|
||||
if button_code in BUTTONS['confirm']: # A: Toggle checkbox
|
||||
if isinstance(focused, QTableWidget):
|
||||
current_row = focused.currentRow()
|
||||
if current_row >= 0:
|
||||
checkbox_item = focused.item(current_row, 0)
|
||||
if checkbox_item and isinstance(checkbox_item, QTableWidgetItem):
|
||||
new_state = Qt.CheckState.Checked if checkbox_item.checkState() == Qt.CheckState.Unchecked else Qt.CheckState.Unchecked
|
||||
checkbox_item.setCheckState(new_state)
|
||||
return
|
||||
elif button_code in BUTTONS['add_game']: # X: Install (no force)
|
||||
self.winetricks_dialog.install_selected(force=False)
|
||||
return
|
||||
elif button_code in BUTTONS['prev_dir']: # Y: Force Install
|
||||
self.winetricks_dialog.install_selected(force=True)
|
||||
return
|
||||
elif button_code in BUTTONS['back']: # B: Cancel
|
||||
self.winetricks_dialog.reject()
|
||||
return
|
||||
elif button_code in BUTTONS['prev_tab']: # LB: Prev Tab
|
||||
current_index = self.winetricks_dialog.tab_widget.currentIndex()
|
||||
new_index = max(0, current_index - 1)
|
||||
self.winetricks_dialog.tab_widget.setCurrentIndex(new_index)
|
||||
self._focus_first_row_in_current_table()
|
||||
return
|
||||
elif button_code in BUTTONS['next_tab']: # RB: Next Tab
|
||||
current_index = self.winetricks_dialog.tab_widget.currentIndex()
|
||||
new_index = min(self.winetricks_dialog.tab_widget.count() - 1, current_index + 1)
|
||||
self.winetricks_dialog.tab_widget.setCurrentIndex(new_index)
|
||||
self._focus_first_row_in_current_table()
|
||||
return
|
||||
# Fallback: Activate focused widget (e.g., buttons)
|
||||
self._parent.activateFocusedWidget()
|
||||
except Exception as e:
|
||||
logger.error(f"Error in handle_winetricks_button: {e}")
|
||||
|
||||
def handle_winetricks_dpad(self, code, value, now):
|
||||
if self.winetricks_dialog is None:
|
||||
return
|
||||
try:
|
||||
if value == 0: # Release: Stop repeat
|
||||
self.dpad_timer.stop()
|
||||
self.current_dpad_code = None
|
||||
self.current_dpad_value = 0
|
||||
return
|
||||
|
||||
# Start/update repeat timer for hold navigation
|
||||
if self.current_dpad_code != code or self.current_dpad_value != value:
|
||||
self.dpad_timer.stop()
|
||||
self.dpad_timer.setInterval(150 if self.dpad_timer.isActive() else 300) # Initial slower, then faster repeat
|
||||
self.dpad_timer.start()
|
||||
self.current_dpad_code = code
|
||||
self.current_dpad_value = value
|
||||
|
||||
table = self._get_current_table()
|
||||
if not table or table.rowCount() == 0:
|
||||
return
|
||||
|
||||
current_row = table.currentRow()
|
||||
if code == ecodes.ABS_HAT0Y: # Up/Down: Navigate rows
|
||||
if value < 0: # Up
|
||||
new_row = max(0, current_row - 1)
|
||||
elif value > 0: # Down
|
||||
new_row = min(table.rowCount() - 1, current_row + 1)
|
||||
else:
|
||||
return
|
||||
if new_row != current_row:
|
||||
table.setCurrentCell(new_row, 0) # Focus checkbox column
|
||||
table.setFocus(Qt.FocusReason.OtherFocusReason)
|
||||
elif code == ecodes.ABS_HAT0X: # Left/Right: Switch tabs
|
||||
if value < 0: # Left: Prev tab
|
||||
current_index = self.winetricks_dialog.tab_widget.currentIndex()
|
||||
new_index = max(0, current_index - 1)
|
||||
self.winetricks_dialog.tab_widget.setCurrentIndex(new_index)
|
||||
elif value > 0: # Right: Next tab
|
||||
current_index = self.winetricks_dialog.tab_widget.currentIndex()
|
||||
new_index = min(self.winetricks_dialog.tab_widget.count() - 1, current_index + 1)
|
||||
self.winetricks_dialog.tab_widget.setCurrentIndex(new_index)
|
||||
self._focus_first_row_in_current_table()
|
||||
except Exception as e:
|
||||
logger.error(f"Error in handle_winetricks_dpad: {e}")
|
||||
|
||||
def _get_current_table(self):
|
||||
"""Get the current visible table from the tab widget's stacked container."""
|
||||
if self.winetricks_dialog is None:
|
||||
return None
|
||||
current_container = self.winetricks_dialog.tab_widget.currentWidget()
|
||||
if current_container and isinstance(current_container, QStackedWidget):
|
||||
current_table = current_container.widget(1) # Table is at index 1 (after preloader)
|
||||
if isinstance(current_table, QTableWidget):
|
||||
return current_table
|
||||
return None
|
||||
|
||||
def _focus_first_row_in_current_table(self):
|
||||
"""Focus the first row in the current table after tab switch."""
|
||||
if self.winetricks_dialog is None:
|
||||
return
|
||||
table = self._get_current_table()
|
||||
if table and table.rowCount() > 0:
|
||||
table.setCurrentCell(0, 0)
|
||||
table.setFocus(Qt.FocusReason.OtherFocusReason)
|
||||
|
||||
def handle_navigation_repeat(self):
|
||||
"""Плавное повторение движения с переменной скоростью для FileExplorer"""
|
||||
try:
|
||||
@@ -705,39 +870,6 @@ class InputManager(QObject):
|
||||
self._parent.toggleGame(self._parent.current_exec_line, None)
|
||||
return
|
||||
|
||||
|
||||
if isinstance(active, WinetricksDialog):
|
||||
if button_code in BUTTONS['confirm']: # A button - toggle checkbox
|
||||
current_table = active.tab_widget.currentWidget()
|
||||
if isinstance(current_table, QTableWidget):
|
||||
current_row = current_table.currentRow()
|
||||
if current_row >= 0:
|
||||
checkbox = current_table.item(current_row, 0)
|
||||
if checkbox:
|
||||
checkbox.setCheckState(
|
||||
Qt.CheckState.Unchecked if checkbox.checkState() == Qt.CheckState.Checked else Qt.CheckState.Checked
|
||||
)
|
||||
return
|
||||
elif button_code in BUTTONS['add_game']: # X button - install
|
||||
active.install_selected(force=False)
|
||||
return
|
||||
elif button_code in BUTTONS['prev_dir']: # Y button - force install
|
||||
active.install_selected(force=True)
|
||||
return
|
||||
elif button_code in BUTTONS['back']: # B button - close dialog
|
||||
active.reject()
|
||||
return
|
||||
elif button_code in BUTTONS['prev_tab']: # LB - previous tab
|
||||
current_idx = active.tab_widget.currentIndex()
|
||||
new_idx = (current_idx - 1) % active.tab_widget.count()
|
||||
active.tab_widget.setCurrentIndex(new_idx)
|
||||
return
|
||||
elif button_code in BUTTONS['next_tab']: # RB - next tab
|
||||
current_idx = active.tab_widget.currentIndex()
|
||||
new_idx = (current_idx + 1) % active.tab_widget.count()
|
||||
active.tab_widget.setCurrentIndex(new_idx)
|
||||
return
|
||||
|
||||
# Standard navigation
|
||||
if button_code in BUTTONS['confirm']:
|
||||
self._parent.activateFocusedWidget()
|
||||
|
@@ -260,6 +260,10 @@ class MainWindow(QMainWindow):
|
||||
GamepadType.XBOX: "xbox_y",
|
||||
GamepadType.PLAYSTATION: "ps_square",
|
||||
},
|
||||
'prev_dir': {
|
||||
GamepadType.XBOX: "xbox_y",
|
||||
GamepadType.PLAYSTATION: "ps_square",
|
||||
},
|
||||
}
|
||||
return mappings.get(action, {}).get(gtype, "placeholder")
|
||||
|
||||
|
Reference in New Issue
Block a user