2 Commits

Author SHA1 Message Date
3573b8e373 chore: temporary drop standart-light theme
All checks were successful
Code check / Check code (push) Successful in 1m59s
Signed-off-by: Boris Yumankulov <boria138@altlinux.org>
2025-08-07 14:23:35 +05:00
582ddd2218 feat: added animation to goBackDetailPage
Signed-off-by: Boris Yumankulov <boria138@altlinux.org>
2025-08-07 14:22:22 +05:00
27 changed files with 142 additions and 794 deletions

View File

@@ -1,8 +1,11 @@
from PySide6.QtCore import QPropertyAnimation, QByteArray, QEasingCurve, QAbstractAnimation, QParallelAnimationGroup, QRect, Qt from PySide6.QtCore import QPropertyAnimation, QByteArray, QEasingCurve, QAbstractAnimation, QParallelAnimationGroup, QRect, Qt, QPoint
from PySide6.QtGui import QPainter, QPen, QColor, QConicalGradient, QBrush from PySide6.QtGui import QPainter, QPen, QColor, QConicalGradient, QBrush
from PySide6.QtWidgets import QWidget, QGraphicsOpacityEffect from PySide6.QtWidgets import QWidget, QGraphicsOpacityEffect
from collections.abc import Callable from collections.abc import Callable
import portprotonqt.themes.standart.styles as default_styles import portprotonqt.themes.standart.styles as default_styles
from portprotonqt.logger import get_logger
logger = get_logger(__name__)
class GameCardAnimations: class GameCardAnimations:
def __init__(self, game_card, theme=None): def __init__(self, game_card, theme=None):
@@ -38,7 +41,6 @@ class GameCardAnimations:
self.game_card.hoverChanged.emit(self.game_card.name, True) self.game_card.hoverChanged.emit(self.game_card.name, True)
self.game_card.setFocus(Qt.FocusReason.MouseFocusReason) self.game_card.setFocus(Qt.FocusReason.MouseFocusReason)
# Ensure thickness_anim is initialized
if not self.thickness_anim: if not self.thickness_anim:
self.setup_animations() self.setup_animations()
@@ -90,7 +92,6 @@ class GameCardAnimations:
self.game_card._focused = True self.game_card._focused = True
self.game_card.focusChanged.emit(self.game_card.name, True) self.game_card.focusChanged.emit(self.game_card.name, True)
# Ensure thickness_anim is initialized
if not self.thickness_anim: if not self.thickness_anim:
self.setup_animations() self.setup_animations()
@@ -178,56 +179,28 @@ class DetailPageAnimations:
self.animations[detail_page] = animation self.animations[detail_page] = animation
animation.finished.connect(lambda: detail_page.setGraphicsEffect(shadow) if shadow is not None else detail_page.setGraphicsEffect(None)) # type: ignore animation.finished.connect(lambda: detail_page.setGraphicsEffect(shadow) if shadow is not None else detail_page.setGraphicsEffect(None)) # type: ignore
animation.finished.connect(load_image_and_restore_effect) animation.finished.connect(load_image_and_restore_effect)
elif animation_type == "slide_left": elif animation_type in ["slide_left", "slide_right", "slide_up", "slide_down"]:
duration = self.theme.GAME_CARD_ANIMATION.get("detail_page_slide_duration", 500) duration = self.theme.GAME_CARD_ANIMATION.get("detail_page_slide_duration", 500)
detail_page.move(self.main_window.width(), 0) easing_curve = QEasingCurve(QEasingCurve.Type[self.theme.GAME_CARD_ANIMATION.get("detail_page_easing_curve", "OutCubic")])
start_pos = {
"slide_left": QPoint(self.main_window.width(), 0),
"slide_right": QPoint(-self.main_window.width(), 0),
"slide_up": QPoint(0, self.main_window.height()),
"slide_down": QPoint(0, -self.main_window.height())
}[animation_type]
detail_page.move(start_pos)
animation = QPropertyAnimation(detail_page, QByteArray(b"pos")) animation = QPropertyAnimation(detail_page, QByteArray(b"pos"))
animation.setDuration(duration) animation.setDuration(duration)
animation.setStartValue(detail_page.pos()) animation.setStartValue(start_pos)
animation.setEndValue(self.main_window.stackedWidget.rect().topLeft()) animation.setEndValue(self.main_window.stackedWidget.rect().topLeft())
animation.setEasingCurve(QEasingCurve.Type.OutCubic) animation.setEasingCurve(easing_curve)
animation.start(QAbstractAnimation.DeletionPolicy.DeleteWhenStopped)
self.animations[detail_page] = animation
animation.finished.connect(cleanup_animation)
animation.finished.connect(load_image_and_restore_effect)
elif animation_type == "slide_right":
duration = self.theme.GAME_CARD_ANIMATION.get("detail_page_slide_duration", 500)
detail_page.move(-self.main_window.width(), 0)
animation = QPropertyAnimation(detail_page, QByteArray(b"pos"))
animation.setDuration(duration)
animation.setStartValue(detail_page.pos())
animation.setEndValue(self.main_window.stackedWidget.rect().topLeft())
animation.setEasingCurve(QEasingCurve.Type.OutCubic)
animation.start(QAbstractAnimation.DeletionPolicy.DeleteWhenStopped)
self.animations[detail_page] = animation
animation.finished.connect(cleanup_animation)
animation.finished.connect(load_image_and_restore_effect)
elif animation_type == "slide_up":
duration = self.theme.GAME_CARD_ANIMATION.get("detail_page_slide_duration", 500)
detail_page.move(0, self.main_window.height())
animation = QPropertyAnimation(detail_page, QByteArray(b"pos"))
animation.setDuration(duration)
animation.setStartValue(detail_page.pos())
animation.setEndValue(self.main_window.stackedWidget.rect().topLeft())
animation.setEasingCurve(QEasingCurve.Type.OutCubic)
animation.start(QAbstractAnimation.DeletionPolicy.DeleteWhenStopped)
self.animations[detail_page] = animation
animation.finished.connect(cleanup_animation)
animation.finished.connect(load_image_and_restore_effect)
elif animation_type == "slide_down":
duration = self.theme.GAME_CARD_ANIMATION.get("detail_page_slide_duration", 500)
detail_page.move(0, -self.main_window.height())
animation = QPropertyAnimation(detail_page, QByteArray(b"pos"))
animation.setDuration(duration)
animation.setStartValue(detail_page.pos())
animation.setEndValue(self.main_window.stackedWidget.rect().topLeft())
animation.setEasingCurve(QEasingCurve.Type.OutCubic)
animation.start(QAbstractAnimation.DeletionPolicy.DeleteWhenStopped) animation.start(QAbstractAnimation.DeletionPolicy.DeleteWhenStopped)
self.animations[detail_page] = animation self.animations[detail_page] = animation
animation.finished.connect(cleanup_animation) animation.finished.connect(cleanup_animation)
animation.finished.connect(load_image_and_restore_effect) animation.finished.connect(load_image_and_restore_effect)
elif animation_type == "bounce": elif animation_type == "bounce":
duration = self.theme.GAME_CARD_ANIMATION.get("detail_page_zoom_duration", 400) duration = self.theme.GAME_CARD_ANIMATION.get("detail_page_bounce_duration", 400)
easing_curve = QEasingCurve(QEasingCurve.Type[self.theme.GAME_CARD_ANIMATION.get("detail_page_easing_curve", "OutCubic")])
detail_page.setWindowOpacity(0.0) detail_page.setWindowOpacity(0.0)
opacity_anim = QPropertyAnimation(detail_page, QByteArray(b"windowOpacity")) opacity_anim = QPropertyAnimation(detail_page, QByteArray(b"windowOpacity"))
opacity_anim.setDuration(duration) opacity_anim.setDuration(duration)
@@ -240,7 +213,7 @@ class DetailPageAnimations:
geometry_anim.setDuration(duration) geometry_anim.setDuration(duration)
geometry_anim.setStartValue(initial_rect) geometry_anim.setStartValue(initial_rect)
geometry_anim.setEndValue(final_rect) geometry_anim.setEndValue(final_rect)
geometry_anim.setEasingCurve(QEasingCurve.Type.OutBack) geometry_anim.setEasingCurve(easing_curve)
group_anim = QParallelAnimationGroup() group_anim = QParallelAnimationGroup()
group_anim.addAnimation(opacity_anim) group_anim.addAnimation(opacity_anim)
group_anim.addAnimation(geometry_anim) group_anim.addAnimation(geometry_anim)
@@ -248,3 +221,75 @@ class DetailPageAnimations:
group_anim.finished.connect(cleanup_animation) group_anim.finished.connect(cleanup_animation)
group_anim.start(QAbstractAnimation.DeletionPolicy.DeleteWhenStopped) group_anim.start(QAbstractAnimation.DeletionPolicy.DeleteWhenStopped)
self.animations[detail_page] = group_anim self.animations[detail_page] = group_anim
def animate_detail_page_exit(self, detail_page: QWidget, cleanup_callback: Callable):
"""Animate the detail page exit based on theme settings."""
try:
animation_type = self.theme.GAME_CARD_ANIMATION.get("detail_page_animation_type", "fade")
# Safely stop and remove any existing animation
if detail_page in self.animations:
try:
animation = self.animations[detail_page]
if isinstance(animation, QAbstractAnimation) and animation.state() == QAbstractAnimation.State.Running:
animation.stop()
except RuntimeError:
logger.debug("Animation already deleted for page")
except Exception as e:
logger.error(f"Error stopping existing animation: {e}", exc_info=True)
finally:
self.animations.pop(detail_page, None)
# Define animation based on type
if animation_type == "fade":
duration = self.theme.GAME_CARD_ANIMATION.get("detail_page_fade_duration_exit", 350)
opacity_effect = QGraphicsOpacityEffect(detail_page)
detail_page.setGraphicsEffect(opacity_effect)
animation = QPropertyAnimation(opacity_effect, QByteArray(b"opacity"))
animation.setDuration(duration)
animation.setStartValue(1)
animation.setEndValue(0)
animation.start(QAbstractAnimation.DeletionPolicy.DeleteWhenStopped)
self.animations[detail_page] = animation
animation.finished.connect(cleanup_callback)
elif animation_type in ["slide_left", "slide_right", "slide_up", "slide_down"]:
duration = self.theme.GAME_CARD_ANIMATION.get("detail_page_slide_duration_exit", 500)
easing_curve = QEasingCurve(QEasingCurve.Type[self.theme.GAME_CARD_ANIMATION.get("detail_page_easing_curve_exit", "InCubic")])
end_pos = {
"slide_left": QPoint(-self.main_window.width(), 0), # Exit to left (opposite of entry)
"slide_right": QPoint(self.main_window.width(), 0), # Exit to right
"slide_up": QPoint(0, self.main_window.height()), # Exit downward
"slide_down": QPoint(0, -self.main_window.height()) # Exit upward
}[animation_type]
animation = QPropertyAnimation(detail_page, QByteArray(b"pos"))
animation.setDuration(duration)
animation.setStartValue(detail_page.pos())
animation.setEndValue(end_pos)
animation.setEasingCurve(easing_curve)
animation.start(QAbstractAnimation.DeletionPolicy.DeleteWhenStopped)
self.animations[detail_page] = animation
animation.finished.connect(cleanup_callback)
elif animation_type == "bounce":
duration = self.theme.GAME_CARD_ANIMATION.get("detail_page_bounce_duration_exit", 400)
easing_curve = QEasingCurve(QEasingCurve.Type[self.theme.GAME_CARD_ANIMATION.get("detail_page_easing_curve_exit", "InCubic")])
opacity_anim = QPropertyAnimation(detail_page, QByteArray(b"windowOpacity"))
opacity_anim.setDuration(duration)
opacity_anim.setStartValue(1.0)
opacity_anim.setEndValue(0.0)
final_rect = QRect(detail_page.x() + detail_page.width() // 4, detail_page.y() + detail_page.height() // 4,
detail_page.width() // 2, detail_page.height() // 2)
geometry_anim = QPropertyAnimation(detail_page, QByteArray(b"geometry"))
geometry_anim.setDuration(duration)
geometry_anim.setStartValue(detail_page.geometry())
geometry_anim.setEndValue(final_rect)
geometry_anim.setEasingCurve(easing_curve)
group_anim = QParallelAnimationGroup()
group_anim.addAnimation(opacity_anim)
group_anim.addAnimation(geometry_anim)
group_anim.finished.connect(cleanup_callback)
group_anim.start(QAbstractAnimation.DeletionPolicy.DeleteWhenStopped)
self.animations[detail_page] = group_anim
except Exception as e:
logger.error(f"Error in animate_detail_page_exit: {e}", exc_info=True)
self.animations.pop(detail_page, None)
cleanup_callback() # Fallback to cleanup if animation setup fails

View File

@@ -1967,17 +1967,23 @@ class MainWindow(QMainWindow):
parent = parent.parent() parent = parent.parent()
def goBackDetailPage(self, page: QWidget | None) -> None: def goBackDetailPage(self, page: QWidget | None) -> None:
if page is None or page != self.stackedWidget.currentWidget(): if page is None or page != self.stackedWidget.currentWidget() or getattr(self, '_exit_animation_in_progress', False):
return return
self._exit_animation_in_progress = True
self._detail_page_active = False self._detail_page_active = False
self._current_detail_page = None self._current_detail_page = None
if hasattr(self, '_animations') and page in self._animations:
def cleanup():
"""Helper function to clean up after animation."""
try: try:
if page in self._animations:
animation = self._animations[page] animation = self._animations[page]
try:
if animation.state() == QAbstractAnimation.State.Running: if animation.state() == QAbstractAnimation.State.Running:
animation.stop() animation.stop()
del self._animations[page]
except RuntimeError: except RuntimeError:
pass # Animation already deleted
finally:
del self._animations[page] del self._animations[page]
self.stackedWidget.setCurrentIndex(0) self.stackedWidget.setCurrentIndex(0)
self.stackedWidget.removeWidget(page) self.stackedWidget.removeWidget(page)
@@ -1985,6 +1991,18 @@ class MainWindow(QMainWindow):
self.currentDetailPage = None self.currentDetailPage = None
self.current_exec_line = None self.current_exec_line = None
self.current_play_button = None self.current_play_button = None
self._exit_animation_in_progress = False
except Exception as e:
logger.error(f"Error in cleanup: {e}", exc_info=True)
self._exit_animation_in_progress = False
# Start exit animation
try:
self.detail_animations.animate_detail_page_exit(page, cleanup)
except Exception as e:
logger.error(f"Error starting exit animation: {e}", exc_info=True)
self._exit_animation_in_progress = False
cleanup() # Fallback to cleanup if animation fails
def is_target_exe_running(self): def is_target_exe_running(self):
"""Проверяет, запущен ли процесс с именем self.target_exe через psutil.""" """Проверяет, запущен ли процесс с именем self.target_exe через psutil."""

View File

@@ -1 +0,0 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="m3.3334 1c-1.2926 0-2.3333 1.0408-2.3333 2.3333v9.3333c0 1.2926 1.0408 2.3333 2.3333 2.3333h9.3333c1.2926 0 2.3333-1.0408 2.3333-2.3333v-9.3333c0-1.2926-1.0408-2.3333-2.3333-2.3333zm4.6667 2.4979c0.41261 0 0.75035 0.33774 0.75035 0.75035v3.0014h3.0014c0.41261 0 0.75035 0.33774 0.75035 0.75035s-0.33774 0.75035-0.75035 0.75035h-3.0014v3.0014c0 0.41261-0.33774 0.75035-0.75035 0.75035s-0.75035-0.33774-0.75035-0.75035v-3.0014h-3.0014c-0.41261 0-0.75035-0.33774-0.75035-0.75035s0.33774-0.75035 0.75035-0.75035h3.0014v-3.0014c0-0.41261 0.33774-0.75035 0.75035-0.75035z" fill="#fff" fill-rule="evenodd"/></svg>

Before

Width:  |  Height:  |  Size: 734 B

View File

@@ -1 +0,0 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="m12.13 2.2617-5.7389 5.7389 5.7389 5.7389-1.2604 1.2605-7-7 7-7z" fill="#fff"/></svg>

Before

Width:  |  Height:  |  Size: 213 B

View File

@@ -1 +0,0 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="m5.48 11.5 2.52-2.52 2.52 2.52 0.98-0.98-2.52-2.52 2.52-2.52-0.98-0.98-2.52 2.52-2.52-2.52-0.98 0.98 2.52 2.52-2.52 2.52zm2.52 3.5q-1.4525 0-2.73-0.55125t-2.2225-1.4962-1.4962-2.2225-0.55125-2.73 0.55125-2.73 1.4962-2.2225 2.2225-1.4962 2.73-0.55125 2.73 0.55125 2.2225 1.4962 1.4962 2.2225 0.55125 2.73-0.55125 2.73-1.4962 2.2225-2.2225 1.4962-2.73 0.55125zm0-1.4q2.345 0 3.9725-1.6275t1.6275-3.9725-1.6275-3.9725-3.9725-1.6275-3.9725 1.6275-1.6275 3.9725 1.6275 3.9725 3.9725 1.6275z"/></svg>

Before

Width:  |  Height:  |  Size: 622 B

View File

@@ -1 +0,0 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="m8 11.5-7-7h14z" fill="#fff"/></svg>

Before

Width:  |  Height:  |  Size: 164 B

View File

@@ -1 +0,0 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="m7.02 11.22 4.935-4.935-0.98-0.98-3.955 3.955-1.995-1.995-0.98 0.98zm0.98 3.78q-1.4525 0-2.73-0.55125t-2.2225-1.4962-1.4962-2.2225-0.55125-2.73 0.55125-2.73 1.4962-2.2225 2.2225-1.4962 2.73-0.55125 2.73 0.55125 2.2225 1.4962 1.4962 2.2225 0.55125 2.73-0.55125 2.73-1.4962 2.2225-2.2225 1.4962-2.73 0.55125zm0-1.4q2.345 0 3.9725-1.6275t1.6275-3.9725-1.6275-3.9725-3.9725-1.6275-3.9725 1.6275-1.6275 3.9725 1.6275 3.9725 3.9725 1.6275z"/></svg>

Before

Width:  |  Height:  |  Size: 570 B

View File

@@ -1 +0,0 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="m0.52495 13.312c0.03087 1.3036 1.3683 2.0929 2.541 1.4723l9.4303-5.3381c0.51362-0.29103 0.86214-0.82453 0.86214-1.4496 0-0.62514-0.34835-1.1586-0.86214-1.4497l-9.4303-5.3304c-1.1727-0.62059-2.5111 0.16139-2.541 1.4647z" fill="#fff"/></svg>

Before

Width:  |  Height:  |  Size: 367 B

View File

@@ -1 +0,0 @@
<svg width="64" height="64" version="1.1" viewBox="0 0 64 64" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="m31.994 2c-3.5777 0.00874-6.7581 2.209-8.0469 5.5059-6.026 1.9949-11.103 6.1748-14.25 11.576 0.3198-0.03567 0.64498-0.05624 0.9668-0.05664 1.8247 4.03e-4 3.6022 0.57036 5.0801 1.6406 2.053-2.9466 4.892-5.3048 8.2148-6.7754 1.3182 3.2847 4.496 5.4368 8.0352 5.4375 4.7859 5.76e-4 8.6634-3.8782 8.6641-8.6641 0-4.787-3.8774-8.6647-8.6641-8.6641zm14.148 8.4629c0.001493 0.068825 1.08e-4 0.13229 0 0.20117 0 2.0592-0.7314 4.0514-2.0664 5.6191 2.6029 1.9979 4.687 4.6357 6.0332 7.6758-0.03487 0.01246-0.051814 0.019533-0.089844 0.033204-3.239 1.3412-5.3501 4.5078-5.3496 8.0137-5.6e-5 3.5056 2.111 6.6588 5.3496 8 1.0511 0.43551 2.1787 0.66386 3.3164 0.66406 0.37838-3.45e-4 0.74796-0.028635 1.123-0.078125 4.3115-0.56733 7.5408-4.2367 7.541-8.5859-2.29e-4 -0.38522-0.026915-0.77645-0.078125-1.1582-0.41836-3.1252-2.5021-5.7755-5.4395-6.9219-1.8429-5.5649-5.5319-10.293-10.34-13.463zm-35.479 12.867v0.011719c-4.7868-5.8e-4 -8.6645 3.8772-8.6641 8.6641 5.184e-4 3.5694 2.1832 6.7701 5.5078 8.0684 1.9494 5.8885 5.9701 10.844 11.191 14.004-0.02187-0.24765-0.032753-0.49357-0.033203-0.74219 0.0011-1.8915 0.6215-3.7301 1.7656-5.2363-2.8389-2.0415-5.1101-4.8211-6.541-8.0586-0.010718 0.00405-0.023854 0.005164-0.035156 0.007812 3.2771-1.2961 5.4686-4.4709 5.4746-8.043 7e-6 -4.787-3.8793-8.6762-8.666-8.6758zm18.264 2.9746c-1.1128 0.59718-2.0251 1.5031-2.627 2.6133 0.49567 0.91964 0.77734 1.9689 0.77734 3.082 0 1.1135-0.28142 2.168-0.77734 3.0879 0.60218 1.1114 1.5189 2.0216 2.6328 2.6191 0.9175-0.49216 1.9588-0.77148 3.0684-0.77148 1.1032 0 2.1508 0.27284 3.0645 0.75976 1.1182-0.60366 2.032-1.5238 2.6309-2.6445-0.48449-0.91196-0.76367-1.9505-0.76367-3.0508 0-1.1 0.27944-2.1331 0.76367-3.0449-0.59834-1.1194-1.5143-2.0409-2.6309-2.6445-0.91432 0.48781-1.9603 0.76367-3.0645 0.76367-1.1106 3e-6 -2.1561-0.27646-3.0742-0.76953zm19.328 17.041c-2.0547 2.9472-4.8918 5.3038-8.2148 6.7754-1.3171-3.2891-4.504-5.4498-8.0469-5.4492-4.7846 0.0017-8.6634 3.8796-8.6641 8.6641 0 4.7856 3.8788 8.6627 8.6641 8.6641 3.5711 7.48e-4 6.782-2.179 8.0801-5.5059 6.026-1.9954 11.081-6.1633 14.227-11.564-0.3202 0.03625-0.64263 0.05628-0.96484 0.05664-1.822-2.87e-4 -3.6033-0.57345-5.0801-1.6406z"/></svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -1 +0,0 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="m8 11.5-4.375-4.375 1.225-1.2688 2.275 2.275v-7.1312h1.75v7.1312l2.275-2.275 1.225 1.2688zm-5.25 3.5q-0.72188 0-1.2359-0.51406-0.51406-0.51406-0.51406-1.2359v-2.625h1.75v2.625h10.5v-2.625h1.75v2.625q0 0.72188-0.51406 1.2359-0.51406 0.51406-1.2359 0.51406z"/></svg>

Before

Width:  |  Height:  |  Size: 392 B

View File

@@ -1 +0,0 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="m14.396 13.564-2.5415-2.5415c0.94769-1.0626 1.5364-2.4698 1.5364-4.0062 0-3.3169-2.6995-6.0164-6.0164-6.0164-3.3169 0-6.0164 2.6995-6.0164 6.0164s2.6995 6.0164 6.0164 6.0164c1.1774 0 2.2688-0.34469 3.1877-0.91896l2.6421 2.6421c0.15799 0.15799 0.37342 0.24416 0.58871 0.24416 0.21544 0 0.43079-0.08617 0.58874-0.24416 0.34469-0.33033 0.34469-0.86155 0.01512-1.1918zm-11.358-6.5477c0-2.3836 1.9384-4.3364 4.3364-4.3364 2.3979 0 4.3221 1.9528 4.3221 4.3364s-1.9384 4.3364-4.3221 4.3364-4.3364-1.9384-4.3364-4.3364z" fill="#fff"/></svg>

Before

Width:  |  Height:  |  Size: 660 B

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 7.9 KiB

View File

@@ -1 +0,0 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="m14.125 8.875h-1.75c-0.48386 0-0.87498-0.39113-0.87498-0.87498 0-0.48389 0.39113-0.87502 0.87498-0.87502h1.75c0.48386 0 0.87498 0.39113 0.87498 0.87502 0 0.48386-0.39113 0.87498-0.87498 0.87498zm-2.4133-3.3494c-0.34211 0.34211-0.89513 0.34211-1.2372 0-0.34211-0.34214-0.34211-0.89513 0-1.2373l1.2372-1.2372c0.34211-0.34211 0.89513-0.34211 1.2372 0 0.34211 0.34214 0.34211 0.89513 0 1.2372zm-3.7117 9.4744c-0.48389 0-0.87501-0.39113-0.87501-0.87498v-1.75c0-0.48386 0.39113-0.87498 0.87501-0.87498 0.48386 0 0.87498 0.39113 0.87498 0.87498v1.75c0 0.48386-0.39113 0.87498-0.87498 0.87498zm0-10.5c-0.48389 0-0.87501-0.39113-0.87501-0.87498v-1.75c0-0.48386 0.39113-0.87498 0.87501-0.87498 0.48386 0 0.87498 0.39113 0.87498 0.87498v1.75c0 0.48386-0.39113 0.87498-0.87498 0.87498zm-3.7117 8.449c-0.34211 0.34211-0.8951 0.34211-1.2372 0-0.34211-0.34211-0.34211-0.89513 0-1.2372l1.2372-1.2372c0.34214-0.34211 0.89513-0.34211 1.2373 0 0.34211 0.34211 0.34211 0.89513 0 1.2372zm0-7.4234-1.2372-1.2373c-0.34211-0.34211-0.34211-0.8951 0-1.2372 0.34214-0.34211 0.89513-0.34211 1.2372 0l1.2373 1.2372c0.34211 0.34214 0.34211 0.89513 0 1.2373-0.34214 0.34211-0.89513 0.34211-1.2373 0zm0.21165 2.4744c0 0.48386-0.39113 0.87498-0.87498 0.87498h-1.75c-0.48386 0-0.87498-0.39113-0.87498-0.87498 0-0.48389 0.39113-0.87501 0.87498-0.87501h1.75c0.48386 0 0.87498 0.39113 0.87498 0.87501zm7.2117 2.4744 1.2372 1.2372c0.34211 0.34211 0.34211 0.89598 0 1.2372-0.34211 0.34126-0.89513 0.34211-1.2372 0l-1.2372-1.2372c-0.34211-0.34211-0.34211-0.89513 0-1.2372s0.89513-0.34211 1.2372 0z" fill="#fff"/></svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -1 +0,0 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="m7.9881 1.001c-3.6755 0-6.6898 2.835-6.9751 6.4383l3.752 1.5505c0.31806-0.21655 0.70174-0.34431 1.1152-0.34431 0.03671 0 0.07309 0.0017 0.1098 0.0033l1.6691-2.4162v-0.03456c0-1.4556 1.183-2.639 2.639-2.639 1.4547 0 2.639 1.1847 2.639 2.6407 0 1.456-1.1843 2.6395-2.639 2.6395h-0.06118l-2.3778 1.6979c0 0.03009 0.0017 0.06118 0.0017 0.09276 0 1.0938-0.88376 1.981-1.9776 1.981-0.95374 0-1.7592-0.68426-1.9429-1.5907l-2.6863-1.1126c0.83168 2.9383 3.5292 5.0924 6.7335 5.0924 3.8657 0 6.9995-3.1343 6.9995-7s-3.1343-7-6.9995-7zm-2.5895 10.623-0.85924-0.35569c0.15262 0.31676 0.4165 0.58274 0.7665 0.72931 0.75645 0.31456 1.6293-0.04415 1.9438-0.80194 0.15361-0.3675 0.15394-0.76956 0.0033-1.1371-0.15097-0.3675-0.4375-0.65408-0.80324-0.80674-0.364-0.1518-0.7525-0.14535-1.0955-0.01753l0.88855 0.3675c0.55782 0.23318 0.82208 0.875 0.58845 1.4319-0.23145 0.55826-0.87326 0.8225-1.4315 0.59019zm6.6587-5.4267c0-0.96948-0.78926-1.7587-1.7587-1.7587-0.97126 0-1.7587 0.78926-1.7587 1.7587 0 0.97126 0.7875 1.7587 1.7587 1.7587 0.96994 0 1.7587-0.7875 1.7587-1.7587zm-3.0756-0.0033c0-0.73019 0.59106-1.3217 1.3212-1.3217 0.72844 0 1.3217 0.59148 1.3217 1.3217 0 0.72976-0.59326 1.3213-1.3217 1.3213-0.73106 0-1.3212-0.5915-1.3212-1.3213z" fill="#fff"/></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1 +0,0 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="14" height="14" rx="2.8" fill="#fff" fill-rule="evenodd"/></svg>

Before

Width:  |  Height:  |  Size: 208 B

View File

@@ -1 +0,0 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="m1 11.5 7-7 7 7z" fill="#fff"/></svg>

Before

Width:  |  Height:  |  Size: 165 B

View File

@@ -1 +0,0 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="m8 15q-1.4583 0-2.7319-0.55417-1.2735-0.55417-2.2167-1.4972-0.94313-0.94306-1.4972-2.2167t-0.55417-2.7319q-7.699e-5 -1.4583 0.55417-2.7319 0.55424-1.2736 1.4972-2.2167 0.94298-0.94306 2.2167-1.4972 1.2737-0.55417 2.7319-0.55417 1.5944 0 3.0237 0.68056 1.4292 0.68056 2.4208 1.925v-1.8278h1.5556v4.6667h-4.6667v-1.5556h2.1389q-0.79722-1.0889-1.9639-1.7111-1.1667-0.62222-2.5083-0.62222-2.275 0-3.8596 1.5848t-1.5848 3.8596q-1.55e-4 2.2748 1.5848 3.8596 1.585 1.5848 3.8596 1.5848 2.0417 0 3.5681-1.3222t1.7985-3.3444h1.5944q-0.29167 2.6639-2.2848 4.443-1.9931 1.7791-4.6763 1.7792z"/></svg>

Before

Width:  |  Height:  |  Size: 717 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 475 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 151 KiB

View File

@@ -1,5 +0,0 @@
[Metainfo]
author = BlackSnaker
author_link =
description = Стандартная тема PortProtonQt (светлый вариант)
name = Light

View File

@@ -1,712 +0,0 @@
from portprotonqt.theme_manager import ThemeManager
from portprotonqt.config_utils import read_theme_from_config
theme_manager = ThemeManager()
current_theme_name = read_theme_from_config()
# КОНСТАНТЫ
favoriteLabelSize = 48, 48
pixmapsScaledSize = 60, 60
GAME_CARD_ANIMATION = {
# Тип анимации fade при входе на детальную страницу
# Возможные значения: "fade", "slide_left", "slide_right", "slide_up", "slide_down", "bounce", "none"
"detail_page_animation_type": "fade",
# Ширина обводки карточки в состоянии покоя (без наведения или фокуса).
# Влияет на толщину рамки вокруг карточки, когда она не выделена.
# Значение в пикселях.
"default_border_width": 2,
# Ширина обводки при наведении курсора.
# Увеличивает толщину рамки, когда курсор находится над карточкой.
# Значение в пикселях.
"hover_border_width": 8,
# Ширина обводки при фокусе (например, при выборе с клавиатуры).
# Увеличивает толщину рамки, когда карточка в фокусе.
# Значение в пикселях.
"focus_border_width": 12,
# Минимальная ширина обводки во время пульсирующей анимации.
# Определяет минимальную толщину рамки при пульсации (анимация "дыхания").
# Значение в пикселях.
"pulse_min_border_width": 8,
# Максимальная ширина обводки во время пульсирующей анимации.
# Определяет максимальную толщину рамки при пульсации.
# Значение в пикселях.
"pulse_max_border_width": 10,
# Длительность анимации изменения толщины обводки (например, при наведении или фокусе).
# Влияет на скорость перехода от одной ширины обводки к другой.
# Значение в миллисекундах.
"thickness_anim_duration": 300,
# Длительность одного цикла пульсирующей анимации.
# Определяет, как быстро рамка "пульсирует" между min и max значениями.
# Значение в миллисекундах.
"pulse_anim_duration": 800,
# Длительность анимации вращения градиента.
# Влияет на скорость, с которой градиентная обводка вращается вокруг карточки.
# Значение в миллисекундах.
"gradient_anim_duration": 3000,
# Начальный угол градиента (в градусах).
# Определяет начальную точку вращения градиента при старте анимации.
"gradient_start_angle": 360,
# Конечный угол градиента (в градусах).
# Определяет конечную точку вращения градиента.
# Значение 0 означает полный поворот на 360 градусов.
"gradient_end_angle": 0,
# Тип кривой сглаживания для анимации увеличения обводки (при наведении/фокусе).
# Влияет на "чувство" анимации (например, плавное ускорение или замедление).
# Возможные значения: строки, соответствующие QEasingCurve.Type (например, "OutBack", "InOutQuad").
"thickness_easing_curve": "OutBack",
# Тип кривой сглаживания для анимации уменьшения обводки (при уходе курсора/потере фокуса).
# Влияет на "чувство" возврата к исходной ширине обводки.
"thickness_easing_curve_out": "InBack",
# Цвета градиента для анимированной обводки.
# Список словарей, где каждый словарь задает позицию (0.01.0) и цвет в формате hex.
# Влияет на внешний вид обводки при наведении или фокусе.
"gradient_colors": [
{"position": 0, "color": "#00fff5"}, # Начальный цвет (циан)
{"position": 0.33, "color": "#FF5733"}, # Цвет на 33% (оранжевый)
{"position": 0.66, "color": "#9B59B6"}, # Цвет на 66% (пурпурный)
{"position": 1, "color": "#00fff5"} # Конечный цвет (возвращение к циану)
],
# Длительность анимации fade при входе на детальную страницу
"detail_page_fade_duration": 350,
# Длительность анимации slide при входе на детальную страницу
"detail_page_slide_duration": 500,
# Длительность анимации zoom при входе на детальную страницу
"detail_page_zoom_duration": 400
}
# СТИЛЬ ШАПКИ ГЛАВНОГО ОКНА
MAIN_WINDOW_HEADER_STYLE = """
QFrame {
background: transparent;
border: 10px solid rgba(255, 255, 255, 0.10);
border-bottom: 0px solid rgba(255, 255, 255, 0.15);
border-top-left-radius: 30px;
border-top-right-radius: 30px;
border: none;
}
"""
# СТИЛЬ ЗАГОЛОВКА (ЛОГО) В ШАПКЕ
TITLE_LABEL_STYLE = """
QLabel {
font-family: 'RASKHAL';
font-size: 38px;
margin: 0 0 0 0;
color: #007AFF;
}
"""
# СТИЛЬ ОБЛАСТИ НАВИГАЦИИ (КНОПКИ ВКЛАДОК)
NAV_WIDGET_STYLE = """
QWidget {
background: #ffffff;
border-bottom: 0px solid rgba(0, 0, 0, 0.10);
}
"""
# СТИЛЬ КНОПОК ВКЛАДОК НАВИГАЦИИ
NAV_BUTTON_STYLE = """
NavLabel {
background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
stop:0 rgba(242, 242, 242, 0.5),
stop:1 rgba(232, 232, 232, 0.5));
padding: 10px 10px;
margin: 10px 0 10px 10px;
color: #333333;
font-size: 16px;
font-family: 'Poppins';
text-transform: uppercase;
border: 1px solid rgba(179, 179, 179, 0.4);
border-radius: 15px;
}
NavLabel[checked = true] {
background: rgba(0,122,255,0.25);
color: #002244;
font-weight: bold;
border-radius: 15px;
}
NavLabel:hover {
background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
stop:0 rgba(0,122,255,0.12),
stop:1 rgba(0,122,255,0.08));
color: #002244;
}
"""
# ГЛОБАЛЬНЫЙ СТИЛЬ ДЛЯ ОКНА (ФОН) И QLabel
MAIN_WINDOW_STYLE = """
QMainWindow {
background: none;
}
QLabel {
color: #333333;
}
"""
# СТИЛЬ ПОЛЯ ПОИСКА
SEARCH_EDIT_STYLE = """
QLineEdit {
background-color: rgba(30, 30, 30, 0.50);
border: 1px solid rgba(255, 255, 255, 0.5);
border-radius: 10px;
padding: 7px 14px;
font-family: 'Poppins';
font-size: 16px;
color: #ffffff;
}
QLineEdit:focus {
border: 1px solid rgba(0,122,255,0.25);
}
"""
# ОТКЛЮЧАЕМ РАМКУ У QScrollArea
SCROLL_AREA_STYLE = """
QWidget {
background: transparent;
}
QScrollBar:vertical {
width: 10px;
border: 0px solid;
border-radius: 5px;
background: rgba(20, 20, 20, 0.30);
}
QScrollBar::handle:vertical {
background: rgba(255, 255, 255, 0.7);
border: 0px solid;
border-radius: 5px;
}
QScrollBar::add-line:vertical {
border: 0px solid;
background: none;
}
QScrollBar::sub-line:vertical {
border: 0px solid;
background: none;
}
QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical {
border: 0px solid;
width: 3px;
height: 3px;
background: none;
}
QScrollBar:horizontal {
height: 10px;
border: 0px solid;
border-radius: 5px;
background: rgba(20, 20, 20, 0.30);
}
QScrollBar::handle:horizontal {
background: #bebebe;
border: 0px solid;
border-radius: 5px;
}
QScrollBar::add-line:horizontal {
border: 0px solid;
background: none;
}
QScrollBar::sub-line:horizontal {
border: 0px solid;
background: none;
}
QScrollBar::up-arrow:horizontal, QScrollBar::down-arrow:horizontal {
border: 0px solid;
width: 3px;
height: 3px;
background: none;
}
"""
# SLIDER_SIZE_STYLE
SLIDER_SIZE_STYLE= """
QWidget {
background: transparent;
height: 25px;
}
QSlider::groove:horizontal {
border: 0px solid;
border-radius: 3px;
height: 6px; /* the groove expands to the size of the slider by default. by giving it a height, it has a fixed size */
background: rgba(20, 20, 20, 0.30);
margin: 6px 0;
}
QSlider::handle:horizontal {
background: #bebebe;
border: 0px solid;
width: 18px;
height: 18px;
margin: -6px 0; /* handle is placed by default on the contents rect of the groove. Expand outside the groove */
border-radius: 9px;
}
"""
# СТИЛЬ ОБЛАСТИ ДЛЯ КАРТОЧЕК ИГР (QWidget)
LIST_WIDGET_STYLE = """
QWidget {
background: none;
border: 0px solid rgba(255, 255, 255, 0.10);
border-radius: 25px;
}
"""
# ЗАГОЛОВОК "БИБЛИОТЕКА" НА ВКЛАДКЕ
INSTALLED_TAB_TITLE_STYLE = "font-family: 'Poppins'; font-size: 24px; color: #232627;"
# СТИЛЬ КНОПОК "СОХРАНЕНИЯ, ПРИМЕНЕНИЯ И Т.Д."
ACTION_BUTTON_STYLE = """
QPushButton {
background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
stop:0 rgba(242, 242, 242, 0.5),
stop:1 rgba(232, 232, 232, 0.5));
border: 1px solid rgba(179, 179, 179, 0.4);
border-radius: 10px;
color: #232627;
font-size: 16px;
font-family: 'Poppins';
padding: 8px 16px;
}
QPushButton:hover {
background: rgba(0,122,255,0.25);
}
QPushButton:pressed {
background: rgba(0,122,255,0.25);
}
"""
# ТЕКСТОВЫЕ СТИЛИ: ЗАГОЛОВКИ И ОСНОВНОЙ КОНТЕНТ
TAB_TITLE_STYLE = "font-family: 'Poppins'; font-size: 24px; color: #232627; background-color: none;"
CONTENT_STYLE = """
QLabel {
font-family: 'Poppins';
font-size: 16px;
color: #232627;
background-color: none;
border-bottom: 1px solid rgba(165, 165, 165, 0.7);
padding-bottom: 15px;
}
"""
# СТИЛЬ ОСНОВНЫХ СТРАНИЦ
# LIBRARY_WIDGET_STYLE
LIBRARY_WIDGET_STYLE= """
QWidget {
background: qlineargradient(spread:pad, x1:0.162, y1:0.0313409, x2:1, y2:1, stop:0 rgba(215, 235, 255, 255), stop:1 rgba(253, 252, 255, 255));
border-radius: 0px;
}
"""
# CONTAINER_STYLE
CONTAINER_STYLE= """
QWidget {
background-color: none;
}
"""
# OTHER_PAGES_WIDGET_STYLE
OTHER_PAGES_WIDGET_STYLE= """
QWidget {
background: qlineargradient(spread:pad, x1:0.162, y1:0.0313409, x2:1, y2:1, stop:0 rgba(215, 235, 255, 255), stop:1 rgba(253, 252, 255, 255));
border-radius: 0px;
}
"""
# CAROUSEL_WIDGET_STYLE
CAROUSEL_WIDGET_STYLE= """
QWidget {
background: qlineargradient(spread:pad, x1:0.099, y1:0.119, x2:0.917, y2:0.936149, stop:0 rgba(215, 235, 255, 255), stop:1 rgba(217, 193, 255, 255));
border-radius: 0px;
}
"""
# ФОН ДЛЯ ДЕТАЛЬНОЙ СТРАНИЦЫ, ЕСЛИ ОБЛОЖКА НЕ ЗАГРУЖЕНА
DETAIL_PAGE_NO_COVER_STYLE = "background: rgba(20,20,20,0.95); border-radius: 15px;"
# СТИЛЬ КНОПКИ "ДОБАВИТЬ ИГРУ" И "НАЗАД" НА ДЕТАЛЬНОЙ СТРАНИЦЕ И БИБЛИОТЕКИ
ADDGAME_BACK_BUTTON_STYLE = """
QPushButton {
background: rgba(20, 20, 20, 0.40);
border: 1px solid rgba(255, 255, 255, 0.5);
border-radius: 10px;
color: #ffffff;
font-size: 16px;
font-family: 'Poppins';
padding: 4px 16px;
}
QPushButton:hover {
background: rgba(0,122,255,0.25);
}
QPushButton:pressed {
background: rgba(0,122,255,0.25);
}
"""
# ОСНОВНОЙ ФРЕЙМ ДЕТАЛЕЙ ИГРЫ
DETAIL_CONTENT_FRAME_STYLE = """
QFrame {
background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
stop:0 rgba(20, 20, 20, 0.40),
stop:1 rgba(20, 20, 20, 0.35));
border: 0px solid rgba(255, 255, 255, 0.10);
border-radius: 15px;
}
"""
# ФРЕЙМ ПОД ОБЛОЖКОЙ
COVER_FRAME_STYLE = """
QFrame {
background: rgba(30, 30, 30, 0.80);
border-radius: 15px;
border: 0px solid rgba(255, 255, 255, 0.15);
}
"""
# СКРУГЛЕНИЕ LABEL ПОД ОБЛОЖКУ
COVER_LABEL_STYLE = "border-radius: 100px;"
# ВИДЖЕТ ДЕТАЛЕЙ (ТЕКСТ, ОПИСАНИЕ)
DETAILS_WIDGET_STYLE = "background: rgba(20,20,20,0.40); border-radius: 15px; padding: 10px;"
# НАЗВАНИЕ (ЗАГОЛОВОК) НА ДЕТАЛЬНОЙ СТРАНИЦЕ
DETAIL_PAGE_TITLE_STYLE = "font-family: 'Orbitron'; font-size: 32px; color: #007AFF;"
# ЛИНИЯ-РАЗДЕЛИТЕЛЬ
DETAIL_PAGE_LINE_STYLE = "color: rgba(255,255,255,0.12); margin: 10px 0;"
# ТЕКСТ ОПИСАНИЯ
DETAIL_PAGE_DESC_STYLE = "font-family: 'Poppins'; font-size: 16px; color: #ffffff; line-height: 1.5;"
# СТИЛЬ КНОПКИ "ИГРАТЬ"
PLAY_BUTTON_STYLE = """
QPushButton {
background: rgba(20, 20, 20, 0.40);
border: 1px solid rgba(255, 255, 255, 0.5);
border-radius: 10px;
font-size: 18px;
color: #ffffff;
font-weight: bold;
font-family: 'Orbitron';
padding: 8px 16px;
min-width: 120px;
min-height: 40px;
}
QPushButton:hover {
background: rgba(0,122,255,0.25);
}
QPushButton:pressed {
background: rgba(0,122,255,0.25);
}
"""
# СТИЛЬ КНОПКИ "ОБЗОР..." В ДИАЛОГЕ "ДОБАВИТЬ ИГРУ"
DIALOG_BROWSE_BUTTON_STYLE = """
QPushButton {
background: rgba(20, 20, 20, 0.40);
border: 0px solid rgba(255, 255, 255, 0.20);
border-radius: 15px;
color: #ffffff;
font-size: 16px;
padding: 5px 10px;
}
QPushButton:hover {
background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
stop:0 rgba(0,122,255,0.20),
stop:1 rgba(0,122,255,0.15));
}
QPushButton:pressed {
background: rgba(20, 20, 20, 0.60);
border: 0px solid rgba(255, 255, 255, 0.25);
}
"""
# СТИЛЬ КАРТОЧКИ ИГРЫ (GAMECARD)
GAME_CARD_WINDOW_STYLE = """
QFrame {
border-radius: 20px;
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 rgba(255, 255, 255, 0.3),
stop:1 rgba(249, 249, 249, 0.3));
border: 0px solid rgba(255, 255, 255, 0.4);
}
"""
# НАЗВАНИЕ В КАРТОЧКЕ (QLabel)
GAME_CARD_NAME_LABEL_STYLE = """
QLabel {
color: #333333;
font-family: 'Orbitron';
font-size: 16px;
font-weight: bold;
background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0,
stop:0 rgba(242, 242, 242, 0.5),
stop:1 rgba(232, 232, 232, 0.5));
border-radius: 20px;
padding: 7px;
qproperty-wordWrap: true;
}
"""
# ДОПОЛНИТЕЛЬНЫЕ СТИЛИ ИНФОРМАЦИИ НА СТРАНИЦЕ ИГР
LAST_LAUNCH_TITLE_STYLE = "font-family: 'Poppins'; font-size: 11px; color: #bbbbbb; text-transform: uppercase; letter-spacing: 0.75px; margin-bottom: 2px;"
LAST_LAUNCH_VALUE_STYLE = "font-family: 'Poppins'; font-size: 13px; color: #ffffff; font-weight: 600; letter-spacing: 0.75px;"
PLAY_TIME_TITLE_STYLE = "font-family: 'Poppins'; font-size: 11px; color: #bbbbbb; text-transform: uppercase; letter-spacing: 0.75px; margin-bottom: 2px;"
PLAY_TIME_VALUE_STYLE = "font-family: 'Poppins'; font-size: 13px; color: #ffffff; font-weight: 600; letter-spacing: 0.75px;"
GAMEPAD_SUPPORT_VALUE_STYLE = """
font-family: 'Poppins'; font-size: 12px; color: #00ff00;
font-weight: bold; background: rgba(0, 0, 0, 0.3);
border-radius: 5px; padding: 4px 8px;
"""
# СТИЛИ ПОЛНОЭКРАНОГО ПРЕВЬЮ СКРИНШОТОВ ТЕМЫ
PREV_BUTTON_STYLE="background-color: rgba(0, 0, 0, 0.5); color: white; border: none;"
NEXT_BUTTON_STYLE="background-color: rgba(0, 0, 0, 0.5); color: white; border: none;"
CAPTION_LABEL_STYLE="color: white; font-size: 16px;"
# СТИЛИ БЕЙДЖА PROTONDB НА КАРТОЧКЕ
def get_protondb_badge_style(tier):
tier = tier.lower()
tier_colors = {
"platinum": {"background": "rgba(255,255,255,0.9)", "color": "black"},
"gold": {"background": "rgba(253,185,49,0.7)", "color": "black"},
"silver": {"background": "rgba(169,169,169,0.8)", "color": "black"},
"bronze": {"background": "rgba(205,133,63,0.7)", "color": "black"},
"borked": {"background": "rgba(255,0,0,0.7)", "color": "black"},
"pending": {"background": "rgba(160,82,45,0.7)", "color": "black"}
}
colors = tier_colors.get(tier, {"background": "rgba(0, 0, 0, 0.5)", "color": "white"})
return f"""
qproperty-alignment: AlignCenter;
background-color: {colors["background"]};
color: {colors["color"]};
border-radius: 5px;
font-family: 'Poppins';
font-weight: bold;
"""
def get_anticheat_badge_style(status):
status = status.lower()
status_colors = {
"supported": {"background": "rgba(102, 168, 15, 0.7)", "color": "black"},
"running": {"background": "rgba(25, 113, 194, 0.7)", "color": "black"},
"planned": {"background": "rgba(156, 54, 181, 0.7)", "color": "black"},
"broken": {"background": "rgba(232, 89, 12, 0.7)", "color": "black"},
"denied": {"background": "rgba(224, 49, 49, 0.7)", "color": "black"}
}
colors = status_colors.get(status, {"background": "rgba(0, 0, 0, 0.5)", "color": "white"})
return f"""
qproperty-alignment: AlignCenter;
background-color: {colors["background"]};
color: {colors["color"]};
border-radius: 5px;
font-family: 'Poppins';
font-weight: bold;
"""
# СТИЛИ БЕЙДЖА STEAM
STEAM_BADGE_STYLE= """
qproperty-alignment: AlignCenter;
background: rgba(0, 0, 0, 0.5);
color: white;
border-radius: 5px;
font-family: 'Poppins';
font-weight: bold;
"""
# Favorite Star
FAVORITE_LABEL_STYLE = "color: gold; font-size: 32px; background: transparent; border: none;"
# СТИЛИ ДЛЯ QMessageBox (ОКНА СООБЩЕНИЙ)
MESSAGE_BOX_STYLE = """
QMessageBox {
background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
stop:0 rgba(40, 40, 40, 0.95),
stop:1 rgba(25, 25, 25, 0.95));
border: 1px solid rgba(255, 255, 255, 0.15);
border-radius: 12px;
}
QMessageBox QLabel {
color: #ffffff;
font-family: 'Poppins';
font-size: 16px;
}
QMessageBox QPushButton {
background: rgba(30, 30, 30, 0.6);
border: 1px solid rgba(165, 165, 165, 0.7);
border-radius: 8px;
color: #ffffff;
font-family: 'Poppins';
padding: 8px 20px;
min-width: 80px;
}
QMessageBox QPushButton:hover {
background: #09bec8;
border-color: rgba(255, 255, 255, 0.3);
}
"""
# СТИЛИ ДЛЯ ВКЛАДКИ НАСТРОЕК PORTPROTON
# PARAMS_TITLE_STYLE
PARAMS_TITLE_STYLE = "color: #232627; font-family: 'Poppins'; font-size: 16px; padding: 10px; background: transparent;"
PROXY_INPUT_STYLE = """
QLineEdit {
background: rgba(20, 20, 20, 0.40);
border: 0px solid rgba(165, 165, 165, 0.7);
border-radius: 10px;
height: 34px;
padding-left: 12px;
color: #ffffff;
font-family: 'Poppins';
font-size: 16px;
}
QLineEdit:focus {
border: 1px solid rgba(0,122,255,0.25);
}
QMenu {
border: 1px solid rgba(255, 255, 255, 0.5);
padding: 5px 10px;
background: #c7c7c7;
}
QMenu::item {
padding: 0px 10px;
border: 10px solid transparent; /* reserve space for selection border */
}
QMenu::item:selected {
background: 1px solid rgba(255, 255, 255, 0.5);
border-radius: 10px;
}
"""
SETTINGS_COMBO_STYLE = f"""
QComboBox {{
background: rgba(20, 20, 20, 0.40);
border: 1px solid rgba(255, 255, 255, 0.5);
border-radius: 10px;
height: 34px;
padding-left: 12px;
color: #ffffff;
font-family: 'Poppins';
font-size: 16px;
min-width: 120px;
combobox-popup: 0;
}}
QComboBox:on {{
background: rgba(20, 20, 20, 0.40);
border: 1px solid rgba(165, 165, 165, 0.7);
border-top-left-radius: 10px;
border-top-right-radius: 10px;
border-bottom-left-radius: 0px;
border-bottom-right-radius: 0px;
}}
QComboBox:hover {{
border: 1px solid rgba(165, 165, 165, 0.7);
}}
QComboBox::drop-down {{
subcontrol-origin: padding;
subcontrol-position: center right;
border-left: 1px solid rgba(255, 255, 255, 0.5);
padding: 12px;
height: 12px;
width: 12px;
}}
QComboBox::down-arrow {{
image: url({theme_manager.get_icon("down", current_theme_name, as_path=True)});
padding: 12px;
height: 12px;
width: 12px;
}}
QComboBox::down-arrow:on {{
image: url({theme_manager.get_icon("up", current_theme_name, as_path=True)});
padding: 12px;
height: 12px;
width: 12px;
}}
QComboBox QAbstractItemView {{
outline: none;
border: 1px solid rgba(165, 165, 165, 0.7);
border-top-style: none;
}}
QListView {{
background: #ffffff;
}}
QListView::item {{
padding: 7px 7px 7px 12px;
border-radius: 0px;
color: #232627;
}}
QListView::item:hover {{
background: rgba(0,122,255,0.25);
}}
QListView::item:selected {{
background: rgba(0,122,255,0.25);
}}
"""
class FileExplorerStyles:
WINDOW_STYLE = """
QDialog {
background-color: #2d2d2d;
color: #ffffff;
font-family: "Arial";
font-size: 14px;
}
"""
PATH_LABEL_STYLE = """
QLabel {
color: #3daee9;
font-size: 16px;
padding: 5px;
}
"""
LIST_STYLE = """
QListWidget {
font-size: 16px;
background-color: #353535;
color: #eee;
border: 1px solid #444;
border-radius: 4px;
}
QListWidget::item {
padding: 8px;
border-bottom: 1px solid #444;
}
QListWidget::item:selected {
background-color: #3daee9;
color: white;
border-radius: 2px;
}
"""
BUTTON_STYLE = """
QPushButton {
background-color: #3daee9;
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
font-size: 14px;
}
QPushButton:hover {
background-color: #2c9fd8;
}
QPushButton:pressed {
background-color: #1a8fc7;
}
"""

View File

@@ -27,7 +27,7 @@ color_g = "rgba(0, 0, 0, 0)"
color_h = "transparent" color_h = "transparent"
GAME_CARD_ANIMATION = { GAME_CARD_ANIMATION = {
# Тип анимации fade при входе на детальную страницу # Тип анимации при входе и выходе на детальную страницу
# Возможные значения: "fade", "slide_left", "slide_right", "slide_up", "slide_down", "bounce" # Возможные значения: "fade", "slide_left", "slide_right", "slide_up", "slide_down", "bounce"
"detail_page_animation_type": "fade", "detail_page_animation_type": "fade",
@@ -105,8 +105,25 @@ GAME_CARD_ANIMATION = {
# Длительность анимации slide при входе на детальную страницу # Длительность анимации slide при входе на детальную страницу
"detail_page_slide_duration": 500, "detail_page_slide_duration": 500,
# Длительность анимации zoom при входе на детальную страницу # Длительность анимации bounce при входе на детальную страницу
"detail_page_zoom_duration": 400 "detail_page_bounce_duration": 400,
# Длительность анимации fade при выходе из детальной страницы
"detail_page_fade_duration_exit": 350,
# Длительность анимации slide при выходе из детальной страницы
"detail_page_slide_duration_exit": 500,
# Длительность анимации bounce при выходе из детальной страницы
"detail_page_bounce_duration_exit": 400,
# Тип кривой сглаживания для анимации при входе на детальную страницу
# Применяется к slide и bounce анимациям
"detail_page_easing_curve": "OutCubic",
# Тип кривой сглаживания для анимации при выходе из детальной страницы
# Применяется к slide и bounce анимациям
"detail_page_easing_curve_exit": "InCubic"
} }
CONTEXT_MENU_STYLE = f""" CONTEXT_MENU_STYLE = f"""