forked from Boria138/PortProtonQt
feat(settings): Added Gamepad type settings
Signed-off-by: Boris Yumankulov <boria138@altlinux.org>
This commit is contained in:
@@ -259,6 +259,25 @@ def save_rumble_config(rumble_enabled):
|
|||||||
with open(CONFIG_FILE, "w", encoding="utf-8") as configfile:
|
with open(CONFIG_FILE, "w", encoding="utf-8") as configfile:
|
||||||
cp.write(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():
|
def ensure_default_proxy_config():
|
||||||
"""Ensures the [Proxy] section exists in the configuration file.
|
"""Ensures the [Proxy] section exists in the configuration file.
|
||||||
Creates it with empty values if missing.
|
Creates it with empty values if missing.
|
||||||
|
@@ -12,7 +12,7 @@ from portprotonqt.logger import get_logger
|
|||||||
from portprotonqt.image_utils import FullscreenDialog
|
from portprotonqt.image_utils import FullscreenDialog
|
||||||
from portprotonqt.custom_widgets import NavLabel, AutoSizeButton
|
from portprotonqt.custom_widgets import NavLabel, AutoSizeButton
|
||||||
from portprotonqt.game_card import GameCard
|
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.dialogs import AddGameDialog, WinetricksDialog
|
||||||
from portprotonqt.virtual_keyboard import VirtualKeyboard
|
from portprotonqt.virtual_keyboard import VirtualKeyboard
|
||||||
|
|
||||||
@@ -87,8 +87,13 @@ class InputManager(QObject):
|
|||||||
super().__init__(cast(QObject, main_window))
|
super().__init__(cast(QObject, main_window))
|
||||||
self._parent = main_window
|
self._parent = main_window
|
||||||
self._gamepad_handling_enabled = True
|
self._gamepad_handling_enabled = True
|
||||||
self.gamepad_type = GamepadType.UNKNOWN
|
type_str = read_gamepad_type()
|
||||||
# Ensure attributes exist on main_window
|
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.currentDetailPage = getattr(self._parent, 'currentDetailPage', None)
|
||||||
self._parent.current_exec_line = getattr(self._parent, 'current_exec_line', 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)
|
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:
|
elif current_row_idx == 0:
|
||||||
self._parent.tabButtons[tab_index].setFocus(Qt.FocusReason.OtherFocusReason)
|
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):
|
def enable_file_explorer_mode(self, file_explorer):
|
||||||
"""Настройка обработки геймпада для FileExplorer"""
|
"""Настройка обработки геймпада для FileExplorer"""
|
||||||
try:
|
try:
|
||||||
@@ -1369,8 +1342,6 @@ class InputManager(QObject):
|
|||||||
new_gamepad = self.find_gamepad()
|
new_gamepad = self.find_gamepad()
|
||||||
if new_gamepad and new_gamepad != self.gamepad:
|
if new_gamepad and new_gamepad != self.gamepad:
|
||||||
logger.info(f"Gamepad connected: {new_gamepad.name}")
|
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.stop_rumble()
|
||||||
self.gamepad = new_gamepad
|
self.gamepad = new_gamepad
|
||||||
if self.gamepad_thread:
|
if self.gamepad_thread:
|
||||||
|
@@ -29,7 +29,7 @@ from portprotonqt.config_utils import (
|
|||||||
read_display_filter, read_favorites, save_favorites, save_time_config, save_sort_method,
|
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_display_filter, save_proxy_config, read_proxy_config, read_fullscreen_config,
|
||||||
save_fullscreen_config, read_window_geometry, save_window_geometry, reset_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.localization import _, get_egs_language, read_metadata_translations
|
||||||
from portprotonqt.howlongtobeat_api import HowLongToBeat
|
from portprotonqt.howlongtobeat_api import HowLongToBeat
|
||||||
@@ -1784,7 +1784,22 @@ class MainWindow(QMainWindow):
|
|||||||
self.gamesDisplayCombo.setCurrentIndex(idx)
|
self.gamesDisplayCombo.setCurrentIndex(idx)
|
||||||
formLayout.addRow(self.gamesDisplayTitle, self.gamesDisplayCombo)
|
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 = CustomLineEdit(self, theme=self.theme)
|
||||||
self.proxyUrlEdit.setPlaceholderText(_("Proxy URL"))
|
self.proxyUrlEdit.setPlaceholderText(_("Proxy URL"))
|
||||||
self.proxyUrlEdit.setStyleSheet(self.theme.PROXY_INPUT_STYLE)
|
self.proxyUrlEdit.setStyleSheet(self.theme.PROXY_INPUT_STYLE)
|
||||||
@@ -1816,7 +1831,7 @@ class MainWindow(QMainWindow):
|
|||||||
self.proxyPasswordTitle.setFocusPolicy(Qt.FocusPolicy.NoFocus)
|
self.proxyPasswordTitle.setFocusPolicy(Qt.FocusPolicy.NoFocus)
|
||||||
formLayout.addRow(self.proxyPasswordTitle, self.proxyPasswordEdit)
|
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 = QCheckBox(_("Launch Application in Fullscreen"))
|
||||||
self.fullscreenCheckBox.setStyleSheet(self.theme.SETTINGS_CHECKBOX_STYLE)
|
self.fullscreenCheckBox.setStyleSheet(self.theme.SETTINGS_CHECKBOX_STYLE)
|
||||||
self.fullscreenCheckBox.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
|
self.fullscreenCheckBox.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
|
||||||
@@ -1827,7 +1842,7 @@ class MainWindow(QMainWindow):
|
|||||||
self.fullscreenCheckBox.setChecked(current_fullscreen)
|
self.fullscreenCheckBox.setChecked(current_fullscreen)
|
||||||
formLayout.addRow(self.fullscreenTitle, self.fullscreenCheckBox)
|
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 = QCheckBox(_("Auto Fullscreen on Gamepad connected"))
|
||||||
self.autoFullscreenGamepadCheckBox.setStyleSheet(self.theme.SETTINGS_CHECKBOX_STYLE)
|
self.autoFullscreenGamepadCheckBox.setStyleSheet(self.theme.SETTINGS_CHECKBOX_STYLE)
|
||||||
self.autoFullscreenGamepadCheckBox.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
|
self.autoFullscreenGamepadCheckBox.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
|
||||||
@@ -1839,7 +1854,7 @@ class MainWindow(QMainWindow):
|
|||||||
self.autoFullscreenGamepadCheckBox.setChecked(current_auto_fullscreen)
|
self.autoFullscreenGamepadCheckBox.setChecked(current_auto_fullscreen)
|
||||||
formLayout.addRow(self.autoFullscreenGamepadTitle, self.autoFullscreenGamepadCheckBox)
|
formLayout.addRow(self.autoFullscreenGamepadTitle, self.autoFullscreenGamepadCheckBox)
|
||||||
|
|
||||||
# 7. Gamepad haptic feedback config
|
# 8. Gamepad haptic feedback config
|
||||||
self.gamepadRumbleCheckBox = QCheckBox(_("Gamepad haptic feedback"))
|
self.gamepadRumbleCheckBox = QCheckBox(_("Gamepad haptic feedback"))
|
||||||
self.gamepadRumbleCheckBox.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
|
self.gamepadRumbleCheckBox.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
|
||||||
self.gamepadRumbleCheckBox.setStyleSheet(self.theme.SETTINGS_CHECKBOX_STYLE)
|
self.gamepadRumbleCheckBox.setStyleSheet(self.theme.SETTINGS_CHECKBOX_STYLE)
|
||||||
@@ -1850,7 +1865,7 @@ class MainWindow(QMainWindow):
|
|||||||
self.gamepadRumbleCheckBox.setChecked(current_rumble_state)
|
self.gamepadRumbleCheckBox.setChecked(current_rumble_state)
|
||||||
formLayout.addRow(self.gamepadRumbleTitle, self.gamepadRumbleCheckBox)
|
formLayout.addRow(self.gamepadRumbleTitle, self.gamepadRumbleCheckBox)
|
||||||
|
|
||||||
# # 8. Legendary Authentication
|
# # 9. Legendary Authentication
|
||||||
# self.legendaryAuthButton = AutoSizeButton(
|
# self.legendaryAuthButton = AutoSizeButton(
|
||||||
# _("Open Legendary Login"),
|
# _("Open Legendary Login"),
|
||||||
# icon=self.theme_manager.get_icon("login")self.theme_manager.get_icon("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
|
old_filter = self.current_display_filter
|
||||||
save_display_filter(filter_key)
|
save_display_filter(filter_key)
|
||||||
|
|
||||||
save_display_filter(filter_key)
|
|
||||||
|
|
||||||
proxy_url = self.proxyUrlEdit.text().strip()
|
proxy_url = self.proxyUrlEdit.text().strip()
|
||||||
proxy_user = self.proxyUserEdit.text().strip()
|
proxy_user = self.proxyUserEdit.text().strip()
|
||||||
proxy_password = self.proxyPasswordEdit.text().strip()
|
proxy_password = self.proxyPasswordEdit.text().strip()
|
||||||
@@ -2037,6 +2050,19 @@ class MainWindow(QMainWindow):
|
|||||||
rumble_enabled = self.gamepadRumbleCheckBox.isChecked()
|
rumble_enabled = self.gamepadRumbleCheckBox.isChecked()
|
||||||
save_rumble_config(rumble_enabled)
|
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:
|
if filter_key != old_filter:
|
||||||
for card in self.game_library_manager.game_card_cache.values():
|
for card in self.game_library_manager.game_card_cache.values():
|
||||||
card.update_badge_visibility(filter_key)
|
card.update_badge_visibility(filter_key)
|
||||||
|
Reference in New Issue
Block a user