From a930cbd7050a0f148c70c301edf256d8e6e9b0d6 Mon Sep 17 00:00:00 2001 From: Boris Yumankulov Date: Tue, 3 Jun 2025 14:26:25 +0500 Subject: [PATCH] feat(ui): add ProtonDB, Steam, and WeAntiCheatYet badges to game detail page Signed-off-by: Boris Yumankulov --- portprotonqt/game_card.py | 18 +++++--- portprotonqt/main_window.py | 89 ++++++++++++++++++++++++++++++++++++- 2 files changed, 99 insertions(+), 8 deletions(-) diff --git a/portprotonqt/game_card.py b/portprotonqt/game_card.py index 152474f..d484a00 100644 --- a/portprotonqt/game_card.py +++ b/portprotonqt/game_card.py @@ -217,7 +217,8 @@ class GameCard(QFrame): if self.context_menu_manager: self.context_menu_manager.show_context_menu(self, pos) - def getAntiCheatText(self, status): + @staticmethod + def getAntiCheatText(status: str) -> str: if not status: return "" translations = { @@ -229,7 +230,8 @@ class GameCard(QFrame): } return translations.get(status.lower(), "") - def getAntiCheatIconFilename(self, status): + @staticmethod + def getAntiCheatIconFilename(status: str) -> str: status = status.lower() if status in ("supported", "running"): return "platinum-gold" @@ -237,7 +239,8 @@ class GameCard(QFrame): return "broken" return "" - def getProtonDBText(self, tier): + @staticmethod + def getProtonDBText(tier: str) -> str: if not tier: return "" translations = { @@ -250,7 +253,8 @@ class GameCard(QFrame): } return translations.get(tier.lower(), "") - def getProtonDBIconFilename(self, tier): + @staticmethod + def getProtonDBIconFilename(tier: str) -> str: tier = tier.lower() if tier in ("platinum", "gold"): return "platinum-gold" @@ -451,7 +455,8 @@ class GameCard(QFrame): self.last_launch, self.formatted_playtime, self.protondb_tier, - self.steam_game + self.steam_game, + self.anticheat_status ) super().mousePressEvent(event) @@ -467,7 +472,8 @@ class GameCard(QFrame): self.last_launch, self.formatted_playtime, self.protondb_tier, - self.steam_game + self.steam_game, + self.anticheat_status ) else: super().keyPressEvent(event) diff --git a/portprotonqt/main_window.py b/portprotonqt/main_window.py index 943d489..c326adf 100644 --- a/portprotonqt/main_window.py +++ b/portprotonqt/main_window.py @@ -1320,7 +1320,7 @@ class MainWindow(QMainWindow): def darkenColor(self, color, factor=200): return color.darker(factor) - def openGameDetailPage(self, name, description, cover_path=None, appid="", exec_line="", controller_support="", last_launch="", formatted_playtime="", protondb_tier="", steam_game=""): + def openGameDetailPage(self, name, description, cover_path=None, appid="", exec_line="", controller_support="", last_launch="", formatted_playtime="", protondb_tier="", steam_game="", anticheat_status=""): detailPage = QWidget() self._animations = {} imageLabel = QLabel() @@ -1375,7 +1375,7 @@ class MainWindow(QMainWindow): coverLayout.addWidget(imageLabel) - # Добавляем значок избранного поверх обложки в левом верхнем углу + # Значок избранного favoriteLabelCover = ClickableLabel(coverFrame) favoriteLabelCover.setFixedSize(*self.theme.favoriteLabelSize) favoriteLabelCover.setStyleSheet(self.theme.FAVORITE_LABEL_STYLE) @@ -1388,6 +1388,91 @@ class MainWindow(QMainWindow): favoriteLabelCover.move(8, 8) favoriteLabelCover.raise_() + # Добавляем бейджи (ProtonDB, Steam, WeAntiCheatYet) + right_margin = 8 + badge_spacing = 5 + top_y = 10 + badge_y_positions = [] + badge_width = int(300 * 2/3) # 2/3 ширины обложки (300 px) + + # ProtonDB бейдж + protondb_text = GameCard.getProtonDBText(protondb_tier) + if protondb_text: + icon_filename = GameCard.getProtonDBIconFilename(protondb_tier) + icon = self.theme_manager.get_icon(icon_filename, self.current_theme_name) + protondbLabel = ClickableLabel( + protondb_text, + icon=icon, + parent=coverFrame, + icon_size=16, + icon_space=3, + ) + protondbLabel.setStyleSheet(self.theme.get_protondb_badge_style(protondb_tier)) + protondbLabel.setFixedWidth(badge_width) + protondbLabel.clicked.connect(lambda: QDesktopServices.openUrl(QUrl(f"https://www.protondb.com/app/{appid}"))) + protondb_visible = True + else: + protondbLabel = ClickableLabel("", parent=coverFrame, icon_size=16, icon_space=3) + protondbLabel.setFixedWidth(badge_width) + protondbLabel.setVisible(False) + protondb_visible = False + + # Steam бейдж + steam_icon = self.theme_manager.get_icon("steam") + steamLabel = ClickableLabel( + "Steam", + icon=steam_icon, + parent=coverFrame, + icon_size=16, + icon_space=5, + ) + steamLabel.setStyleSheet(self.theme.STEAM_BADGE_STYLE) + steamLabel.setFixedWidth(badge_width) + steam_visible = (str(steam_game).lower() == "true") + steamLabel.setVisible(steam_visible) + steamLabel.clicked.connect(lambda: QDesktopServices.openUrl(QUrl(f"https://steamcommunity.com/app/{appid}"))) + + # WeAntiCheatYet бейдж + anticheat_text = GameCard.getAntiCheatText(anticheat_status) + if anticheat_text: + icon_filename = GameCard.getAntiCheatIconFilename(anticheat_status) + icon = self.theme_manager.get_icon(icon_filename, self.current_theme_name) + anticheatLabel = ClickableLabel( + anticheat_text, + icon=icon, + parent=coverFrame, + icon_size=16, + icon_space=3, + ) + anticheatLabel.setStyleSheet(self.theme.STEAM_BADGE_STYLE) + anticheatLabel.setFixedWidth(badge_width) + anticheatLabel.clicked.connect(lambda: QDesktopServices.openUrl(QUrl(f"https://areweanticheatyet.com/game/{name.lower().replace(' ', '-')}"))) + anticheat_visible = True + else: + anticheatLabel = ClickableLabel("", parent=coverFrame, icon_size=16, icon_space=3) + anticheatLabel.setFixedWidth(badge_width) + anticheatLabel.setVisible(False) + anticheat_visible = False + + # Расположение бейджей + if steam_visible: + steam_x = 300 - badge_width - right_margin + steamLabel.move(steam_x, top_y) + badge_y_positions.append(top_y + steamLabel.height()) + if protondb_visible: + protondb_x = 300 - badge_width - right_margin + protondb_y = badge_y_positions[-1] + badge_spacing if badge_y_positions else top_y + protondbLabel.move(protondb_x, protondb_y) + badge_y_positions.append(protondb_y + protondbLabel.height()) + if anticheat_visible: + anticheat_x = 300 - badge_width - right_margin + anticheat_y = badge_y_positions[-1] + badge_spacing if badge_y_positions else top_y + anticheatLabel.move(anticheat_x, anticheat_y) + + anticheatLabel.raise_() + protondbLabel.raise_() + steamLabel.raise_() + contentFrameLayout.addWidget(coverFrame) # Детали игры (справа)