From 61fae97dade19650286c1ffb0eb7a62af1d50963 Mon Sep 17 00:00:00 2001 From: Boris Yumankulov Date: Sun, 12 Oct 2025 14:45:52 +0500 Subject: [PATCH] fix(autoinstall): fix virtual keyboard open Signed-off-by: Boris Yumankulov --- portprotonqt/input_manager.py | 155 +++------------------------------- portprotonqt/main_window.py | 25 ++++-- 2 files changed, 32 insertions(+), 148 deletions(-) diff --git a/portprotonqt/input_manager.py b/portprotonqt/input_manager.py index b07a9c7..a4db6cd 100644 --- a/portprotonqt/input_manager.py +++ b/portprotonqt/input_manager.py @@ -483,17 +483,27 @@ class InputManager(QObject): if not app or not active: return + current_tab_index = self._parent.stackedWidget.currentIndex() + if button_code in BUTTONS['confirm'] and isinstance(focused, QLineEdit): - search_edit = getattr(self._parent, 'searchEdit', None) + search_edit = None + if current_tab_index == 0: + search_edit = getattr(self._parent, 'searchEdit', None) + elif current_tab_index == 1: + search_edit = getattr(self._parent, 'autoInstallSearchLineEdit', None) if focused == search_edit: keyboard = getattr(self._parent, 'keyboard', None) if keyboard: keyboard.show_for_widget(focused) return - # Handle Y button to focus search + # Handle Y button to focus search if button_code in BUTTONS['prev_dir']: # Y button - search_edit = getattr(self._parent, 'searchEdit', None) + search_edit = None + if current_tab_index == 0: + search_edit = getattr(self._parent, 'searchEdit', None) + elif current_tab_index == 1: + search_edit = getattr(self._parent, 'autoInstallSearchLineEdit', None) if search_edit: search_edit.setFocus() return @@ -1022,130 +1032,6 @@ class InputManager(QObject): elif current_row_idx == 0: self._parent.tabButtons[0].setFocus(Qt.FocusReason.OtherFocusReason) - # Autoinstall tab navigation(index 1) - if self._parent.stackedWidget.currentIndex() == 1 and code in (ecodes.ABS_HAT0X, ecodes.ABS_HAT0Y): - focused = QApplication.focusWidget() - game_cards = self._parent.autoInstallContainer.findChildren(GameCard) - if not game_cards: - return - - scroll_area = self._parent.autoInstallContainer.parentWidget() - while scroll_area and not isinstance(scroll_area, QScrollArea): - scroll_area = scroll_area.parentWidget() - - # If no focused widget or not a GameCard, focus the first card - if not isinstance(focused, GameCard) or focused not in game_cards: - game_cards[0].setFocus() - if scroll_area: - scroll_area.ensureWidgetVisible(game_cards[0], 50, 50) - return - - cards = self._parent.autoInstallContainer.findChildren(GameCard, options=Qt.FindChildOption.FindChildrenRecursively) - if not cards: - return - # Group cards by rows with tolerance for y-position - rows = {} - y_tolerance = 10 # Allow slight variations in y-position - for card in cards: - y = card.pos().y() - matched = False - for row_y in rows: - if abs(y - row_y) <= y_tolerance: - rows[row_y].append(card) - matched = True - break - if not matched: - rows[y] = [card] - sorted_rows = sorted(rows.items(), key=lambda x: x[0]) - if not sorted_rows: - return - current_row_idx = None - current_col_idx = None - for row_idx, (_y, row_cards) in enumerate(sorted_rows): - for idx, card in enumerate(row_cards): - if card == focused: - current_row_idx = row_idx - current_col_idx = idx - break - if current_row_idx is not None: - break - - # Fallback: if focused card not found, select closest row by y-position - if current_row_idx is None: - if not sorted_rows: # Additional safety check - return - focused_y = focused.pos().y() - current_row_idx = min(range(len(sorted_rows)), key=lambda i: abs(sorted_rows[i][0] - focused_y)) - if current_row_idx >= len(sorted_rows): # Safety check - return - current_row = sorted_rows[current_row_idx][1] - focused_x = focused.pos().x() + focused.width() / 2 - current_col_idx = min(range(len(current_row)), key=lambda i: abs((current_row[i].pos().x() + current_row[i].width() / 2) - focused_x), default=0) # type: ignore - - # Add null checks before using current_row_idx and current_col_idx - if current_row_idx is None or current_col_idx is None or current_row_idx >= len(sorted_rows): - return - - current_row = sorted_rows[current_row_idx][1] - if code == ecodes.ABS_HAT0X and value != 0: - if value < 0: # Left - if current_col_idx > 0: - next_card = current_row[current_col_idx - 1] - next_card.setFocus(Qt.FocusReason.OtherFocusReason) - if scroll_area: - scroll_area.ensureWidgetVisible(next_card, 50, 50) - else: - if current_row_idx > 0: - prev_row = sorted_rows[current_row_idx - 1][1] - next_card = prev_row[-1] if prev_row else None - if next_card: - next_card.setFocus(Qt.FocusReason.OtherFocusReason) - if scroll_area: - scroll_area.ensureWidgetVisible(next_card, 50, 50) - elif value > 0: # Right - if current_col_idx < len(current_row) - 1: - next_card = current_row[current_col_idx + 1] - next_card.setFocus(Qt.FocusReason.OtherFocusReason) - if scroll_area: - scroll_area.ensureWidgetVisible(next_card, 50, 50) - else: - if current_row_idx < len(sorted_rows) - 1: - next_row = sorted_rows[current_row_idx + 1][1] - next_card = next_row[0] if next_row else None - if next_card: - next_card.setFocus(Qt.FocusReason.OtherFocusReason) - if scroll_area: - scroll_area.ensureWidgetVisible(next_card, 50, 50) - elif code == ecodes.ABS_HAT0Y and value != 0: - if value > 0: # Down - if current_row_idx < len(sorted_rows) - 1: - next_row = sorted_rows[current_row_idx + 1][1] - current_x = focused.pos().x() + focused.width() / 2 - next_card = min( - next_row, - key=lambda c: abs((c.pos().x() + c.width() / 2) - current_x), - default=None - ) - if next_card: - next_card.setFocus(Qt.FocusReason.OtherFocusReason) - if scroll_area: - scroll_area.ensureWidgetVisible(next_card, 50, 50) - elif value < 0: # Up - if current_row_idx > 0: - prev_row = sorted_rows[current_row_idx - 1][1] - current_x = focused.pos().x() + focused.width() / 2 - next_card = min( - prev_row, - key=lambda c: abs((c.pos().x() + c.width() / 2) - current_x), - default=None - ) - if next_card: - next_card.setFocus(Qt.FocusReason.OtherFocusReason) - if scroll_area: - scroll_area.ensureWidgetVisible(next_card, 50, 50) - elif current_row_idx == 0: - self._parent.tabButtons[0].setFocus(Qt.FocusReason.OtherFocusReason) - # Vertical navigation in other tabs elif code == ecodes.ABS_HAT0Y and value != 0: focused = QApplication.focusWidget() @@ -1212,21 +1098,6 @@ class InputManager(QObject): keyboard.on_backspace_pressed() elif value == 0: keyboard.stop_backspace_repeat() - elif button_code in BUTTONS['search']: # Кнопка Y/Square - поиск (tab-specific) - if value == 1: - current_index = self._parent.stackedWidget.currentIndex() - search_field = None - if current_index == 0: # Library tab - search_field = self._parent.searchLineEdit - elif current_index == 1: # Auto Install tab - search_field = self._parent.autoInstallSearchLineEdit - else: - return - - if search_field: - search_field.setFocus() - keyboard.current_input_widget = search_field - keyboard.show() def eventFilter(self, obj: QObject, event: QEvent) -> bool: app = QApplication.instance() diff --git a/portprotonqt/main_window.py b/portprotonqt/main_window.py index 3d2ce08..775b65d 100644 --- a/portprotonqt/main_window.py +++ b/portprotonqt/main_window.py @@ -39,7 +39,7 @@ from portprotonqt.game_library_manager import GameLibraryManager from portprotonqt.virtual_keyboard import VirtualKeyboard from PySide6.QtWidgets import (QLineEdit, QMainWindow, QStatusBar, QWidget, QVBoxLayout, QLabel, QHBoxLayout, QStackedWidget, QComboBox, - QDialog, QFormLayout, QFrame, QGraphicsDropShadowEffect, QMessageBox, QApplication, QPushButton, QProgressBar, QCheckBox, QSizePolicy, QGridLayout, QScrollArea) + QDialog, QFormLayout, QFrame, QGraphicsDropShadowEffect, QMessageBox, QApplication, QPushButton, QProgressBar, QCheckBox, QSizePolicy, QGridLayout, QScrollArea, QScroller) from PySide6.QtCore import Qt, QAbstractAnimation, QUrl, Signal, QTimer, Slot, QProcess from PySide6.QtGui import QIcon, QPixmap, QColor, QDesktopServices from typing import cast @@ -1061,7 +1061,7 @@ class MainWindow(QMainWindow): def createAutoInstallTab(self): autoInstallPage = QWidget() - autoInstallPage.setStyleSheet(self.theme.MAIN_WINDOW_STYLE) + autoInstallPage.setStyleSheet(self.theme.LIBRARY_WIDGET_STYLE) autoInstallLayout = QVBoxLayout(autoInstallPage) autoInstallLayout.setContentsMargins(0, 0, 0, 0) autoInstallLayout.setSpacing(0) @@ -1073,7 +1073,7 @@ class MainWindow(QMainWindow): headerLayout.setSpacing(10) # Заголовок - titleLabel = QLabel(_("Auto Install Games")) + titleLabel = QLabel(_("Auto Install")) titleLabel.setStyleSheet(self.theme.TAB_TITLE_STYLE) titleLabel.setAlignment(Qt.AlignVCenter | Qt.AlignLeft) headerLayout.addWidget(titleLabel) @@ -1103,9 +1103,8 @@ class MainWindow(QMainWindow): # Скролл self.autoInstallScrollArea = QScrollArea() self.autoInstallScrollArea.setWidgetResizable(True) - self.autoInstallScrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) - self.autoInstallScrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) - self.autoInstallScrollArea.setStyleSheet("QScrollArea { border: none; background: transparent; }") + self.autoInstallScrollArea.setStyleSheet(self.theme.SCROLL_AREA_STYLE) + QScroller.grabGesture(self.autoInstallScrollArea.viewport(), QScroller.ScrollerGestureType.LeftMouseButtonGesture) self.autoInstallContainer = QWidget() self.autoInstallContainerLayout = FlowLayout(self.autoInstallContainer) @@ -1163,6 +1162,20 @@ class MainWindow(QMainWindow): parent=self.autoInstallContainer, ) + # Hide badges and favorite button + if hasattr(card, 'steamLabel'): + card.steamLabel.setVisible(False) + if hasattr(card, 'egsLabel'): + card.egsLabel.setVisible(False) + if hasattr(card, 'portprotonLabel'): + card.portprotonLabel.setVisible(False) + if hasattr(card, 'protondbLabel'): + card.protondbLabel.setVisible(False) + if hasattr(card, 'anticheatLabel'): + card.anticheatLabel.setVisible(False) + if hasattr(card, 'favoriteLabel'): + card.favoriteLabel.setVisible(False) + self.autoInstallGameCards[exe_name] = card self.allAutoInstallCards.append(card) self.autoInstallContainerLayout.addWidget(card)