fix: enforce mutual exclusivity of hovered and focused states in GameCard
All checks were successful
Code and build check / Check code (push) Successful in 1m40s
Code and build check / Build with uv (push) Successful in 54s

Signed-off-by: Boris Yumankulov <boria138@altlinux.org>
This commit is contained in:
2025-06-17 22:58:57 +05:00
parent 593db00166
commit 32bbe89911
2 changed files with 48 additions and 4 deletions

View File

@ -26,6 +26,7 @@ class GameCard(QFrame):
removeFromSteamRequested = Signal(str, str) # name, exec_line
openGameFolderRequested = Signal(str, str) # name, exec_line
hoverChanged = Signal(str, bool)
focusChanged = Signal(str, bool)
def __init__(self, name, description, cover_path, appid, controller_support, exec_line,
last_launch, formatted_playtime, protondb_tier, anticheat_status, last_launch_ts, playtime_seconds, game_source,
@ -475,7 +476,9 @@ class GameCard(QFrame):
def enterEvent(self, event):
self._hovered = True
self._focused = False
self.hoverChanged.emit(self.name, True)
self.thickness_anim.stop()
if self._isPulseAnimationConnected:
self.thickness_anim.finished.disconnect(self.startPulseAnimation)
@ -496,6 +499,7 @@ class GameCard(QFrame):
self.gradient_anim.setLoopCount(-1)
self.gradient_anim.start()
self.clearFocus()
super().enterEvent(event)
def leaveEvent(self, event):
@ -521,6 +525,10 @@ class GameCard(QFrame):
def focusInEvent(self, event):
self._focused = True
self._hovered = False
self.hoverChanged.emit(self.name, False)
self.focusChanged.emit(self.name, True)
self.thickness_anim.stop()
if self._isPulseAnimationConnected:
self.thickness_anim.finished.disconnect(self.startPulseAnimation)
@ -545,7 +553,8 @@ class GameCard(QFrame):
def focusOutEvent(self, event):
self._focused = False
if not self._hovered: # Сохраняем анимацию, если есть наведение
self.focusChanged.emit(self.name, False)
if not self._hovered:
if self.gradient_anim:
self.gradient_anim.stop()
self.gradient_anim = None

View File

@ -56,6 +56,7 @@ class MainWindow(QMainWindow):
self.current_exec_line = None
self.currentDetailPage = None
self.current_play_button = None
self.current_focused_card = None
self.pending_games = []
self.game_card_cache = {}
self.pending_images = {}
@ -242,10 +243,39 @@ class MainWindow(QMainWindow):
self.updateGameGrid()
self.progress_bar.setVisible(False)
def _on_card_focused(self, game_name: str, is_focused: bool):
"""Обработчик сигнала focusChanged от GameCard."""
card_key = None
for key, card in self.game_card_cache.items():
if card.name == game_name:
card_key = key
break
if not card_key:
return
card = self.game_card_cache[card_key]
if is_focused:
# Если карточка получила фокус
if self.current_hovered_card and self.current_hovered_card != card:
# Сбрасываем текущую hovered карточку
self.current_hovered_card._hovered = False
self.current_hovered_card.leaveEvent(None)
self.current_hovered_card = None
if self.current_focused_card and self.current_focused_card != card:
# Сбрасываем текущую focused карточку
self.current_focused_card._focused = False
self.current_focused_card.clearFocus()
self.current_focused_card = card
else:
# Если карточка потеряла фокус
if self.current_focused_card == card:
self.current_focused_card = None
def _on_card_hovered(self, game_name: str, is_hovered: bool):
"""Обработчик сигнала hoverChanged от GameCard."""
card_key = None
# Находим ключ карточки по имени игры
for key, card in self.game_card_cache.items():
if card.name == game_name:
card_key = key
@ -258,10 +288,14 @@ class MainWindow(QMainWindow):
if is_hovered:
# Если мышь наведена на карточку
if self.current_focused_card and self.current_focused_card != card:
# Сбрасываем текущую focused карточку
self.current_focused_card._focused = False
self.current_focused_card.clearFocus()
if self.current_hovered_card and self.current_hovered_card != card:
# Сбрасываем предыдущую выделенную карточку
# Сбрасываем предыдущую hovered карточку
self.current_hovered_card._hovered = False
self.current_hovered_card.leaveEvent(None) # Принудительно вызываем leaveEvent
self.current_hovered_card.leaveEvent(None)
self.current_hovered_card = card
else:
# Если мышь покинула карточку
@ -709,6 +743,7 @@ class MainWindow(QMainWindow):
context_menu_manager=self.context_menu_manager
)
card.hoverChanged.connect(self._on_card_hovered)
card.focusChanged.connect(self._on_card_focused)
# Подключаем сигналы контекстного меню
card.editShortcutRequested.connect(self.context_menu_manager.edit_game_shortcut)
card.deleteGameRequested.connect(self.context_menu_manager.delete_game)