feat(settings): Added Gamepad type settings

Signed-off-by: Boris Yumankulov <boria138@altlinux.org>
This commit is contained in:
2025-10-15 15:30:31 +05:00
parent 476c896940
commit 82249d7eab
3 changed files with 61 additions and 45 deletions

View File

@@ -259,6 +259,25 @@ def save_rumble_config(rumble_enabled):
with open(CONFIG_FILE, "w", encoding="utf-8") as configfile:
cp.write(configfile)
def read_gamepad_type():
"""Reads the gamepad type from the [Gamepad] section.
Returns 'xbox' if the parameter is missing.
"""
cp = read_config_safely(CONFIG_FILE)
if cp is None or not cp.has_section("Gamepad") or not cp.has_option("Gamepad", "type"):
save_gamepad_type("xbox")
return "xbox"
return cp.get("Gamepad", "type", fallback="xbox").lower()
def save_gamepad_type(gpad_type):
"""Saves the gamepad type to the [Gamepad] section."""
cp = read_config_safely(CONFIG_FILE) or configparser.ConfigParser()
if "Gamepad" not in cp:
cp["Gamepad"] = {}
cp["Gamepad"]["type"] = gpad_type
with open(CONFIG_FILE, "w", encoding="utf-8") as configfile:
cp.write(configfile)
def ensure_default_proxy_config():
"""Ensures the [Proxy] section exists in the configuration file.
Creates it with empty values if missing.

View File

@@ -12,7 +12,7 @@ from portprotonqt.logger import get_logger
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
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.virtual_keyboard import VirtualKeyboard
@@ -87,8 +87,13 @@ class InputManager(QObject):
super().__init__(cast(QObject, main_window))
self._parent = main_window
self._gamepad_handling_enabled = True
self.gamepad_type = GamepadType.UNKNOWN
# Ensure attributes exist on main_window
type_str = read_gamepad_type()
if type_str == "playstation":
self.gamepad_type = GamepadType.PLAYSTATION
elif type_str == "xbox":
self.gamepad_type = GamepadType.XBOX
else:
self.gamepad_type = GamepadType.UNKNOWN
self._parent.currentDetailPage = getattr(self._parent, 'currentDetailPage', None)
self._parent.current_exec_line = getattr(self._parent, 'current_exec_line', None)
self._parent.current_add_game_dialog = getattr(self._parent, 'current_add_game_dialog', None)
@@ -271,38 +276,6 @@ class InputManager(QObject):
elif current_row_idx == 0:
self._parent.tabButtons[tab_index].setFocus(Qt.FocusReason.OtherFocusReason)
def detect_gamepad_type(self, device: InputDevice) -> GamepadType:
"""
Определяет тип геймпада по capabilities
"""
caps = device.capabilities()
keys = set(caps.get(ecodes.EV_KEY, []))
# Для EV_ABS вытаскиваем только коды (первый элемент кортежа)
abs_axes = {a if isinstance(a, int) else a[0] for a in caps.get(ecodes.EV_ABS, [])}
# Xbox layout
if {ecodes.BTN_SOUTH, ecodes.BTN_EAST, ecodes.BTN_NORTH, ecodes.BTN_WEST}.issubset(keys):
if {ecodes.ABS_X, ecodes.ABS_Y, ecodes.ABS_RX, ecodes.ABS_RY}.issubset(abs_axes):
self.gamepad_type = GamepadType.XBOX
return GamepadType.XBOX
# PlayStation layout
if ecodes.BTN_TOUCH in keys or (ecodes.BTN_DPAD_UP in keys and ecodes.BTN_EAST in keys):
self.gamepad_type = GamepadType.PLAYSTATION
logger.info(f"Detected {self.gamepad_type.value} controller: {device.name}")
return GamepadType.PLAYSTATION
# Steam Controller / Deck (трекпады)
if any(a for a in abs_axes if a >= ecodes.ABS_MT_SLOT):
self.gamepad_type = GamepadType.XBOX
logger.info(f"Detected {self.gamepad_type.value} controller: {device.name}")
return GamepadType.XBOX
# Fallback
self.gamepad_type = GamepadType.XBOX
return GamepadType.XBOX
def enable_file_explorer_mode(self, file_explorer):
"""Настройка обработки геймпада для FileExplorer"""
try:
@@ -1369,8 +1342,6 @@ class InputManager(QObject):
new_gamepad = self.find_gamepad()
if new_gamepad and new_gamepad != self.gamepad:
logger.info(f"Gamepad connected: {new_gamepad.name}")
self.detect_gamepad_type(new_gamepad)
logger.info(f"Detected gamepad type: {self.gamepad_type.value}")
self.stop_rumble()
self.gamepad = new_gamepad
if self.gamepad_thread:

View File

@@ -29,7 +29,7 @@ from portprotonqt.config_utils import (
read_display_filter, read_favorites, save_favorites, save_time_config, save_sort_method,
save_display_filter, save_proxy_config, read_proxy_config, read_fullscreen_config,
save_fullscreen_config, read_window_geometry, save_window_geometry, reset_config,
clear_cache, read_auto_fullscreen_gamepad, save_auto_fullscreen_gamepad, read_rumble_config, save_rumble_config
clear_cache, read_auto_fullscreen_gamepad, save_auto_fullscreen_gamepad, read_rumble_config, save_rumble_config, read_gamepad_type, save_gamepad_type
)
from portprotonqt.localization import _, get_egs_language, read_metadata_translations
from portprotonqt.howlongtobeat_api import HowLongToBeat
@@ -1784,7 +1784,22 @@ class MainWindow(QMainWindow):
self.gamesDisplayCombo.setCurrentIndex(idx)
formLayout.addRow(self.gamesDisplayTitle, self.gamesDisplayCombo)
# 4. Proxy settings
# 4 Gamepad Type
self.gamepadTypeCombo = QComboBox()
self.gamepadTypeCombo.addItems(["Xbox", "PlayStation"])
self.gamepadTypeCombo.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
self.gamepadTypeCombo.setStyleSheet(self.theme.SETTINGS_COMBO_STYLE)
self.gamepadTypeTitle = QLabel(_("Gamepad Type:"))
self.gamepadTypeTitle.setStyleSheet(self.theme.PARAMS_TITLE_STYLE)
self.gamepadTypeTitle.setFocusPolicy(Qt.FocusPolicy.NoFocus)
current_type_str = read_gamepad_type()
if current_type_str == "playstation":
self.gamepadTypeCombo.setCurrentText("PlayStation")
else:
self.gamepadTypeCombo.setCurrentText("Xbox")
formLayout.addRow(self.gamepadTypeTitle, self.gamepadTypeCombo)
# 5. Proxy settings
self.proxyUrlEdit = CustomLineEdit(self, theme=self.theme)
self.proxyUrlEdit.setPlaceholderText(_("Proxy URL"))
self.proxyUrlEdit.setStyleSheet(self.theme.PROXY_INPUT_STYLE)
@@ -1816,7 +1831,7 @@ class MainWindow(QMainWindow):
self.proxyPasswordTitle.setFocusPolicy(Qt.FocusPolicy.NoFocus)
formLayout.addRow(self.proxyPasswordTitle, self.proxyPasswordEdit)
# 5. Fullscreen setting for application
# 6. Fullscreen setting for application
self.fullscreenCheckBox = QCheckBox(_("Launch Application in Fullscreen"))
self.fullscreenCheckBox.setStyleSheet(self.theme.SETTINGS_CHECKBOX_STYLE)
self.fullscreenCheckBox.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
@@ -1827,7 +1842,7 @@ class MainWindow(QMainWindow):
self.fullscreenCheckBox.setChecked(current_fullscreen)
formLayout.addRow(self.fullscreenTitle, self.fullscreenCheckBox)
# 6. Automatic fullscreen on gamepad connection
# 7. Automatic fullscreen on gamepad connection
self.autoFullscreenGamepadCheckBox = QCheckBox(_("Auto Fullscreen on Gamepad connected"))
self.autoFullscreenGamepadCheckBox.setStyleSheet(self.theme.SETTINGS_CHECKBOX_STYLE)
self.autoFullscreenGamepadCheckBox.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
@@ -1839,7 +1854,7 @@ class MainWindow(QMainWindow):
self.autoFullscreenGamepadCheckBox.setChecked(current_auto_fullscreen)
formLayout.addRow(self.autoFullscreenGamepadTitle, self.autoFullscreenGamepadCheckBox)
# 7. Gamepad haptic feedback config
# 8. Gamepad haptic feedback config
self.gamepadRumbleCheckBox = QCheckBox(_("Gamepad haptic feedback"))
self.gamepadRumbleCheckBox.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
self.gamepadRumbleCheckBox.setStyleSheet(self.theme.SETTINGS_CHECKBOX_STYLE)
@@ -1850,7 +1865,7 @@ class MainWindow(QMainWindow):
self.gamepadRumbleCheckBox.setChecked(current_rumble_state)
formLayout.addRow(self.gamepadRumbleTitle, self.gamepadRumbleCheckBox)
# # 8. Legendary Authentication
# # 9. Legendary Authentication
# self.legendaryAuthButton = AutoSizeButton(
# _("Open Legendary Login"),
# icon=self.theme_manager.get_icon("login")self.theme_manager.get_icon("login")
@@ -2021,8 +2036,6 @@ class MainWindow(QMainWindow):
old_filter = self.current_display_filter
save_display_filter(filter_key)
save_display_filter(filter_key)
proxy_url = self.proxyUrlEdit.text().strip()
proxy_user = self.proxyUserEdit.text().strip()
proxy_password = self.proxyPasswordEdit.text().strip()
@@ -2037,6 +2050,19 @@ class MainWindow(QMainWindow):
rumble_enabled = self.gamepadRumbleCheckBox.isChecked()
save_rumble_config(rumble_enabled)
gamepad_type_text = self.gamepadTypeCombo.currentText()
gpad_type = "playstation" if gamepad_type_text == "PlayStation" else "xbox"
save_gamepad_type(gpad_type)
if hasattr(self, 'input_manager'):
if gpad_type == "playstation":
self.input_manager.gamepad_type = GamepadType.PLAYSTATION
elif gpad_type == "xbox":
self.input_manager.gamepad_type = GamepadType.XBOX
else:
self.input_manager.gamepad_type = GamepadType.UNKNOWN
self.updateControlHints()
if filter_key != old_filter:
for card in self.game_library_manager.game_card_cache.values():
card.update_badge_visibility(filter_key)