feat: added scale animation to game card hover and focus
Signed-off-by: Boris Yumankulov <boria138@altlinux.org>
This commit is contained in:
@@ -12,29 +12,27 @@ from portprotonqt.custom_widgets import ClickableLabel
|
||||
from portprotonqt.portproton_api import PortProtonAPI
|
||||
from portprotonqt.downloader import Downloader
|
||||
from portprotonqt.animations import GameCardAnimations
|
||||
import weakref
|
||||
from typing import cast
|
||||
|
||||
|
||||
class GameCard(QFrame):
|
||||
borderWidthChanged = Signal()
|
||||
gradientAngleChanged = Signal()
|
||||
# Signals for context menu actions
|
||||
editShortcutRequested = Signal(str, str, str) # name, exec_line, cover_path
|
||||
deleteGameRequested = Signal(str, str) # name, exec_line
|
||||
addToMenuRequested = Signal(str, str) # name, exec_line
|
||||
removeFromMenuRequested = Signal(str) # name
|
||||
addToDesktopRequested = Signal(str, str) # name, exec_line
|
||||
removeFromDesktopRequested = Signal(str) # name
|
||||
addToSteamRequested = Signal(str, str, str) # name, exec_line, cover_path
|
||||
removeFromSteamRequested = Signal(str, str) # name, exec_line
|
||||
openGameFolderRequested = Signal(str, str) # name, exec_line
|
||||
scaleChanged = Signal()
|
||||
editShortcutRequested = Signal(str, str, str)
|
||||
deleteGameRequested = Signal(str, str)
|
||||
addToMenuRequested = Signal(str, str)
|
||||
removeFromMenuRequested = Signal(str)
|
||||
addToDesktopRequested = Signal(str, str)
|
||||
removeFromDesktopRequested = Signal(str)
|
||||
addToSteamRequested = Signal(str, str, str)
|
||||
removeFromSteamRequested = Signal(str, str)
|
||||
openGameFolderRequested = Signal(str, str)
|
||||
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,
|
||||
select_callback, theme=None, card_width=250, parent=None, context_menu_manager=None):
|
||||
last_launch, formatted_playtime, protondb_tier, anticheat_status, last_launch_ts, playtime_seconds, game_source,
|
||||
select_callback, theme=None, card_width=250, parent=None, context_menu_manager=None):
|
||||
super().__init__(parent)
|
||||
self.name = name
|
||||
self.description = description
|
||||
@@ -49,7 +47,9 @@ class GameCard(QFrame):
|
||||
self.game_source = game_source
|
||||
self.last_launch_ts = last_launch_ts
|
||||
self.playtime_seconds = playtime_seconds
|
||||
self.card_width = card_width
|
||||
self.base_card_width = card_width
|
||||
self.base_pixmap = None
|
||||
self.base_font_size = None
|
||||
|
||||
self.select_callback = select_callback
|
||||
self.context_menu_manager = context_menu_manager
|
||||
@@ -67,75 +67,46 @@ class GameCard(QFrame):
|
||||
self.egs_visible = (str(game_source).lower() == "epic" and self.display_filter in ("all", "favorites"))
|
||||
self.portproton_visible = (str(game_source).lower() == "portproton" and self.display_filter in ("all", "favorites"))
|
||||
|
||||
# Дополнительное пространство для анимации
|
||||
extra_margin = 20
|
||||
self.setFixedSize(card_width + extra_margin, int(card_width * 1.6) + extra_margin)
|
||||
self.base_extra_margin = 20
|
||||
self.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
|
||||
self.setStyleSheet(self.theme.GAME_CARD_WINDOW_STYLE)
|
||||
|
||||
# Параметры анимации обводки
|
||||
self._borderWidth = self.theme.GAME_CARD_ANIMATION["default_border_width"]
|
||||
self._gradientAngle = self.theme.GAME_CARD_ANIMATION["gradient_start_angle"]
|
||||
self._scale = self.theme.GAME_CARD_ANIMATION["default_scale"]
|
||||
self._hovered = False
|
||||
self._focused = False
|
||||
|
||||
# Анимации
|
||||
self.animations = GameCardAnimations(self, self.theme)
|
||||
self.animations.setup_animations()
|
||||
|
||||
# Тень
|
||||
shadow = QGraphicsDropShadowEffect(self)
|
||||
shadow.setBlurRadius(20)
|
||||
shadow.setColor(QColor(0, 0, 0, 150))
|
||||
shadow.setOffset(0, 0)
|
||||
self.setGraphicsEffect(shadow)
|
||||
self.shadow = QGraphicsDropShadowEffect(self)
|
||||
self.shadow.setBlurRadius(20)
|
||||
self.shadow.setColor(QColor(0, 0, 0, 150))
|
||||
self.shadow.setOffset(0, 0)
|
||||
self.setGraphicsEffect(self.shadow)
|
||||
|
||||
# Отступы
|
||||
layout = QVBoxLayout(self)
|
||||
layout.setContentsMargins(extra_margin // 2, extra_margin // 2, extra_margin // 2, extra_margin // 2)
|
||||
layout.setSpacing(5)
|
||||
self.layout_ = QVBoxLayout(self)
|
||||
self.layout_.setSpacing(5)
|
||||
self.layout_.setContentsMargins(self.base_extra_margin // 2, self.base_extra_margin // 2, self.base_extra_margin // 2, self.base_extra_margin // 2)
|
||||
|
||||
# Контейнер обложки
|
||||
coverWidget = QWidget()
|
||||
coverWidget.setFixedSize(card_width, int(card_width * 1.2))
|
||||
coverLayout = QStackedLayout(coverWidget)
|
||||
self.coverWidget = QWidget()
|
||||
coverLayout = QStackedLayout(self.coverWidget)
|
||||
coverLayout.setContentsMargins(0, 0, 0, 0)
|
||||
coverLayout.setStackingMode(QStackedLayout.StackingMode.StackAll)
|
||||
|
||||
# Обложка
|
||||
self.coverLabel = QLabel()
|
||||
self.coverLabel.setFixedSize(card_width, int(card_width * 1.2))
|
||||
self.coverLabel.setStyleSheet(self.theme.COVER_LABEL_STYLE)
|
||||
coverLayout.addWidget(self.coverLabel)
|
||||
|
||||
# создаём слабую ссылку на label
|
||||
label_ref = weakref.ref(self.coverLabel)
|
||||
load_pixmap_async(cover_path or "", self.base_card_width, int(self.base_card_width * 1.2), self.on_cover_loaded)
|
||||
|
||||
def on_cover_loaded(pixmap):
|
||||
label = label_ref()
|
||||
if label is None:
|
||||
return
|
||||
label.setPixmap(round_corners(pixmap, 15))
|
||||
|
||||
# асинхронная загрузка обложки (пустая строка даст placeholder внутри load_pixmap_async)
|
||||
load_pixmap_async(cover_path or "", card_width, int(card_width * 1.2), on_cover_loaded)
|
||||
|
||||
# Значок избранного (звёздочка) в левом верхнем углу обложки
|
||||
self.favoriteLabel = ClickableLabel(coverWidget)
|
||||
self.favoriteLabel.setFixedSize(*self.theme.favoriteLabelSize)
|
||||
self.favoriteLabel.move(8, 8)
|
||||
self.favoriteLabel = ClickableLabel(self.coverWidget)
|
||||
self.favoriteLabel.clicked.connect(self.toggle_favorite)
|
||||
self.is_favorite = self.name in read_favorites()
|
||||
self.update_favorite_icon()
|
||||
self.favoriteLabel.raise_()
|
||||
|
||||
# Определяем общие параметры для бейджей
|
||||
badge_width = int(card_width * 2/3)
|
||||
icon_size = int(card_width * 0.06) # 6% от ширины карточки
|
||||
icon_space = int(card_width * 0.012) # 1.2% от ширины карточки
|
||||
font_scale_factor = 0.06 # Шрифт будет 6% от card_width
|
||||
|
||||
# ProtonDB бейдж
|
||||
tier_text = self.getProtonDBText(protondb_tier)
|
||||
if tier_text:
|
||||
icon_filename = self.getProtonDBIconFilename(protondb_tier)
|
||||
@@ -143,67 +114,50 @@ class GameCard(QFrame):
|
||||
self.protondbLabel = ClickableLabel(
|
||||
tier_text,
|
||||
icon=icon,
|
||||
parent=coverWidget,
|
||||
icon_size=icon_size,
|
||||
icon_space=icon_space,
|
||||
font_scale_factor=font_scale_factor
|
||||
parent=self.coverWidget,
|
||||
font_scale_factor=0.06
|
||||
)
|
||||
self.protondbLabel.setStyleSheet(self.theme.get_protondb_badge_style(protondb_tier))
|
||||
self.protondbLabel.setFixedWidth(badge_width)
|
||||
self.protondbLabel.setCardWidth(card_width)
|
||||
else:
|
||||
self.protondbLabel = ClickableLabel("", parent=coverWidget, icon_size=icon_size, icon_space=icon_space)
|
||||
self.protondbLabel.setFixedWidth(badge_width)
|
||||
self.protondbLabel = ClickableLabel("", parent=self.coverWidget)
|
||||
self.protondbLabel.setVisible(False)
|
||||
|
||||
# Steam бейдж
|
||||
steam_icon = self.theme_manager.get_icon("steam")
|
||||
self.steamLabel = ClickableLabel(
|
||||
"Steam",
|
||||
icon=steam_icon,
|
||||
parent=coverWidget,
|
||||
icon_size=icon_size,
|
||||
icon_space=icon_space,
|
||||
font_scale_factor=font_scale_factor
|
||||
parent=self.coverWidget,
|
||||
font_scale_factor=0.06
|
||||
)
|
||||
self.steamLabel.setStyleSheet(self.theme.STEAM_BADGE_STYLE)
|
||||
self.steamLabel.setFixedWidth(badge_width)
|
||||
self.steamLabel.setCardWidth(card_width)
|
||||
self.steamLabel.setVisible(self.steam_visible)
|
||||
|
||||
# Epic Games Store бейдж
|
||||
egs_icon = self.theme_manager.get_icon("epic_games")
|
||||
self.egsLabel = ClickableLabel(
|
||||
"Epic Games",
|
||||
icon=egs_icon,
|
||||
parent=coverWidget,
|
||||
icon_size=icon_size,
|
||||
icon_space=icon_space,
|
||||
font_scale_factor=font_scale_factor,
|
||||
parent=self.coverWidget,
|
||||
font_scale_factor=0.06,
|
||||
change_cursor=False
|
||||
)
|
||||
self.egsLabel.setStyleSheet(self.theme.STEAM_BADGE_STYLE)
|
||||
self.egsLabel.setFixedWidth(badge_width)
|
||||
self.egsLabel.setCardWidth(card_width)
|
||||
self.egsLabel.setVisible(self.egs_visible)
|
||||
|
||||
# PortProton бейдж
|
||||
portproton_icon = self.theme_manager.get_icon("portproton")
|
||||
self.portprotonLabel = ClickableLabel(
|
||||
"PortProton",
|
||||
icon=portproton_icon,
|
||||
parent=coverWidget,
|
||||
icon_size=icon_size,
|
||||
icon_space=icon_space,
|
||||
font_scale_factor=font_scale_factor
|
||||
parent=self.coverWidget,
|
||||
font_scale_factor=0.06
|
||||
)
|
||||
self.portprotonLabel.setStyleSheet(self.theme.STEAM_BADGE_STYLE)
|
||||
self.portprotonLabel.setFixedWidth(badge_width)
|
||||
self.portprotonLabel.setCardWidth(card_width)
|
||||
self.portprotonLabel.setVisible(self.portproton_visible)
|
||||
self.portprotonLabel.clicked.connect(self.open_portproton_forum_topic)
|
||||
|
||||
# WeAntiCheatYet бейдж
|
||||
anticheat_text = self.getAntiCheatText(anticheat_status)
|
||||
if anticheat_text:
|
||||
icon_filename = self.getAntiCheatIconFilename(anticheat_status)
|
||||
@@ -211,40 +165,57 @@ class GameCard(QFrame):
|
||||
self.anticheatLabel = ClickableLabel(
|
||||
anticheat_text,
|
||||
icon=icon,
|
||||
parent=coverWidget,
|
||||
icon_size=icon_size,
|
||||
icon_space=icon_space,
|
||||
font_scale_factor=font_scale_factor
|
||||
parent=self.coverWidget,
|
||||
font_scale_factor=0.06
|
||||
)
|
||||
self.anticheatLabel.setStyleSheet(self.theme.get_anticheat_badge_style(anticheat_status))
|
||||
self.anticheatLabel.setFixedWidth(badge_width)
|
||||
self.anticheatLabel.setCardWidth(card_width)
|
||||
else:
|
||||
self.anticheatLabel = ClickableLabel("", parent=coverWidget, icon_size=icon_size, icon_space=icon_space)
|
||||
self.anticheatLabel.setFixedWidth(badge_width)
|
||||
self.anticheatLabel = ClickableLabel("", parent=self.coverWidget)
|
||||
self.anticheatLabel.setVisible(False)
|
||||
|
||||
# Расположение бейджей
|
||||
self._position_badges(card_width)
|
||||
self.protondbLabel.clicked.connect(self.open_protondb_report)
|
||||
self.steamLabel.clicked.connect(self.open_steam_page)
|
||||
self.anticheatLabel.clicked.connect(self.open_weanticheatyet_page)
|
||||
|
||||
layout.addWidget(coverWidget)
|
||||
self.layout_.addWidget(self.coverWidget)
|
||||
|
||||
# Название игры
|
||||
nameLabel = QLabel(name)
|
||||
nameLabel.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
nameLabel.setStyleSheet(self.theme.GAME_CARD_NAME_LABEL_STYLE)
|
||||
layout.addWidget(nameLabel)
|
||||
self.nameLabel = QLabel(name)
|
||||
self.nameLabel.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
self.nameLabel.setStyleSheet(self.theme.GAME_CARD_NAME_LABEL_STYLE)
|
||||
self.layout_.addWidget(self.nameLabel)
|
||||
|
||||
def _position_badges(self, card_width):
|
||||
"""Позиционирует бейджи на основе ширины карточки."""
|
||||
right_margin = 8
|
||||
badge_spacing = int(card_width * 0.02) # 2% от ширины карточки
|
||||
top_y = 10
|
||||
font_size = self.nameLabel.font().pointSizeF()
|
||||
self.base_font_size = font_size if font_size > 0 else 10.0
|
||||
|
||||
self.update_scale()
|
||||
|
||||
# Force initial layout update to ensure correct geometry
|
||||
self.updateGeometry()
|
||||
parent = self.parentWidget()
|
||||
if parent:
|
||||
layout = parent.layout()
|
||||
if layout:
|
||||
layout.invalidate()
|
||||
parent.updateGeometry()
|
||||
|
||||
def on_cover_loaded(self, pixmap):
|
||||
self.base_pixmap = pixmap
|
||||
self.update_cover_pixmap()
|
||||
|
||||
def update_cover_pixmap(self):
|
||||
if self.base_pixmap:
|
||||
scaled_width = int(self.base_card_width * self._scale)
|
||||
scaled_pixmap = self.base_pixmap.scaled(scaled_width, int(scaled_width * 1.2), Qt.AspectRatioMode.KeepAspectRatioByExpanding, Qt.TransformationMode.SmoothTransformation)
|
||||
rounded_pixmap = round_corners(scaled_pixmap, int(15 * self._scale))
|
||||
self.coverLabel.setPixmap(rounded_pixmap)
|
||||
|
||||
def _position_badges(self, current_width):
|
||||
right_margin = int(8 * self._scale)
|
||||
badge_spacing = int(current_width * 0.02)
|
||||
top_y = int(10 * self._scale)
|
||||
badge_y_positions = []
|
||||
badge_width = int(card_width * 2/3)
|
||||
badge_width = int(current_width * 2/3)
|
||||
|
||||
badges = [
|
||||
(self.steam_visible, self.steamLabel),
|
||||
@@ -256,80 +227,99 @@ class GameCard(QFrame):
|
||||
|
||||
for is_visible, badge in badges:
|
||||
if is_visible:
|
||||
badge_x = card_width - badge_width - right_margin
|
||||
badge_x = current_width - badge_width - right_margin
|
||||
badge_y = badge_y_positions[-1] + badge_spacing if badge_y_positions else top_y
|
||||
badge.move(badge_x, badge_y)
|
||||
badge.move(int(badge_x), int(badge_y))
|
||||
badge_y_positions.append(badge_y + badge.height())
|
||||
|
||||
# Поднимаем бейджи в правильном порядке (от нижнего к верхнему)
|
||||
self.anticheatLabel.raise_()
|
||||
self.protondbLabel.raise_()
|
||||
self.portprotonLabel.raise_()
|
||||
self.egsLabel.raise_()
|
||||
self.steamLabel.raise_()
|
||||
|
||||
def update_card_size(self, new_width: int):
|
||||
"""Обновляет размер карточки, обложки и бейджей."""
|
||||
self.card_width = new_width
|
||||
extra_margin = 20
|
||||
self.setFixedSize(new_width + extra_margin, int(new_width * 1.6) + extra_margin)
|
||||
def update_scale(self):
|
||||
scaled_width = int(self.base_card_width * self._scale)
|
||||
scaled_height = int(self.base_card_width * 1.6 * self._scale)
|
||||
scaled_extra = int(self.base_extra_margin * self._scale)
|
||||
self.setFixedSize(scaled_width + scaled_extra, scaled_height + scaled_extra)
|
||||
self.layout_.setContentsMargins(scaled_extra // 2, scaled_extra // 2, scaled_extra // 2, scaled_extra // 2)
|
||||
|
||||
if self.coverLabel is None:
|
||||
return
|
||||
self.coverWidget.setFixedSize(scaled_width, int(scaled_width * 1.2))
|
||||
self.coverLabel.setFixedSize(scaled_width, int(scaled_width * 1.2))
|
||||
|
||||
coverWidget = self.coverLabel.parentWidget()
|
||||
if coverWidget is None:
|
||||
return
|
||||
self.update_cover_pixmap()
|
||||
|
||||
coverWidget.setFixedSize(new_width, int(new_width * 1.2))
|
||||
self.coverLabel.setFixedSize(new_width, int(new_width * 1.2))
|
||||
favorite_size = (int(self.theme.favoriteLabelSize[0] * self._scale), int(self.theme.favoriteLabelSize[1] * self._scale))
|
||||
self.favoriteLabel.setFixedSize(*favorite_size)
|
||||
self.favoriteLabel.move(int(8 * self._scale), int(8 * self._scale))
|
||||
|
||||
label_ref = weakref.ref(self.coverLabel)
|
||||
def on_cover_loaded(pixmap):
|
||||
label = label_ref()
|
||||
if label:
|
||||
scaled_pixmap = pixmap.scaled(new_width, int(new_width * 1.2), Qt.AspectRatioMode.KeepAspectRatioByExpanding, Qt.TransformationMode.SmoothTransformation)
|
||||
rounded_pixmap = round_corners(scaled_pixmap, 15)
|
||||
label.setPixmap(rounded_pixmap)
|
||||
|
||||
load_pixmap_async(self.cover_path or "", new_width, int(new_width * 1.2), on_cover_loaded)
|
||||
|
||||
# Обновляем размеры и шрифты бейджей
|
||||
badge_width = int(new_width * 2/3)
|
||||
icon_size = int(new_width * 0.06)
|
||||
icon_space = int(new_width * 0.012)
|
||||
badge_width = int(scaled_width * 2/3)
|
||||
icon_size = int(scaled_width * 0.06)
|
||||
icon_space = int(scaled_width * 0.012)
|
||||
for label in [self.steamLabel, self.egsLabel, self.portprotonLabel, self.protondbLabel, self.anticheatLabel]:
|
||||
if label is not None:
|
||||
label.setFixedWidth(badge_width)
|
||||
label.setIconSize(icon_size, icon_space)
|
||||
label.setCardWidth(new_width) # Пересчитываем размер шрифта
|
||||
label.setCardWidth(scaled_width)
|
||||
|
||||
# Перепозиционируем бейджи
|
||||
self._position_badges(new_width)
|
||||
self._position_badges(scaled_width)
|
||||
|
||||
if self.base_font_size is not None:
|
||||
font = self.nameLabel.font()
|
||||
new_font_size = self.base_font_size * self._scale
|
||||
if new_font_size > 0:
|
||||
font.setPointSizeF(new_font_size)
|
||||
self.nameLabel.setFont(font)
|
||||
|
||||
self.shadow.setBlurRadius(int(20 * self._scale))
|
||||
|
||||
self.updateGeometry()
|
||||
self.update()
|
||||
|
||||
# Ensure parent layout is updated safely
|
||||
parent = self.parentWidget()
|
||||
if parent:
|
||||
layout = parent.layout()
|
||||
if layout:
|
||||
layout.invalidate()
|
||||
layout.activate()
|
||||
layout.update()
|
||||
parent.updateGeometry()
|
||||
|
||||
def update_card_size(self, new_width: int):
|
||||
self.base_card_width = new_width
|
||||
load_pixmap_async(self.cover_path or "", new_width, int(new_width * 1.2), self.on_cover_loaded)
|
||||
self.update_scale()
|
||||
|
||||
def update_badge_visibility(self, display_filter: str):
|
||||
"""Обновляет видимость бейджей на основе display_filter."""
|
||||
self.display_filter = display_filter
|
||||
self.steam_visible = (str(self.game_source).lower() == "steam" and display_filter in ("all", "favorites"))
|
||||
self.egs_visible = (str(self.game_source).lower() == "epic" and display_filter in ("all", "favorites"))
|
||||
self.portproton_visible = (str(self.game_source).lower() == "portproton" and display_filter in ("all", "favorites"))
|
||||
self.steam_visible = (str(self.game_source).lower() == "steam" and self.display_filter in ("all", "favorites"))
|
||||
self.egs_visible = (str(self.game_source).lower() == "epic" and self.display_filter in ("all", "favorites"))
|
||||
self.portproton_visible = (str(self.game_source).lower() == "portproton" and self.display_filter in ("all", "favorites"))
|
||||
protondb_visible = bool(self.getProtonDBText(self.protondb_tier))
|
||||
anticheat_visible = bool(self.getAntiCheatText(self.anticheat_status))
|
||||
|
||||
# Обновляем видимость бейджей
|
||||
self.steamLabel.setVisible(self.steam_visible)
|
||||
self.egsLabel.setVisible(self.egs_visible)
|
||||
self.portprotonLabel.setVisible(self.portproton_visible)
|
||||
self.protondbLabel.setVisible(protondb_visible)
|
||||
self.anticheatLabel.setVisible(anticheat_visible)
|
||||
|
||||
# Перепозиционируем бейджи
|
||||
self._position_badges(self.card_width)
|
||||
scaled_width = int(self.base_card_width * self._scale)
|
||||
self._position_badges(scaled_width)
|
||||
|
||||
# Update layout after visibility changes
|
||||
self.updateGeometry()
|
||||
parent = self.parentWidget()
|
||||
if parent:
|
||||
layout = parent.layout()
|
||||
if layout:
|
||||
layout.invalidate()
|
||||
layout.update()
|
||||
parent.updateGeometry()
|
||||
|
||||
def _show_context_menu(self, pos):
|
||||
"""Delegate context menu display to ContextMenuManager."""
|
||||
if self.context_menu_manager:
|
||||
self.context_menu_manager.show_context_menu(self, pos)
|
||||
|
||||
@@ -387,7 +377,6 @@ class GameCard(QFrame):
|
||||
return ""
|
||||
|
||||
def open_portproton_forum_topic(self):
|
||||
"""Open the PortProton forum topic or search page for this game."""
|
||||
result = self.portproton_api.get_forum_topic_slug(self.name)
|
||||
base_url = "https://linux-gaming.ru/"
|
||||
if result.startswith("search?q="):
|
||||
@@ -447,8 +436,18 @@ class GameCard(QFrame):
|
||||
self.gradientAngleChanged.emit()
|
||||
self.update()
|
||||
|
||||
def getScale(self) -> float:
|
||||
return self._scale
|
||||
|
||||
def setScale(self, value: float):
|
||||
if self._scale != value:
|
||||
self._scale = value
|
||||
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))
|
||||
|
||||
def paintEvent(self, event):
|
||||
super().paintEvent(event)
|
||||
@@ -487,6 +486,7 @@ class GameCard(QFrame):
|
||||
)
|
||||
super().mousePressEvent(event)
|
||||
|
||||
|
||||
def keyPressEvent(self, event):
|
||||
if event.key() in (Qt.Key.Key_Return, Qt.Key.Key_Enter):
|
||||
self.select_callback(
|
||||
|
Reference in New Issue
Block a user