feat: rework createControlHintsWidget

Signed-off-by: Boris Yumankulov <boria138@altlinux.org>
This commit is contained in:
2025-09-12 15:07:25 +05:00
parent bff6b7fd34
commit dd4f658b66
4 changed files with 83 additions and 85 deletions

View File

@@ -19,7 +19,7 @@ from portprotonqt.system_overlay import SystemOverlay
from portprotonqt.image_utils import load_pixmap_async, round_corners, ImageCarousel
from portprotonqt.steam_api import get_steam_game_info_async, get_full_steam_game_info_async, get_steam_installed_games
from portprotonqt.egs_api import load_egs_games_async, get_egs_executable
from portprotonqt.theme_manager import ThemeManager, load_theme_screenshots, load_logo
from portprotonqt.theme_manager import ThemeManager, load_theme_screenshots
from portprotonqt.time_utils import save_last_launch, get_last_launch, parse_playtime_file, format_playtime, get_last_launch_timestamp, format_last_launch
from portprotonqt.config_utils import (
get_portproton_location, read_theme_from_config, save_theme_to_config, parse_desktop_entry,
@@ -141,32 +141,26 @@ class MainWindow(QMainWindow):
self.header.setStyleSheet(self.theme.MAIN_WINDOW_HEADER_STYLE)
headerLayout = QVBoxLayout(self.header)
headerLayout.setContentsMargins(0, 0, 0, 0)
# Текст "PortProton" слева
self.titleLabel = QLabel()
pixmap = load_logo()
if pixmap is None:
width, height = self.theme.pixmapsScaledSize
pixmap = QPixmap(width, height)
pixmap.fill(QColor(0, 0, 0, 0))
width, height = self.theme.pixmapsScaledSize
scaled_pixmap = pixmap.scaled(width, height,
Qt.AspectRatioMode.KeepAspectRatio,
Qt.TransformationMode.SmoothTransformation)
self.titleLabel.setPixmap(scaled_pixmap)
self.titleLabel.setFixedSize(scaled_pixmap.size())
self.titleLabel.setStyleSheet(self.theme.TITLE_LABEL_STYLE)
headerLayout.addStretch()
self.input_manager = InputManager(self)
self.input_manager.button_pressed.connect(self.updateControlHints)
self.input_manager.dpad_moved.connect(self.updateControlHints)
# 2. НАВИГАЦИЯ (КНОПКИ ВКЛАДОК)
self.navWidget = QWidget()
self.navWidget.setStyleSheet(self.theme.NAV_WIDGET_STYLE)
navLayout = QHBoxLayout(self.navWidget)
navLayout.setContentsMargins(10, 0, 10, 0)
navLayout.setSpacing(0)
navLayout.setSpacing(10)
navLayout.addWidget(self.titleLabel)
# Left navigation button (key_left or button_lb)
self.leftNavButton = QLabel()
self.leftNavButton.setFixedSize(32, 32)
self.leftNavButton.setAlignment(Qt.AlignmentFlag.AlignCenter)
navLayout.addWidget(self.leftNavButton)
# Вкладки
self.tabButtons = {}
tabs = [
_("Library"),
@@ -185,6 +179,16 @@ class MainWindow(QMainWindow):
self.tabButtons[i] = btn
self.tabButtons[0].setChecked(True)
# Right navigation button (key_right or button_rb)
self.rightNavButton = QLabel()
self.rightNavButton.setFixedSize(32, 32)
self.rightNavButton.setAlignment(Qt.AlignmentFlag.AlignCenter)
navLayout.addWidget(self.rightNavButton)
# Initial update of navigation buttons based on input device
self.updateNavButtons()
mainLayout.addWidget(self.navWidget)
# 3. QStackedWidget (ВКЛАДКИ)
@@ -199,15 +203,12 @@ class MainWindow(QMainWindow):
self.createPortProtonTab() # вкладка 4
self.createThemeTab() # вкладка 5
# Подсказки управления
self.controlHintsWidget = self.createControlHintsWidget()
mainLayout.addWidget(self.controlHintsWidget)
self.restore_state()
self.input_manager = InputManager(self)
# Connect InputManager gamepad connection/disconnection signals
self.input_manager.button_pressed.connect(self.updateControlHints)
self.input_manager.dpad_moved.connect(self.updateControlHints)
self.detail_animations = DetailPageAnimations(self, self.theme)
QTimer.singleShot(0, self.loadGames)
@@ -228,30 +229,23 @@ class MainWindow(QMainWindow):
hintsWidget.setStyleSheet(self.theme.STATUS_BAR_STYLE)
hintsLayout = QHBoxLayout(hintsWidget)
hintsLayout.setContentsMargins(10, 0, 10, 0)
hintsLayout.setSpacing(20)
gamepad_hints = [
("button_a", _("Select")),
("button_b", _("Back")),
("button_x", _("Add Game")),
("button_y", _("Previous Directory")),
("button_lb", _("Previous Tab")),
("button_rb", _("Next Tab")),
("button_start", _("Context Menu")),
("button_select", _("Toggle Fullscreen")),
("button_guide", _("System Overlay")),
("button_rt", _("Increase Size")),
("button_lt", _("Decrease Size")),
("button_start", _("Menu")),
("button_select", _("Fullscreen")),
]
keyboard_hints = [
("key_enter", _("Select")),
("key_esc", _("Back")),
("key_e", _("Add Game")),
("key_left", _("Previous Tab")),
("key_right", _("Next Tab")),
("key_context", _("Context Menu")),
("key_insert", _("System Overlay")),
("key_f11", _("Toggle Fullscreen")),
("key_context", _("Menu")),
("key_f11", _("Fullscreen")),
]
self.hintsLabels = []
@@ -260,11 +254,11 @@ class MainWindow(QMainWindow):
container = QWidget()
layout = QHBoxLayout(container)
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(10)
layout.setSpacing(6)
# иконка
# иконка кнопки
icon_label = QLabel()
icon_label.setFixedSize(48, 48)
icon_label.setFixedSize(32, 32)
icon_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
pixmap = QPixmap()
@@ -276,12 +270,15 @@ class MainWindow(QMainWindow):
pixmap.load(str(icon_path))
if not pixmap.isNull():
icon_label.setPixmap(pixmap.scaled(48, 48, Qt.AspectRatioMode.KeepAspectRatio,
Qt.TransformationMode.SmoothTransformation))
icon_label.setPixmap(pixmap.scaled(
32, 32,
Qt.AspectRatioMode.KeepAspectRatio,
Qt.TransformationMode.SmoothTransformation
))
layout.addWidget(icon_label)
# текст
# текст действия
text_label = QLabel(action)
text_label.setStyleSheet(self.theme.LAST_LAUNCH_VALUE_STYLE)
text_label.setAlignment(Qt.AlignmentFlag.AlignVCenter | Qt.AlignmentFlag.AlignLeft)
@@ -297,20 +294,57 @@ class MainWindow(QMainWindow):
for icon, action in keyboard_hints:
makeHint(icon, action, visible=True)
hintsLayout.addStretch() # чтобы всё разъехалось на всю ширину
hintsLayout.addStretch() # растянуть вправо
return hintsWidget
def updateNavButtons(self, *args) -> None:
"""Updates control hints and navigation buttons based on gamepad connection status."""
is_gamepad_connected = self.input_manager.gamepad is not None
logger.debug("Updating control hints, gamepad connected: %s", is_gamepad_connected)
# Left navigation button
left_pix = QPixmap()
left_icon_name = "button_lb" if is_gamepad_connected else "key_left"
left_icon = self.theme_manager.get_theme_image(left_icon_name, self.current_theme_name)
if left_icon:
left_pix.load(str(left_icon))
if not left_pix.isNull():
self.leftNavButton.setPixmap(left_pix.scaled(
32, 32,
Qt.AspectRatioMode.KeepAspectRatio,
Qt.TransformationMode.SmoothTransformation
))
self.leftNavButton.setVisible(is_gamepad_connected or not is_gamepad_connected)
# Right navigation button
right_pix = QPixmap()
right_icon_name = "button_rb" if is_gamepad_connected else "key_right"
right_icon = self.theme_manager.get_theme_image(right_icon_name, self.current_theme_name)
if right_icon:
right_pix.load(str(right_icon))
if not right_pix.isNull():
self.rightNavButton.setPixmap(right_pix.scaled(
32, 32,
Qt.AspectRatioMode.KeepAspectRatio,
Qt.TransformationMode.SmoothTransformation
))
self.rightNavButton.setVisible(is_gamepad_connected or not is_gamepad_connected)
def updateControlHints(self, *args) -> None:
"""Updates control hints based on gamepad connection status."""
"""Updates control hints and navigation buttons based on gamepad connection status."""
is_gamepad_connected = self.input_manager.gamepad is not None
logger.debug("Updating control hints, gamepad connected: %s", is_gamepad_connected)
for container, icon_name in self.hintsLabels:
if icon_name.startswith("button_"): # это геймпад
if icon_name.startswith("button_"): # геймпад
container.setVisible(is_gamepad_connected)
else: # это клавиатура
else: # клавиатура
container.setVisible(not is_gamepad_connected)
# Update navigation buttons
self.updateNavButtons()
@Slot(list)
def on_games_loaded(self, games: list[tuple]):
self.games = games
@@ -760,6 +794,8 @@ class MainWindow(QMainWindow):
sliderLayout = QHBoxLayout()
sliderLayout.addStretch()
# Слайдер
self.sizeSlider = QSlider(Qt.Orientation.Horizontal)
self.sizeSlider.setMinimum(200)
self.sizeSlider.setMaximum(250)
@@ -770,6 +806,7 @@ class MainWindow(QMainWindow):
self.sizeSlider.setStyleSheet(self.theme.SLIDER_SIZE_STYLE)
self.sizeSlider.sliderReleased.connect(self.on_slider_released)
sliderLayout.addWidget(self.sizeSlider)
layout.addLayout(sliderLayout)
def calculate_card_width():
@@ -1421,7 +1458,6 @@ class MainWindow(QMainWindow):
self.settingsDebounceTimer.start()
# Управление полноэкранным режимом
gamepad_connected = self.input_manager.find_gamepad() is not None
if fullscreen or (auto_fullscreen_gamepad and gamepad_connected):

View File

@@ -2,8 +2,7 @@ import importlib.util
import os
import ast
from portprotonqt.logger import get_logger
from PySide6.QtSvg import QSvgRenderer
from PySide6.QtGui import QIcon, QColor, QFontDatabase, QPixmap, QPainter
from PySide6.QtGui import QIcon, QFontDatabase, QPixmap
from portprotonqt.config_utils import save_theme_to_config, load_theme_metainfo
logger = get_logger(__name__)
@@ -138,28 +137,6 @@ def load_theme_fonts(theme_name):
_loaded_theme = theme_name
def load_logo():
"""
Загружает логотип темы из стандартной папки.
"""
logo_path = None
base_dir = os.path.dirname(os.path.abspath(__file__))
logo_path = os.path.join(base_dir, "themes", "standart", "images", "theme_logo.svg")
file_extension = os.path.splitext(logo_path)[1].lower()
if file_extension == ".svg":
renderer = QSvgRenderer(logo_path)
if not renderer.isValid():
logger.error(f"Error loading SVG logo: {logo_path}")
return None
pixmap = QPixmap(128, 128)
pixmap.fill(QColor(0, 0, 0, 0))
painter = QPainter(pixmap)
renderer.render(painter)
painter.end()
return pixmap
class ThemeWrapper:
"""
Обёртка для кастомной темы с поддержкой метаинформации.
@@ -225,10 +202,6 @@ class ThemeManager:
"""Возвращает список доступных тем."""
return list_themes()
def get_theme_logo(self):
"""Возвращает логотип текущей темы."""
return load_logo()
def apply_theme(self, theme_name: str):
"""
Применяет указанную тему, если она ещё не применена.

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 7.8 KiB

View File

@@ -280,16 +280,6 @@ MAIN_WINDOW_HEADER_STYLE = f"""
}}
"""
# СТИЛЬ ЗАГОЛОВКА (ЛОГО) В ШАПКЕ
TITLE_LABEL_STYLE = """
QLabel {
font-family: 'RASKHAL';
font-size: 38px;
margin: 0 0 0 0;
color: #007AFF;
}
"""
# СТИЛЬ ОБЛАСТИ НАВИГАЦИИ (КНОПКИ ВКЛАДОК)
NAV_WIDGET_STYLE = f"""
QWidget {{