From 3026e7da4e69f6e42bf29ee4cafab7cf9abc8834 Mon Sep 17 00:00:00 2001 From: Boris Yumankulov Date: Thu, 27 Nov 2025 15:51:39 +0500 Subject: [PATCH] fix: fix code work with pyside 6.10 Signed-off-by: Boris Yumankulov --- portprotonqt/game_card.py | 9 ++--- portprotonqt/game_library_manager.py | 14 ++++--- portprotonqt/image_utils.py | 6 +-- portprotonqt/main_window.py | 22 +++++----- portprotonqt/virtual_keyboard.py | 60 +++++++++++++++++----------- pyproject.toml | 2 +- renovate.json | 2 +- uv.lock | 2 +- 8 files changed, 66 insertions(+), 51 deletions(-) diff --git a/portprotonqt/game_card.py b/portprotonqt/game_card.py index 8b06cd6..aca4f6a 100644 --- a/portprotonqt/game_card.py +++ b/portprotonqt/game_card.py @@ -1,7 +1,6 @@ from PySide6.QtGui import QPainter, QColor, QDesktopServices from PySide6.QtCore import Signal, Property, Qt, QUrl, QTimer from PySide6.QtWidgets import QFrame, QGraphicsDropShadowEffect, QVBoxLayout, QWidget, QStackedLayout, QLabel -from collections.abc import Callable from portprotonqt.image_utils import load_pixmap_async, round_corners from portprotonqt.localization import _ from portprotonqt.config_utils import read_favorites, save_favorites, read_display_filter, read_theme_from_config @@ -10,8 +9,6 @@ from portprotonqt.custom_widgets import ClickableLabel from portprotonqt.portproton_api import PortProtonAPI from portprotonqt.downloader import Downloader from portprotonqt.animations import GameCardAnimations -from typing import cast - class GameCard(QFrame): borderWidthChanged = Signal() @@ -455,9 +452,9 @@ class GameCard(QFrame): self.update_scale() self.scaleChanged.emit() - borderWidth = Property(int, getBorderWidth, setBorderWidth, None, "", notify=cast(Callable[[], None], borderWidthChanged)) - gradientAngle = Property(float, getGradientAngle, setGradientAngle, None, "", notify=cast(Callable[[], None], gradientAngleChanged)) - scale = Property(float, getScale, setScale, None, "", notify=cast(Callable[[], None], scaleChanged)) + borderWidth = Property(int, getBorderWidth, setBorderWidth, None, "", notify=borderWidthChanged) + gradientAngle = Property(float, getGradientAngle, setGradientAngle, None, "", notify=gradientAngleChanged) + scale = Property(float, getScale, setScale, None, "", notify=scaleChanged) def paintEvent(self, event): diff --git a/portprotonqt/game_library_manager.py b/portprotonqt/game_library_manager.py index 4ad8c97..207f352 100644 --- a/portprotonqt/game_library_manager.py +++ b/portprotonqt/game_library_manager.py @@ -222,13 +222,17 @@ class GameLibraryManager: def force_update_cards_library(self): if self.gamesListWidget and self.gamesListLayout: + # Use singleShot to ensure UI updates happen after all other operations complete + # This prevents potential freezing in PySide 6.10.1 + QTimer.singleShot(0, self._perform_force_update) + + def _perform_force_update(self): + """Perform the actual force update on the layout.""" + if self.gamesListLayout: self.gamesListLayout.invalidate() + if self.gamesListWidget: + self.gamesListWidget.adjustSize() self.gamesListWidget.updateGeometry() - widget = self.gamesListWidget - QTimer.singleShot(0, lambda: ( - widget.adjustSize(), - widget.updateGeometry() - )) def _update_game_grid_immediate(self): """Updates the game grid with the provided or current game list.""" diff --git a/portprotonqt/image_utils.py b/portprotonqt/image_utils.py index 63b9142..26e4bcf 100644 --- a/portprotonqt/image_utils.py +++ b/portprotonqt/image_utils.py @@ -199,9 +199,9 @@ def load_pixmap_async(cover: str, width: int, height: int, callback: Callable[[Q painter.end() finish_with(pixmap) - with queue_lock: - image_load_queue.put(process_image) - image_executor.submit(lambda: image_load_queue.get()()) + # Submit the process_image function directly to the executor + # This avoids the potential blocking issue with queue.get() in PySide 6.10.1 + image_executor.submit(process_image) def round_corners(pixmap, radius): """ diff --git a/portprotonqt/main_window.py b/portprotonqt/main_window.py index 0575e0e..d588157 100644 --- a/portprotonqt/main_window.py +++ b/portprotonqt/main_window.py @@ -855,19 +855,17 @@ class MainWindow(QMainWindow): if mgr.gamesListWidget and mgr.gamesListLayout: games_layout = mgr.gamesListLayout games_widget = mgr.gamesListWidget - QTimer.singleShot(0, lambda: ( - games_layout.invalidate(), - games_widget.adjustSize(), - games_widget.updateGeometry() - )) + # Update layout updates to be more compatible with PySide 6.10.1 + QTimer.singleShot(0, lambda: games_layout.invalidate()) + QTimer.singleShot(10, lambda: games_widget.adjustSize()) + QTimer.singleShot(15, lambda: games_widget.updateGeometry()) if hasattr(self, "autoInstallContainer") and hasattr(self, "autoInstallContainerLayout"): auto_layout = self.autoInstallContainerLayout auto_widget = self.autoInstallContainer - QTimer.singleShot(0, lambda: ( - auto_layout.invalidate(), - auto_widget.adjustSize(), - auto_widget.updateGeometry() - )) + # Update layout updates to be more compatible with PySide 6.10.1 + QTimer.singleShot(0, lambda: auto_layout.invalidate()) + QTimer.singleShot(10, lambda: auto_widget.adjustSize()) + QTimer.singleShot(15, lambda: auto_widget.updateGeometry()) def openSystemOverlay(self): @@ -1234,7 +1232,9 @@ class MainWindow(QMainWindow): while self.autoInstallContainerLayout.count(): child = self.autoInstallContainerLayout.takeAt(0) if child: - child.widget().deleteLater() + widget = child.widget() + if widget: + widget.deleteLater() self.autoInstallGameCards.clear() self.allAutoInstallCards.clear() diff --git a/portprotonqt/virtual_keyboard.py b/portprotonqt/virtual_keyboard.py index 7c49cf4..5567305 100644 --- a/portprotonqt/virtual_keyboard.py +++ b/portprotonqt/virtual_keyboard.py @@ -166,8 +166,10 @@ class VirtualKeyboard(QFrame): # Очищаем предыдущие кнопки while self.keyboard_layout.count(): item = self.keyboard_layout.takeAt(0) - if item.widget(): - item.widget().deleteLater() + if item: + widget = item.widget() + if widget: + widget.deleteLater() fixed_w = self.button_width fixed_h = self.button_height @@ -280,8 +282,10 @@ class VirtualKeyboard(QFrame): if coords: row, col = coords item = self.keyboard_layout.itemAtPosition(row, col) - if item and item.widget(): - item.widget().setFocus() + if item: + widget = item.widget() + if widget: + widget.setFocus() def up_key(self): """Перемещает курсор в QLineEdit вверх/в начало, если клавиатура видима""" @@ -392,7 +396,8 @@ class VirtualKeyboard(QFrame): if self.current_input_widget is not None: self.current_input_widget.insert('\t') self.keyPressed.emit('Tab') - self.current_input_widget.setFocus() + if self.current_input_widget: + self.current_input_widget.setFocus() self.highlight_cursor_position() def on_caps_click(self): @@ -530,8 +535,9 @@ class VirtualKeyboard(QFrame): search_col = current_col + col_span while search_col < num_cols: item = self.keyboard_layout.itemAtPosition(search_row, search_col) - if item and item.widget() and item.widget().isEnabled(): - next_button = cast(QPushButton, item.widget()) + widget = item.widget() if item else None + if widget and widget.isEnabled(): + next_button = cast(QPushButton, widget) next_button.setFocus() found = True break @@ -544,8 +550,9 @@ class VirtualKeyboard(QFrame): # Ищем первую кнопку в этой строке while search_col < num_cols: item = self.keyboard_layout.itemAtPosition(search_row, search_col) - if item and item.widget() and item.widget().isEnabled(): - next_button = cast(QPushButton, item.widget()) + widget = item.widget() if item else None + if widget and widget.isEnabled(): + next_button = cast(QPushButton, widget) next_button.setFocus() found = True break @@ -557,8 +564,9 @@ class VirtualKeyboard(QFrame): search_col = current_col - 1 while search_col >= 0: item = self.keyboard_layout.itemAtPosition(search_row, search_col) - if item and item.widget() and item.widget().isEnabled(): - next_button = cast(QPushButton, item.widget()) + widget = item.widget() if item else None + if widget and widget.isEnabled(): + next_button = cast(QPushButton, widget) next_button.setFocus() found = True break @@ -571,8 +579,9 @@ class VirtualKeyboard(QFrame): # Ищем последнюю кнопку в этой строке while search_col >= 0: item = self.keyboard_layout.itemAtPosition(search_row, search_col) - if item and item.widget() and item.widget().isEnabled(): - next_button = cast(QPushButton, item.widget()) + widget = item.widget() if item else None + if widget and widget.isEnabled(): + next_button = cast(QPushButton, widget) next_button.setFocus() found = True break @@ -584,8 +593,9 @@ class VirtualKeyboard(QFrame): search_row = current_row + row_span while search_row < num_rows: item = self.keyboard_layout.itemAtPosition(search_row, search_col) - if item and item.widget() and item.widget().isEnabled(): - next_button = cast(QPushButton, item.widget()) + widget = item.widget() if item else None + if widget and widget.isEnabled(): + next_button = cast(QPushButton, widget) next_button.setFocus() found = True break @@ -598,8 +608,9 @@ class VirtualKeyboard(QFrame): # Ищем первую кнопку в этом столбце while search_row < num_rows: item = self.keyboard_layout.itemAtPosition(search_row, search_col) - if item and item.widget() and item.widget().isEnabled(): - next_button = cast(QPushButton, item.widget()) + widget = item.widget() if item else None + if widget and widget.isEnabled(): + next_button = cast(QPushButton, widget) next_button.setFocus() found = True break @@ -611,8 +622,9 @@ class VirtualKeyboard(QFrame): search_row = current_row - 1 while search_row >= 0: item = self.keyboard_layout.itemAtPosition(search_row, search_col) - if item and item.widget() and item.widget().isEnabled(): - next_button = cast(QPushButton, item.widget()) + widget = item.widget() if item else None + if widget and widget.isEnabled(): + next_button = cast(QPushButton, widget) next_button.setFocus() found = True break @@ -625,8 +637,9 @@ class VirtualKeyboard(QFrame): # Ищем последнюю кнопку в этом столбце while search_row >= 0: item = self.keyboard_layout.itemAtPosition(search_row, search_col) - if item and item.widget() and item.widget().isEnabled(): - next_button = cast(QPushButton, item.widget()) + widget = item.widget() if item else None + if widget and widget.isEnabled(): + next_button = cast(QPushButton, widget) next_button.setFocus() found = True break @@ -637,6 +650,7 @@ class VirtualKeyboard(QFrame): for row in range(self.keyboard_layout.rowCount()): for col in range(self.keyboard_layout.columnCount()): item = self.keyboard_layout.itemAtPosition(row, col) - if item and item.widget() and item.widget().isEnabled(): - return cast(QPushButton, item.widget()) + widget = item.widget() if item else None + if widget and widget.isEnabled(): + return cast(QPushButton, widget) return None diff --git a/pyproject.toml b/pyproject.toml index 04ba790..e153138 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,7 @@ dependencies = [ "orjson>=3.11.3", "pillow>=12.0.0", "psutil>=7.1.0", - "pyside6==6.9.1", + "pyside6>=6.9.1", "pyudev>=0.24.3", "requests>=2.32.5", "tqdm>=4.67.1", diff --git a/renovate.json b/renovate.json index 6c42956..3111ce3 100644 --- a/renovate.json +++ b/renovate.json @@ -52,7 +52,7 @@ "groupName": "Python dependencies" }, { - "matchPackageNames": ["numpy", "setuptools", "python", "pyside6"], + "matchPackageNames": ["numpy", "setuptools", "python"], "enabled": false, "description": "Disabled due to Python 3.10 incompatibility with numpy>=2.3.2 (requires Python>=3.11)" }, diff --git a/uv.lock b/uv.lock index e9752dc..02d46cf 100644 --- a/uv.lock +++ b/uv.lock @@ -560,7 +560,7 @@ requires-dist = [ { name = "orjson", specifier = ">=3.11.3" }, { name = "pillow", specifier = ">=12.0.0" }, { name = "psutil", specifier = ">=7.1.0" }, - { name = "pyside6", specifier = "==6.9.1" }, + { name = "pyside6", specifier = ">=6.9.1" }, { name = "pyudev", specifier = ">=0.24.3" }, { name = "requests", specifier = ">=2.32.5" }, { name = "tqdm", specifier = ">=4.67.1" },