From 80d3b69311e7baf98363dc70818a24841056512f Mon Sep 17 00:00:00 2001 From: Boris Yumankulov Date: Thu, 25 Dec 2025 12:30:27 +0500 Subject: [PATCH] chore(themes): reorgonize it to submodules Signed-off-by: Boris Yumankulov --- documentation/theme_guide/README.md | 50 +- documentation/theme_guide/README.ru.md | 50 +- portprotonqt/themes/standart/styles.py | 1271 +---------------- .../themes/standart/styles/__init__.py | 0 portprotonqt/themes/standart/styles/base.py | 378 +++++ .../themes/standart/styles/constants.py | 176 +++ .../themes/standart/styles/detail_page.py | 115 ++ .../themes/standart/styles/game_card.py | 87 ++ .../themes/standart/styles/settings.py | 111 ++ .../themes/standart/styles/theme_utils.py | 84 ++ .../themes/standart/styles/winetricks.py | 317 ++++ 11 files changed, 1358 insertions(+), 1281 deletions(-) create mode 100644 portprotonqt/themes/standart/styles/__init__.py create mode 100644 portprotonqt/themes/standart/styles/base.py create mode 100644 portprotonqt/themes/standart/styles/constants.py create mode 100644 portprotonqt/themes/standart/styles/detail_page.py create mode 100644 portprotonqt/themes/standart/styles/game_card.py create mode 100644 portprotonqt/themes/standart/styles/settings.py create mode 100644 portprotonqt/themes/standart/styles/theme_utils.py create mode 100644 portprotonqt/themes/standart/styles/winetricks.py diff --git a/documentation/theme_guide/README.md b/documentation/theme_guide/README.md index c59c735..4c5777f 100644 --- a/documentation/theme_guide/README.md +++ b/documentation/theme_guide/README.md @@ -31,17 +31,49 @@ mkdir -p ~/.local/share/PortProtonQT/themes/my_custom_theme ## 🎨 Style File (`styles.py`) -Create a `styles.py` in the theme root. It should define variables or functions that return CSS. +Create a `styles.py` in the theme root. It should define variables or functions that return QSS (Qt Style Sheets). For better organization, you can split your theme into multiple submodules by creating a `styles` subdirectory with separate Python files for different components, and import them in `styles.py`. -**Example:** +**Example of modular structure:** +``` +my_custom_theme/ +├── styles.py +├── metainfo.ini +├── fonts/ +├── images/ +└── styles/ + ├── __init__.py # This empty file makes the directory a Python package + ├── constants.py + ├── base.py + ├── game_card.py + ├── detail_page.py + ├── settings.py + ├── winetricks.py + └── theme_utils.py +``` + +**Main styles.py file:** ```python -def custom_button_style(color1, color2): - return f""" - QPushButton {{ - background: qlineargradient(x1:0, y1:0, x2:1, y2:0, - stop:0 {color1}, stop:1 {color2}); - }} - """ +# Import from the theme's submodules using absolute paths relative to the package +# Replace 'my_custom_theme' with your actual theme folder name +from portprotonqt.themes.my_custom_theme.styles.constants import * +from portprotonqt.themes.my_custom_theme.styles.base import * +from portprotonqt.themes.my_custom_theme.styles.game_card import * +from portprotonqt.themes.my_custom_theme.styles.detail_page import * +from portprotonqt.themes.my_custom_theme.styles.settings import * +from portprotonqt.themes.my_custom_theme.styles.winetricks import * +from portprotonqt.themes.my_custom_theme.styles.theme_utils import * +``` + +**Example submodule (styles/constants.py):** +```python +# Theme constants +font_family = "Play" +font_size_a = "16px" +font_size_b = "24px" +border_radius_a = "10px" +color_a = "#409EFF" +color_b = "#282a33" +# ... other constants ``` --- diff --git a/documentation/theme_guide/README.ru.md b/documentation/theme_guide/README.ru.md index 3c4e47b..81920b7 100644 --- a/documentation/theme_guide/README.ru.md +++ b/documentation/theme_guide/README.ru.md @@ -31,17 +31,49 @@ mkdir -p ~/.local/share/PortProtonQT/themes/my_custom_theme ## 🎨 Файл стилей (`styles.py`) -Создайте `styles.py` в корне темы. В нём определите переменные и/или функции, возвращающие CSS-оформление. +Создайте `styles.py` в корне темы. В нём определите переменные и/или функции, возвращающие QSS-оформление (Qt Style Sheets). Для лучшей организации кода, вы можете разделить тему на несколько подмодулей, создав поддиректорию `styles` с отдельными Python-файлами для разных компонентов, и импортировать их в `styles.py`. -**Пример функции:** +**Пример модульной структуры:** +``` +my_custom_theme/ +├── styles.py +├── metainfo.ini +├── fonts/ +├── images/ +└── styles/ + ├── __init__.py # Этот пустой файл делает директорию Python-пакетом + ├── constants.py + ├── base.py + ├── game_card.py + ├── detail_page.py + ├── settings.py + ├── winetricks.py + └── theme_utils.py +``` + +**Основной файл styles.py:** ```python -def custom_button_style(color1, color2): - return f""" - QPushButton {{ - background: qlineargradient(x1:0, y1:0, x2:1, y2:0, - stop:0 {color1}, stop:1 {color2}); - }} - """ +# Импорт из подмодулей темы с использованием абсолютных путей относительно пакета +# Замените 'my_custom_theme' на фактическое имя папки вашей темы +from portprotonqt.themes.my_custom_theme.styles.constants import * +from portprotonqt.themes.my_custom_theme.styles.base import * +from portprotonqt.themes.my_custom_theme.styles.game_card import * +from portprotonqt.themes.my_custom_theme.styles.detail_page import * +from portprotonqt.themes.my_custom_theme.styles.settings import * +from portprotonqt.themes.my_custom_theme.styles.winetricks import * +from portprotonqt.themes.my_custom_theme.styles.theme_utils import * +``` + +**Пример подмодуля (styles/constants.py):** +```python +# Константы темы +font_family = "Play" +font_size_a = "16px" +font_size_b = "24px" +border_radius_a = "10px" +color_a = "#409EFF" +color_b = "#282a33" +# ... другие константы ``` --- diff --git a/portprotonqt/themes/standart/styles.py b/portprotonqt/themes/standart/styles.py index 7405bc8..cb0b64c 100644 --- a/portprotonqt/themes/standart/styles.py +++ b/portprotonqt/themes/standart/styles.py @@ -1,1263 +1,8 @@ -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 - -# VARS -font_family = "Play" -font_size_a = "16px" -font_size_b = "24px" -border_a = "0px solid" -border_b = "1px solid" -border_c = "2px solid" -border_radius_a = "10px" -border_radius_b = "15px" -color_a = "#409EFF" -color_b = "#282a33" -color_c = "#3f424d" -color_d = "#32343d" -color_e = "#404554" -color_f = "#ffffff" -color_g = "rgba(0, 0, 0, 0)" -color_h = "transparent" -color_i = "rgba(40, 42, 51, 0.9)" - -GAME_CARD_ANIMATION = { - # Тип анимации при входе и выходе на детальную страницу - # Возможные значения: "fade", "slide_left", "slide_right", "slide_up", "slide_down", "bounce" - # Определяет, как детальная страница появляется и исчезает - "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, - - # Тип анимации для карточки при наведении или фокусе - # Возможные значения: "gradient", "scale" - # "gradient" включает вращающийся градиент для обводки, "scale" увеличивает размер карточки - "card_animation_type": "gradient", - - # Масштаб карточки в состоянии покоя - # Определяет базовый размер карточки (1.0 = 100% от исходного размера) - # Значение в долях (например, 1.0 для нормального размера) - "default_scale": 1.0, - - # Масштаб карточки при наведении курсора - # Увеличивает размер карточки при наведении - # Значение в долях (например, 1.1 = 110% от исходного размера) - "hover_scale": 1.1, - - # Масштаб карточки при фокусе (например, при выборе с клавиатуры) - # Увеличивает размер карточки при фокусе - # Значение в долях (например, 1.05 = 105% от исходного размера) - "focus_scale": 1.05, - - # Длительность анимации масштабирования - # Влияет на скорость изменения размера карточки при наведении или фокусе - # Значение в миллисекундах - "scale_anim_duration": 200, - - # Тип кривой сглаживания для анимации увеличения обводки (при наведении/фокусе) - # Влияет на "чувство" анимации (например, плавное ускорение или замедление) - # Возможные значения: строки, соответствующие QEasingCurve.Type (например, "OutBack", "InOutQuad") - "thickness_easing_curve": "OutBack", - - # Тип кривой сглаживания для анимации уменьшения обводки (при уходе курсора/потере фокуса) - # Влияет на "чувство" возврата к исходной ширине обводки - "thickness_easing_curve_out": "InBack", - - # Тип кривой сглаживания для анимации увеличения масштаба (при наведении/фокусе) - # Влияет на "чувство" анимации масштабирования (например, с эффектом "отскока") - # Возможные значения: строки, соответствующие QEasingCurve.Type - "scale_easing_curve": "OutBack", - - # Тип кривой сглаживания для анимации уменьшения масштаба (при уходе курсора/потере фокуса) - # Влияет на "чувство" возврата к исходному масштабу - "scale_easing_curve_out": "InBack", - - # Цвета градиента для анимированной обводки - # Список словарей, где каждый словарь задает позицию (0.0–1.0) и цвет в формате hex - # Влияет на внешний вид обводки при наведении или фокусе, если card_animation_type="gradient" - "gradient_colors": [ - {"position": 0, "color": "#00fff5"}, # Начальный цвет (циан) - {"position": 0.33, "color": "#FF5733"}, # Цвет на 33% (оранжевый) - {"position": 0.66, "color": "#9B59B6"}, # Цвет на 66% (пурпурный) - {"position": 1, "color": "#00fff5"} # Конечный цвет (возвращение к циану) - ], - - # Длительность анимации fade при входе на детальную страницу - # Влияет на скорость появления страницы при fade-анимации - # Значение в миллисекундах - "detail_page_fade_duration": 350, - - # Длительность анимации slide при входе на детальную страницу - # Влияет на скорость скольжения страницы при slide-анимации - # Значение в миллисекундах - "detail_page_slide_duration": 500, - - # Длительность анимации bounce при входе на детальную страницу - # Влияет на скорость "прыжка" страницы при bounce-анимации - # Значение в миллисекундах - "detail_page_bounce_duration": 400, - - # Длительность анимации fade при выходе из детальной страницы - # Влияет на скорость исчезновения страницы при fade-анимации - # Значение в миллисекундах - "detail_page_fade_duration_exit": 350, - - # Длительность анимации slide при выходе из детальной страницы - # Влияет на скорость скольжения страницы при slide-анимации - # Значение в миллисекундах - "detail_page_slide_duration_exit": 500, - - # Длительность анимации bounce при выходе из детальной страницы - # Влияет на скорость "сжатия" страницы при bounce-анимации - # Значение в миллисекундах - "detail_page_bounce_duration_exit": 400, - - # Тип кривой сглаживания для анимации при входе на детальную страницу - # Применяется к slide и bounce анимациям, влияет на "чувство" движения - # Возможные значения: строки, соответствующие QEasingCurve.Type - "detail_page_easing_curve": "OutCubic", - - # Тип кривой сглаживания для анимации при выходе из детальной страницы - # Применяется к slide и bounce анимациям, влияет на "чувство" движения - # Возможные значения: строки, соответствующие QEasingCurve.Type - "detail_page_easing_curve_exit": "InCubic" -} - -CONTEXT_MENU_STYLE = f""" - QMenu {{ - background: {color_b}; - color: {color_f}; - font-family: '{font_family}'; - font-size: {font_size_a}; - padding: 5px; - min-width: 150px; - }} - QMenu::icon {{ - margin-left: 15px; - }} - QMenu::item {{ - padding: 10px 20px 10px 10px; - background: {color_h}; - border-radius: {border_radius_a}; - color: {color_f}; - }} - QMenu::item:selected {{ - background: {color_a}; - color: {color_f}; - }} - QMenu::item:disabled {{ - color: #7f7f7f; - }} - QMenu::item:hover {{ - background: {color_a}; - color: {color_f}; - }} - QMenu::item:focus {{ - background: {color_a}; - color: {color_f}; - border: {border_b} rgba(255, 255, 255, 0.3); - border-radius: {border_radius_a}; - }} - QMenu::separator {{ - height: 1px; - background-color: #7f7f7f; - margin: 3px 6px; - }} -""" - -VIRTUAL_KEYBOARD_STYLE = f""" -QWidget {{ - background: {color_i}; -}} -QPushButton {{ - font-size: 14px; - border: {border_a} {color_h}; - border-radius: {border_radius_a}; - min-width: 30px; - min-height: 30px; - padding: 5px; - background-color: {color_c}; - color: {color_f}; -}} -QPushButton:hover {{ - background-color: {color_a}; - border: {border_b} {color_a}; -}} -QPushButton:focus {{ - border: {border_b} {color_a}; - background-color: {color_a}; -}} -QPushButton:pressed {{ - background-color: {color_c}; - border: {border_a} {color_h}; -}} -QPushButton[checked="true"] {{ - background-color: {color_a}; - color: {color_f}; - border: {border_a} {color_h}; -}} -QPushButton[checked="true"]:focus {{ - border: {border_b} {color_f}; -}} -""" - -# ГЛОБАЛЬНЫЙ СТИЛЬ ДЛЯ ОКНА (ФОН), ЛЭЙБЛОВ, КНОПОК -MAIN_WINDOW_STYLE = f""" - QWidget {{ - background: {color_b}; - }} - QLabel {{ - color: {color_f}; - font-family: '{font_family}'; - font-size: {font_size_a}; - }} - QPushButton {{ - background: {color_c}; - border: {border_c} rgba(255, 255, 255, 0.01); - border-radius: {border_radius_a}; - color: {color_f}; - font-size: {font_size_a}; - font-family: '{font_family}'; - padding: 8px 16px; - }} - QPushButton:hover {{ - background: {color_a}; - border: {border_c} {color_a}; - }} - QPushButton:pressed {{ - background: {color_b}; - }} - QPushButton:focus {{ - border: {border_c} {color_a}; - background-color: {color_a}; - }} -""" - -# СТИЛЬ ПРОГРЕСС-БАРА -PROGRESS_BAR_STYLE = f""" - QProgressBar {{ - color: {color_f}; - background-color: {color_c}; - text-align: center; - }} - QProgressBar::chunk {{ - background-color: {color_a}; - }} -""" - -# СТИЛЬ СТАТУС-БАРА -STATUS_BAR_STYLE = f""" - QStatusBar {{ - color: {color_f}; - }} -""" - -# СТИЛЬ ШАПКИ ГЛАВНОГО ОКНА -MAIN_WINDOW_HEADER_STYLE = f""" - QFrame {{ - background: {color_h}; - border: 10px solid {color_g}; - border-bottom: 0px solid {color_g}; - border-top-left-radius: 30px; - border-top-right-radius: 30px; - border: none; - }} -""" - -# СТИЛЬ ОБЛАСТИ НАВИГАЦИИ (КНОПКИ ВКЛАДОК) -NAV_WIDGET_STYLE = f""" - QWidget {{ - background: {color_h}; - border: {border_a}; - }} -""" - -# СТИЛЬ КНОПОК ВКЛАДОК НАВИГАЦИИ -NAV_BUTTON_STYLE = f""" - NavLabel {{ - background: rgba(0,0,0,0); - padding: 12px 3px; - margin: 10px 0 10px 10px; - color: #7f7f7f; - font-family: '{font_family}'; - font-size: {font_size_a}; - text-transform: uppercase; - border: {color_a}; - border-radius: {border_radius_b}; - }} - NavLabel[checked = true] {{ - background: rgba(0,0,0,0); - color: {color_a}; - font-weight: normal; - text-decoration: underline; - border-radius: {border_radius_b}; - }} - NavLabel:hover {{ - background: none; - color: {color_a}; - }} -""" - -# СТИЛЬ ПОЛЯ ПОИСКА -SEARCH_EDIT_STYLE = f""" - QLineEdit {{ - background-color: rgba(30, 30, 30, 0.50); - border: {border_b} rgba(255, 255, 255, 0.5); - border-radius: {border_radius_a}; - padding: 7px 14px; - font-family: '{font_family}'; - font-size: {font_size_a}; - color: {color_f}; - }} - QLineEdit:focus {{ - border: {border_b} {color_a}; - }} -""" - -# ОТКЛЮЧАЕМ РАМКУ У QScrollArea -SCROLL_AREA_STYLE = f""" - QWidget {{ - background: {color_h}; - }} - QScrollBar:vertical {{ - width: 10px; - border: {border_a}; - border-radius: 5px; - background: rgba(20, 20, 20, 0.30); - }} - QScrollBar::handle:vertical {{ - background: #bebebe; - border: {border_a}; - border-radius: 5px; - }} - QScrollBar::add-line:vertical {{ - border: {border_a}; - background: none; - }} - QScrollBar::sub-line:vertical {{ - border: {border_a}; - background: none; - }} - QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical {{ - border: {border_a}; - width: 3px; - height: 3px; - background: none; - }} - - QScrollBar:horizontal {{ - height: 10px; - border: {border_a}; - border-radius: 5px; - background: rgba(20, 20, 20, 0.30); - }} - QScrollBar::handle:horizontal {{ - background: #bebebe; - border: {border_a}; - border-radius: 5px; - }} - QScrollBar::add-line:horizontal {{ - border: {border_a}; - background: none; - }} - QScrollBar::sub-line:horizontal {{ - border: {border_a}; - background: none; - }} - QScrollBar::up-arrow:horizontal, QScrollBar::down-arrow:horizontal {{ - border: {border_a}; - width: 3px; - height: 3px; - background: none; - }} -""" - -# SLIDER_SIZE_STYLE -SLIDER_SIZE_STYLE= f""" - QWidget {{ - background: {color_h}; - height: 25px; - }} - QSlider::groove:horizontal {{ - border: {border_a}; - 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: {border_a}; - 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: {border_a} {color_g}; - border-radius: 25px; - } -""" - -# ЗАГОЛОВОК "БИБЛИОТЕКА" НА ВКЛАДКЕ -INSTALLED_TAB_TITLE_STYLE = f""" - QLabel {{ - font-family: '{font_family}'; - font-size: {font_size_b}; - color: {color_f}; - }} -""" - -# СТИЛЬ КНОПОК "СОХРАНЕНИЯ, ПРИМЕНЕНИЯ И Т.Д." -ACTION_BUTTON_STYLE = f""" - QPushButton {{ - background: {color_c}; - border: {border_c} {color_g}; - border-radius: {border_radius_a}; - color: {color_f}; - font-size: {font_size_a}; - font-family: '{font_family}'; - padding: 8px 16px; - }} - QPushButton:hover {{ - background: {color_a}; - border: {border_c} {color_a}; - }} - QPushButton:pressed {{ - background: {color_b}; - }} - QPushButton:focus {{ - border: {border_c} {color_a}; - background-color: {color_a}; - }} -""" - -# СТИЛЬ ОВЕРЛЕЯ -OVERLAY_WINDOW_STYLE = f"background: {color_b};" -OVERLAY_BUTTON_STYLE = f""" - QPushButton {{ - background: {color_c}; - border: {border_c} {color_g}; - border-radius: {border_radius_a}; - color: {color_f}; - font-size: {font_size_a}; - font-family: '{font_family}'; - padding: 8px 16px; - }} - QPushButton:hover {{ - background: {color_a}; - border: {border_c} {color_a}; - }} - QPushButton:pressed {{ - background: {color_b}; - }} - QPushButton:focus {{ - border: {border_c} {color_a}; - background-color: {color_a}; - }} -""" - -# ТЕКСТОВЫЕ СТИЛИ: ЗАГОЛОВКИ И ОСНОВНОЙ КОНТЕНТ -TAB_TITLE_STYLE = f"font-family: '{font_family}'; font-size: {font_size_b}; color: {color_f}; background-color: none;" -CONTENT_STYLE = f""" - QLabel {{ - font-family: '{font_family}'; - font-size: {font_size_a}; - color: {color_f}; - background-color: none; - border-bottom: {border_b} rgba(255, 255, 255, 0.2); - padding-bottom: 15px; - }} -""" - -PREVIEW_WIDGET_STYLE = f""" - QWidget {{ - margin-top: 3px; - background-color: {color_c}; - border-radius: {border_radius_a}; - }} -""" - -# СТИЛЬ ОСНОВНЫХ СТРАНИЦ -# LIBRARY_WIDGET_STYLE -LIBRARY_WIDGET_STYLE= """ - QWidget { - background: qlineargradient(x1:0, y1:0, x2:1, y2:0, - stop:0 rgba(112,20,132,1), - stop:1 rgba(50,134,182,1)); - border-radius: 0px; - } -""" - -# CONTAINER_STYLE -CONTAINER_STYLE= """ - QWidget { - background-color: none; - } -""" - -# OTHER_PAGES_WIDGET_STYLE -OTHER_PAGES_WIDGET_STYLE= f""" - QWidget {{ - background: {color_d}; - border-radius: 0px; - }} -""" - -# CAROUSEL_WIDGET_STYLE -CAROUSEL_WIDGET_STYLE= f""" - QWidget {{ - background: {color_c}; - border-radius: 0px; - }} -""" - -# ФОН ДЛЯ ДЕТАЛЬНОЙ СТРАНИЦЫ, ЕСЛИ ОБЛОЖКА НЕ ЗАГРУЖЕНА -DETAIL_PAGE_NO_COVER_STYLE = f"background: rgba(20,20,20,0.95); border-radius: {border_radius_b};" - -# СТИЛЬ КНОПКИ "ДОБАВИТЬ ИГРУ" И "НАЗАД" НА ДЕТАЛЬНОЙ СТРАНИЦЕ И БИБЛИОТЕКИ -ADDGAME_BACK_BUTTON_STYLE = f""" - QPushButton {{ - background: rgba(20, 20, 20, 0.40); - border: {border_b} rgba(255, 255, 255, 0.5); - border-radius: {border_radius_a}; - color: {color_f}; - font-size: {font_size_a}; - font-family: '{font_family}'; - padding: 8px 16px; - }} - QPushButton:hover {{ - background: {color_a}; - }} - QPushButton:pressed {{ - background: {color_a}; - }} -""" - -# ОСНОВНОЙ ФРЕЙМ ДЕТАЛЕЙ ИГРЫ -DETAIL_CONTENT_FRAME_STYLE = f""" - 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: {border_a} {color_g}; - border-radius: {border_radius_b}; - }} -""" - -# ФРЕЙМ ПОД ОБЛОЖКОЙ -COVER_FRAME_STYLE = f""" - QFrame {{ - background: rgba(30, 30, 30, 0.80); - border-radius: {border_radius_b}; - border: {border_a} {color_g}; - }} -""" - -# СКРУГЛЕНИЕ LABEL ПОД ОБЛОЖКУ -COVER_LABEL_STYLE = f"border-radius: {border_radius_b};" - -# ВИДЖЕТ ДЕТАЛЕЙ (ТЕКСТ, ОПИСАНИЕ) -DETAILS_WIDGET_STYLE = f"background: rgba(20,20,20,0.40); border-radius: {border_radius_b}; padding: 10px;" - -# НАЗВАНИЕ (ЗАГОЛОВОК) НА ДЕТАЛЬНОЙ СТРАНИЦЕ -DETAIL_PAGE_TITLE_STYLE = f"font-family: '{font_family}'; font-size: 32px; color: #007AFF;" - -# ЛИНИЯ-РАЗДЕЛИТЕЛЬ -DETAIL_PAGE_LINE_STYLE = "color: rgba(255,255,255,0.12); margin: 10px 0;" - -# ТЕКСТ ОПИСАНИЯ -DETAIL_PAGE_DESC_STYLE = f"font-family: '{font_family}'; font-size: {font_size_a}; color: {color_f}; line-height: 1.5;" - -# СТИЛЬ КНОПКИ "ИГРАТЬ" -PLAY_BUTTON_STYLE = f""" - QPushButton {{ - background: rgba(20, 20, 20, 0.40); - border: {border_b} rgba(255, 255, 255, 0.5); - border-radius: {border_radius_a}; - font-size: 18px; - color: {color_f}; - font-weight: bold; - font-family: '{font_family}'; - padding: 8px 16px; - min-width: 120px; - min-height: 40px; - }} - QPushButton:hover {{ - background: {color_a}; - }} - QPushButton:pressed {{ - background: {color_a}; - }} - QPushButton:focus {{ - background: {color_a}; - }} -""" - - -ADDGAME_INPUT_STYLE = f""" - QLineEdit {{ - background: {color_c}; - border: {border_c} {color_g}; - border-radius: {border_radius_a}; - height: 34px; - padding-left: 12px; - color: {color_f}; - font-family: '{font_family}'; - font-size: {font_size_a}; - }} - QLineEdit:hover {{ - background: {color_c}; - border: {border_c} {color_a}; - }} - QLineEdit:focus {{ - border: {border_c} {color_a}; - background-color: {color_e}; - }} -""" - -# СТИЛЬ КАРТОЧКИ ИГРЫ (GAMECARD) -GAME_CARD_WINDOW_STYLE = f""" - QFrame {{ - border-radius: 20px; - background: rgba(20, 20, 20, 0.40); - border: {border_a} {color_g}; - }} -""" - -# НАЗВАНИЕ В КАРТОЧКЕ (QLabel) -GAME_CARD_NAME_LABEL_STYLE = f""" - QLabel {{ - color: {color_f}; - font-family: '{font_family}'; - font-size: {font_size_a}; - font-weight: bold; - background-color: {color_g}; - border-bottom-left-radius: 20px; - border-bottom-right-radius: 20px; - padding: 14px, 7px, 3px, 7px; - qproperty-wordWrap: true; - }} -""" - -# ДОПОЛНИТЕЛЬНЫЕ СТИЛИ ИНФОРМАЦИИ НА СТРАНИЦЕ ИГР -LAST_LAUNCH_TITLE_STYLE = f"font-family: '{font_family}'; font-size: 11px; color: #bbbbbb; text-transform: uppercase; letter-spacing: 0.75px; margin-bottom: 2px;" -LAST_LAUNCH_VALUE_STYLE = f"font-family: '{font_family}'; font-size: 13px; color: {color_f}; font-weight: 600; letter-spacing: 0.75px;" -PLAY_TIME_TITLE_STYLE = f"font-family: '{font_family}'; font-size: 11px; color: #bbbbbb; text-transform: uppercase; letter-spacing: 0.75px; margin-bottom: 2px;" -PLAY_TIME_VALUE_STYLE = f"font-family: '{font_family}'; font-size: 13px; color: {color_f}; font-weight: 600; letter-spacing: 0.75px;" -GAMEPAD_SUPPORT_VALUE_STYLE = f""" - font-family: '{font_family}'; font-size: {font_size_a}; color: #00ff00; - font-weight: bold; background: {color_g}; - 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=f"color: white; font-size: {font_size_a};" - -# СТИЛИ БЕЙДЖА 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: '{font_family}'; - font-weight: bold; - """ - -# СТИЛИ БЕЙДЖА WEANTICHEATYET -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"]}; - font-size: {font_size_a}; - border-radius: 5px; - font-weight: bold; - """ - -# СТИЛИ БЕЙДЖА STEAM -STEAM_BADGE_STYLE= f""" - qproperty-alignment: AlignCenter; - background: rgba(0, 0, 0, 0.5); - color: white; - border-radius: 5px; - font-family: '{font_family}'; - font-weight: bold; -""" - -# Favorite Star -FAVORITE_LABEL_STYLE = f"color: gold; font-size: 32px; background: {color_h};" - -# СТИЛИ ДЛЯ QMessageBox (ОКНА СООБЩЕНИЙ) -MESSAGE_BOX_STYLE = f""" - 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: {border_b} rgba(255, 255, 255, 0.15); - border-radius: 12px; - }} - QMessageBox QLabel {{ - color: {color_f}; - font-family: '{font_family}'; - font-size: {font_size_a}; - }} - QMessageBox QPushButton {{ - background: rgba(30, 30, 30, 0.6); - border: {border_b} rgba(255, 255, 255, 0.2); - border-radius: {border_radius_a}; - color: {color_f}; - font-family: '{font_family}'; - padding: 8px 20px; - min-width: 80px; - }} - QMessageBox QPushButton:hover {{ - background: #09bec8; - border-color: rgba(255, 255, 255, 0.3); - }} - QMessageBox QPushButton:focus {{ - border: {border_c} {color_a}; - background: {color_e}; - }} -""" - -# СТИЛИ ДЛЯ ВКЛАДКИ НАСТРОЕК PORTPROTON -# PARAMS_TITLE_STYLE -PARAMS_TITLE_STYLE = f"color: {color_f}; font-family: '{font_family}'; font-size: {font_size_a}; padding: 10px; background: {color_h};" - -PROXY_INPUT_STYLE = f""" - QLineEdit {{ - background: {color_b}; - border: {border_c} rgba(255, 255, 255, 0.01); - border-radius: {border_radius_a}; - height: 34px; - padding-left: 12px; - color: {color_f}; - font-family: '{font_family}'; - font-size: {font_size_a}; - }} - QLineEdit:hover {{ - background: {color_c}; - border: {border_c} {color_a}; - }} - QLineEdit:focus {{ - border: {border_c} {color_a}; - background-color: {color_e}; - }} -""" - -SETTINGS_COMBO_STYLE = f""" - QComboBox {{ - background: {color_c}; - border: {border_c} {color_g}; - border-radius: {border_radius_a}; - height: 34px; - padding-left: 12px; - color: {color_f}; - font-family: '{font_family}'; - font-size: {font_size_a}; - min-width: 120px; - combobox-popup: 0; - }} - QComboBox:on {{ - background: {color_b}; - border: {border_c} {color_a}; - border-bottom-style: none; - border-top-left-radius: 10px; - border-top-right-radius: 10px; - border-bottom-left-radius: 0px; - border-bottom-right-radius: 0px; - }} - QComboBox:hover {{ - border: {border_c} {color_a}; - background: {color_a}; - }} - /* Состояние фокуса */ - QComboBox:focus {{ - border: {border_c} {color_a}; - background-color: {color_a}; - }} - QComboBox::drop-down {{ - subcontrol-origin: padding; - subcontrol-position: center right; - border-left: {border_b} rgba(255, 255, 255, 0.05); - 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: {border_c} {color_a}; - border-top-style: none; - border-top-left-radius: 0px; - border-top-right-radius: 0px; - border-bottom-left-radius: 10px; - border-bottom-right-radius: 10px; - }} - QListView {{ - background: {color_c}; - }} - QListView::item {{ - padding: 7px 7px 7px 12px; - margin: 3px; - border-radius: {border_radius_a}; - color: {color_f}; - }} - QListView::item:hover {{ - background: {color_b}; - }} - QListView::item:selected {{ - background: {color_b}; - }} - /* Выделение в списке при фокусе на элементе */ - QListView::item:focus {{ - background: {color_a}; - color: {color_f}; - }} -""" - -SETTINGS_CHECKBOX_STYLE = f""" - QCheckBox {{ - height: 34px; - color: {color_f}; - font-family: '{font_family}'; - font-size: {font_size_a}; - }} - QCheckBox::indicator {{ - width: 24px; - height: 24px; - border: {border_c} {color_g}; - border-radius: {border_radius_a}; - background: {color_b}; - }} - QCheckBox::indicator:hover {{ - background: {color_c}; - border: {border_c} {color_a}; - }} - QCheckBox::indicator:focus {{ - border: {border_c} {color_a}; - }} - QCheckBox::indicator:checked {{ - image: url({theme_manager.get_icon("check", current_theme_name, as_path=True)}); - border: {border_c} {color_a}; - }} -""" - -WINETRICKS_TAB_STYLE = f""" -QTabWidget::pane {{ - border-top: 1px solid {color_c}; - background: {color_h}; -}} -QTabBar::tab {{ - background: {color_c}; - color: {color_f}; - padding: 8px 16px; - border-top-left-radius: {border_radius_a}; - border-top-right-radius: {border_radius_a}; - margin-right: 2px; -}} -QTabBar::tab:selected {{ - background: {color_a}; - color: {color_f}; -}} -QTabBar::tab:hover {{ - background: {color_a}; -}} -""" - -WINETRICKS_TABBLE_STYLE = f""" -QComboBox {{ - background: {color_c}; - border: {border_c} {color_g}; - border-radius: {border_radius_a}; - padding-left: 12px; - color: {color_f}; - font-family: '{font_family}'; - font-size: {font_size_a}; - min-width: 120px; - combobox-popup: 0; -}} -QComboBox:on {{ - background: {color_b}; - border: {border_c} {color_a}; - border-bottom-style: none; - border-top-left-radius: 10px; - border-top-right-radius: 10px; - border-bottom-left-radius: 0px; - border-bottom-right-radius: 0px; -}} -QComboBox:hover {{ - border: {border_c} {color_a}; - background: {color_a}; -}} -/* Состояние фокуса */ -QComboBox:focus {{ - border: {border_c} {color_a}; - background-color: {color_a}; -}} -QComboBox:disabled {{ - background: #2a2c35; - border: {border_c} #2a2c35; - color: #777a84; -}} -QComboBox::drop-down {{ - subcontrol-origin: padding; - subcontrol-position: center right; - border-left: {border_b} rgba(255, 255, 255, 0.05); - 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; - background: {color_c}; - border: {border_c} {color_a}; - border-top-style: none; - border-top-left-radius: 0px; - border-top-right-radius: 0px; - border-bottom-left-radius: 10px; - border-bottom-right-radius: 10px; -}} -QListView {{ - background: {color_c}; -}} -QListView::item {{ - padding: 7px 7px 7px 12px; - margin: 3px; - border-radius: {border_radius_a}; - color: {color_f}; -}} -QListView::item:hover {{ - background: {color_b}; -}} -QListView::item:selected {{ - background: {color_b}; -}} -/* Выделение в списке при фокусе на элементе */ -QListView::item:focus {{ - background: {color_a}; - color: {color_f}; -}} -QLineEdit {{ - background: {color_c}; - border: {border_c} rgba(255, 255, 255, 0.01); - border-radius: {border_radius_a}; - height: 34px; - padding-left: 12px; - color: {color_f}; - font-family: '{font_family}'; - font-size: {font_size_a}; -}} -QLineEdit:hover {{ - background: {color_c}; - border: {border_c} {color_a}; -}} -QLineEdit:focus {{ - border: {border_c} {color_a}; - background-color: {color_e}; -}} -QTableWidget {{ - background: {color_h}; - color: {color_f}; - gridline-color: {color_h}; - alternate-background-color: {color_d}; - border: {border_a}; - border-radius: {border_radius_a}; - font-family: '{font_family}'; - font-size: {font_size_a}; -}} -QHeaderView::section {{ - background: {color_d}; - color: {color_f}; - padding: 5px; - border: {border_a}; - font-weight: bold; -}} -QTableWidget::item {{ - padding: 8px; - border-bottom: {border_a } {color_c}; - height: 36px; -}} -QTableWidget::item:selected, -QTableWidget::item:focus, -QTableWidget::item:selected:focus {{ - background: {color_a}; - color: {color_f}; - selection-background-color: {color_a}; -}} -QTableWidget::item:hover {{ - background: {color_h}; -}} -QTableWidget::indicator {{ - width: 24px; - height: 24px; - border: {border_c} {color_h}; - border-radius: {border_radius_a}; - background: {color_b}; -}} -QTableWidget::indicator:unchecked {{ - background: rgba(255, 255, 255, 0.1); - image: none; -}} -QTableWidget::indicator:checked {{ - background: {color_b}; - image: url({theme_manager.get_icon("check", current_theme_name, as_path=True)}); - border: {border_c} {color_a}; -}} -QTableWidget::indicator:hover {{ - background: rgba(255, 255, 255, 0.2); - border: {border_c} {color_a}; -}} -QTableWidget::indicator:focus {{ - background: rgba(255, 255, 255, 0.2); - border: {border_c} {color_a}; -}} -QScrollBar:vertical {{ - width: 10px; - border: {border_a}; - border-radius: 5px; - background: rgba(20, 20, 20, 0.30); -}} -QScrollBar::handle:vertical {{ - background: #bebebe; - border: {border_a}; - border-radius: 5px; -}} -QScrollBar::add-line:vertical {{ - border: {border_a}; - background: none; -}} -QScrollBar::sub-line:vertical {{ - border: {border_a}; - background: none; -}} -QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical {{ - border: {border_a}; - width: 3px; - height: 3px; - background: none; -}} -QScrollBar:horizontal {{ - height: 10px; - border: {border_a}; - border-radius: 5px; - background: rgba(20, 20, 20, 0.30); -}} -QScrollBar::handle:horizontal {{ - background: #bebebe; - border: {border_a}; - border-radius: 5px; -}} -QScrollBar::add-line:horizontal {{ - border: {border_a}; - background: none; -}} -QScrollBar::sub-line:horizontal {{ - border: {border_a}; - background: none; -}} -QScrollBar::up-arrow:horizontal, QScrollBar::down-arrow:horizontal {{ - border: {border_a}; - width: 3px; - height: 3px; - background: none; -}} -""" - -WINETRICKS_LOG_STYLE = f""" -QTextEdit {{ - background: {color_c}; - border: {border_a}; - border-radius: {border_radius_a}; - color: {color_f}; - font-family: '{font_family}'; - font-size: {font_size_a}; - padding: 5px; -}} -""" - -FILE_EXPLORER_STYLE = f""" - QListView {{ - font-size: {font_size_a}; - font-family: {font_family}; - background: {color_c}; - alternate-background-color: {color_c}; - color: {color_f}; - border-top-left-radius: 5px; - border-bottom-left-radius: 5px; - }} - QListView::item {{ - padding: 8px; - margin: 0px 5px; - }} - QListView::item:alternate {{ - margin: 0px 5px; - background: {color_d}; - }} - QListView::item:selected {{ - background: {color_a}; - color: {color_f}; - border-radius: {border_radius_a}; - }} - QListView::item:hover {{ - background: {color_a}; - color: {color_f}; - border-radius: {border_radius_a}; - }} - QListView::item:focus {{ - background: {color_a}; - color: {color_f}; - border-radius: {border_radius_a}; - }} - QScrollBar:vertical {{ - width: 10px; - border: {border_a}; - border-radius: 5px; - background: {color_c}; - }} - QScrollBar::handle:vertical {{ - background: #bebebe; - border: {border_a}; - border-radius: 5px; - }} - QScrollBar::add-line:vertical {{ - border: {border_a}; - background: {color_c}; - border-bottom-right-radius: 5px; - }} - QScrollBar::sub-line:vertical {{ - border: {border_a}; - background: {color_c}; - border-top-right-radius: 5px; - }} - QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical {{ - border: {border_a}; - width: 3px; - height: 3px; - background: none; - }} -""" - -FILE_EXPLORER_PATH_LABEL_STYLE = f""" - QLabel {{ - color: {color_a}; - font-size: {font_size_a}; - font-family: {font_family}; - }} -""" - -# ФУНКЦИЯ ДЛЯ ДИНАМИЧЕСКОГО ГРАДИЕНТА (ДЕТАЛИ ИГР) -# Функции из этой темы срабатывает всегда вне зависимости от выбранной темы, функции из других тем работают только в этих темах -def detail_page_style(stops): - return f""" - QWidget {{ - background: qlineargradient(x1:0, y1:0, x2:1, y2:1, - {stops}); - border-radius: {border_radius_b}; - }} -""" +# Import from the theme's submodules using absolute paths relative to the package +from portprotonqt.themes.standart.styles.constants import * +from portprotonqt.themes.standart.styles.base import * +from portprotonqt.themes.standart.styles.game_card import * +from portprotonqt.themes.standart.styles.detail_page import * +from portprotonqt.themes.standart.styles.settings import * +from portprotonqt.themes.standart.styles.winetricks import * +from portprotonqt.themes.standart.styles.theme_utils import * diff --git a/portprotonqt/themes/standart/styles/__init__.py b/portprotonqt/themes/standart/styles/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/portprotonqt/themes/standart/styles/base.py b/portprotonqt/themes/standart/styles/base.py new file mode 100644 index 0000000..fbca417 --- /dev/null +++ b/portprotonqt/themes/standart/styles/base.py @@ -0,0 +1,378 @@ +from .constants import * + +# ГЛОБАЛЬНЫЙ СТИЛЬ ДЛЯ ОКНА (ФОН), ЛЭЙБЛОВ, КНОПОК +MAIN_WINDOW_STYLE = f""" + QWidget {{ + background: {color_b}; + }} + QLabel {{ + color: {color_f}; + font-family: '{font_family}'; + font-size: {font_size_a}; + }} + QPushButton {{ + background: {color_c}; + border: {border_c} rgba(255, 255, 255, 0.01); + border-radius: {border_radius_a}; + color: {color_f}; + font-size: {font_size_a}; + font-family: '{font_family}'; + padding: 8px 16px; + }} + QPushButton:hover {{ + background: {color_a}; + border: {border_c} {color_a}; + }} + QPushButton:pressed {{ + background: {color_b}; + }} + QPushButton:focus {{ + border: {border_c} {color_a}; + background-color: {color_a}; + }} +""" + +# СТИЛЬ ПРОГРЕСС-БАРА +PROGRESS_BAR_STYLE = f""" + QProgressBar {{ + color: {color_f}; + background-color: {color_c}; + text-align: center; + }} + QProgressBar::chunk {{ + background-color: {color_a}; + }} +""" + +# СТИЛЬ СТАТУС-БАРА +STATUS_BAR_STYLE = f""" + QStatusBar {{ + color: {color_f}; + }} +""" + +# СТИЛЬ ШАПКИ ГЛАВНОГО ОКНА +MAIN_WINDOW_HEADER_STYLE = f""" + QFrame {{ + background: {color_h}; + border: 10px solid {color_g}; + border-bottom: 0px solid {color_g}; + border-top-left-radius: 30px; + border-top-right-radius: 30px; + border: none; + }} +""" + +# СТИЛЬ ОБЛАСТИ НАВИГАЦИИ (КНОПКИ ВКЛАДОК) +NAV_WIDGET_STYLE = f""" + QWidget {{ + background: {color_h}; + border: {border_a}; + }} +""" + +# СТИЛЬ КНОПОК ВКЛАДОК НАВИГАЦИИ +NAV_BUTTON_STYLE = f""" + NavLabel {{ + background: rgba(0,0,0,0); + padding: 12px 3px; + margin: 10px 0 10px 10px; + color: #7f7f7f; + font-family: '{font_family}'; + font-size: {font_size_a}; + text-transform: uppercase; + border: {color_a}; + border-radius: {border_radius_b}; + }} + NavLabel[checked = true] {{ + background: rgba(0,0,0,0); + color: {color_a}; + font-weight: normal; + text-decoration: underline; + border-radius: {border_radius_b}; + }} + NavLabel:hover {{ + background: none; + color: {color_a}; + }} +""" + +# СТИЛЬ ПОЛЯ ПОИСКА +SEARCH_EDIT_STYLE = f""" + QLineEdit {{ + background-color: rgba(30, 30, 30, 0.50); + border: {border_b} rgba(255, 255, 255, 0.5); + border-radius: {border_radius_a}; + padding: 7px 14px; + font-family: '{font_family}'; + font-size: {font_size_a}; + color: {color_f}; + }} + QLineEdit:focus {{ + border: {border_b} {color_a}; + }} +""" + +# ОТКЛЮЧАЕМ РАМКУ У QScrollArea +SCROLL_AREA_STYLE = f""" + QWidget {{ + background: {color_h}; + }} + QScrollBar:vertical {{ + width: 10px; + border: {border_a}; + border-radius: 5px; + background: rgba(20, 20, 20, 0.30); + }} + QScrollBar::handle:vertical {{ + background: #bebebe; + border: {border_a}; + border-radius: 5px; + }} + QScrollBar::add-line:vertical {{ + border: {border_a}; + background: none; + }} + QScrollBar::sub-line:vertical {{ + border: {border_a}; + background: none; + }} + QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical {{ + border: {border_a}; + width: 3px; + height: 3px; + background: none; + }} + + QScrollBar:horizontal {{ + height: 10px; + border: {border_a}; + border-radius: 5px; + background: rgba(20, 20, 20, 0.30); + }} + QScrollBar::handle:horizontal {{ + background: #bebebe; + border: {border_a}; + border-radius: 5px; + }} + QScrollBar::add-line:horizontal {{ + border: {border_a}; + background: none; + }} + QScrollBar::sub-line:horizontal {{ + border: {border_a}; + background: none; + }} + QScrollBar::up-arrow:horizontal, QScrollBar::down-arrow:horizontal {{ + border: {border_a}; + width: 3px; + height: 3px; + background: none; + }} +""" + +# SLIDER_SIZE_STYLE +SLIDER_SIZE_STYLE= f""" + QWidget {{ + background: {color_h}; + height: 25px; + }} + QSlider::groove:horizontal {{ + border: {border_a}; + 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: {border_a}; + 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: {border_a} {color_g}; + border-radius: 25px; + } +""" + +# ЗАГОЛОВОК "БИБЛИОТЕКА" НА ВКЛАДКЕ +INSTALLED_TAB_TITLE_STYLE = f""" + QLabel {{ + font-family: '{font_family}'; + font-size: {font_size_b}; + color: {color_f}; + }} +""" + +# СТИЛЬ КНОПОК "СОХРАНЕНИЯ, ПРИМЕНЕНИЯ И Т.Д." +ACTION_BUTTON_STYLE = f""" + QPushButton {{ + background: {color_c}; + border: {border_c} {color_g}; + border-radius: {border_radius_a}; + color: {color_f}; + font-size: {font_size_a}; + font-family: '{font_family}'; + padding: 8px 16px; + }} + QPushButton:hover {{ + background: {color_a}; + border: {border_c} {color_a}; + }} + QPushButton:pressed {{ + background: {color_b}; + }} + QPushButton:focus {{ + border: {border_c} {color_a}; + background-color: {color_a}; + }} +""" + +# СТИЛЬ ОВЕРЛЕЯ +OVERLAY_WINDOW_STYLE = f"background: {color_b};" +OVERLAY_BUTTON_STYLE = f""" + QPushButton {{ + background: {color_c}; + border: {border_c} {color_g}; + border-radius: {border_radius_a}; + color: {color_f}; + font-size: {font_size_a}; + font-family: '{font_family}'; + padding: 8px 16px; + }} + QPushButton:hover {{ + background: {color_a}; + border: {border_c} {color_a}; + }} + QPushButton:pressed {{ + background: {color_b}; + }} + QPushButton:focus {{ + border: {border_c} {color_a}; + background-color: {color_a}; + }} +""" + +# ТЕКСТОВЫЕ СТИЛИ: ЗАГОЛОВКИ И ОСНОВНОЙ КОНТЕНТ +TAB_TITLE_STYLE = f"font-family: '{font_family}'; font-size: {font_size_b}; color: {color_f}; background-color: none;" +CONTENT_STYLE = f""" + QLabel {{ + font-family: '{font_family}'; + font-size: {font_size_a}; + color: {color_f}; + background-color: none; + border-bottom: {border_b} rgba(255, 255, 255, 0.2); + padding-bottom: 15px; + }} +""" + +PREVIEW_WIDGET_STYLE = f""" + QWidget {{ + margin-top: 3px; + background-color: {color_c}; + border-radius: {border_radius_a}; + }} +""" + +# СТИЛЬ ОСНОВНЫХ СТРАНИЦ +# LIBRARY_WIDGET_STYLE +LIBRARY_WIDGET_STYLE= """ + QWidget { + background: qlineargradient(x1:0, y1:0, x2:1, y2:0, + stop:0 rgba(112,20,132,1), + stop:1 rgba(50,134,182,1)); + border-radius: 0px; + } +""" + +# CONTAINER_STYLE +CONTAINER_STYLE= """ + QWidget { + background-color: none; + } +""" + +# OTHER_PAGES_WIDGET_STYLE +OTHER_PAGES_WIDGET_STYLE= f""" + QWidget {{ + background: {color_d}; + border-radius: 0px; + }} +""" + +# CAROUSEL_WIDGET_STYLE +CAROUSEL_WIDGET_STYLE= f""" + QWidget {{ + background: {color_c}; + border-radius: 0px; + }} +""" + +# СТИЛИ ДЛЯ ВКЛАДКИ НАСТРОЕК PORTPROTON +# PARAMS_TITLE_STYLE +PARAMS_TITLE_STYLE = f"color: {color_f}; font-family: '{font_family}'; font-size: {font_size_a}; padding: 10px; background: {color_h};" + +PROXY_INPUT_STYLE = f""" + QLineEdit {{ + background: {color_b}; + border: {border_c} rgba(255, 255, 255, 0.01); + border-radius: {border_radius_a}; + height: 34px; + padding-left: 12px; + color: {color_f}; + font-family: '{font_family}'; + font-size: {font_size_a}; + }} + QLineEdit:hover {{ + background: {color_c}; + border: {border_c} {color_a}; + }} + QLineEdit:focus {{ + border: {border_c} {color_a}; + background-color: {color_e}; + }} +""" + +# СТИЛИ ДЛЯ QMessageBox (ОКНА СООБЩЕНИЙ) +MESSAGE_BOX_STYLE = f""" + 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: {border_b} rgba(255, 255, 255, 0.15); + border-radius: 12px; + }} + QMessageBox QLabel {{ + color: {color_f}; + font-family: '{font_family}'; + font-size: {font_size_a}; + }} + QMessageBox QPushButton {{ + background: rgba(30, 30, 30, 0.6); + border: {border_b} rgba(255, 255, 255, 0.2); + border-radius: {border_radius_a}; + color: {color_f}; + font-family: '{font_family}'; + padding: 8px 20px; + min-width: 80px; + }} + QMessageBox QPushButton:hover {{ + background: #09bec8; + border-color: rgba(255, 255, 255, 0.3); + }} + QMessageBox QPushButton:focus {{ + border: {border_c} {color_a}; + background: {color_e}; + }} +""" + +# Favorite Star +FAVORITE_LABEL_STYLE = f"color: gold; font-size: 32px; background: {color_h};" diff --git a/portprotonqt/themes/standart/styles/constants.py b/portprotonqt/themes/standart/styles/constants.py new file mode 100644 index 0000000..7c52ff5 --- /dev/null +++ b/portprotonqt/themes/standart/styles/constants.py @@ -0,0 +1,176 @@ +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 + +# VARS +font_family = "Play" +font_size_a = "16px" +font_size_b = "24px" +border_a = "0px solid" +border_b = "1px solid" +border_c = "2px solid" +border_radius_a = "10px" +border_radius_b = "15px" +color_a = "#409EFF" +color_b = "#282a33" +color_c = "#3f424d" +color_d = "#32343d" +color_e = "#404554" +color_f = "#ffffff" +color_g = "rgba(0, 0, 0, 0)" +color_h = "transparent" +color_i = "rgba(40, 42, 51, 0.9)" + +GAME_CARD_ANIMATION = { + # Тип анимации при входе и выходе на детальную страницу + # Возможные значения: "fade", "slide_left", "slide_right", "slide_up", "slide_down", "bounce" + # Определяет, как детальная страница появляется и исчезает + "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, + + # Тип анимации для карточки при наведении или фокусе + # Возможные значения: "gradient", "scale" + # "gradient" включает вращающийся градиент для обводки, "scale" увеличивает размер карточки + "card_animation_type": "gradient", + + # Масштаб карточки в состоянии покоя + # Определяет базовый размер карточки (1.0 = 100% от исходного размера) + # Значение в долях (например, 1.0 для нормального размера) + "default_scale": 1.0, + + # Масштаб карточки при наведении курсора + # Увеличивает размер карточки при наведении + # Значение в долях (например, 1.1 = 110% от исходного размера) + "hover_scale": 1.1, + + # Масштаб карточки при фокусе (например, при выборе с клавиатуры) + # Увеличивает размер карточки при фокусе + # Значение в долях (например, 1.05 = 105% от исходного размера) + "focus_scale": 1.05, + + # Длительность анимации масштабирования + # Влияет на скорость изменения размера карточки при наведении или фокусе + # Значение в миллисекундах + "scale_anim_duration": 200, + + # Тип кривой сглаживания для анимации увеличения обводки (при наведении/фокусе) + # Влияет на "чувство" анимации (например, плавное ускорение или замедление) + # Возможные значения: строки, соответствующие QEasingCurve.Type (например, "OutBack", "InOutQuad") + "thickness_easing_curve": "OutBack", + + # Тип кривой сглаживания для анимации уменьшения обводки (при уходе курсора/потере фокуса) + # Влияет на "чувство" возврата к исходной ширине обводки + "thickness_easing_curve_out": "InBack", + + # Тип кривой сглаживания для анимации увеличения масштаба (при наведении/фокусе) + # Влияет на "чувство" анимации масштабирования (например, с эффектом "отскока") + # Возможные значения: строки, соответствующие QEasingCurve.Type + "scale_easing_curve": "OutBack", + + # Тип кривой сглаживания для анимации уменьшения масштаба (при уходе курсора/потере фокуса) + # Влияет на "чувство" возврата к исходному масштабу + "scale_easing_curve_out": "InBack", + + # Цвета градиента для анимированной обводки + # Список словарей, где каждый словарь задает позицию (0.0–1.0) и цвет в формате hex + # Влияет на внешний вид обводки при наведении или фокусе, если card_animation_type="gradient" + "gradient_colors": [ + {"position": 0, "color": "#00fff5"}, # Начальный цвет (циан) + {"position": 0.33, "color": "#FF5733"}, # Цвет на 33% (оранжевый) + {"position": 0.66, "color": "#9B59B6"}, # Цвет на 66% (пурпурный) + {"position": 1, "color": "#00fff5"} # Конечный цвет (возвращение к циану) + ], + + # Длительность анимации fade при входе на детальную страницу + # Влияет на скорость появления страницы при fade-анимации + # Значение в миллисекундах + "detail_page_fade_duration": 350, + + # Длительность анимации slide при входе на детальную страницу + # Влияет на скорость скольжения страницы при slide-анимации + # Значение в миллисекундах + "detail_page_slide_duration": 500, + + # Длительность анимации bounce при входе на детальную страницу + # Влияет на скорость "прыжка" страницы при bounce-анимации + # Значение в миллисекундах + "detail_page_bounce_duration": 400, + + # Длительность анимации fade при выходе из детальной страницы + # Влияет на скорость исчезновения страницы при fade-анимации + # Значение в миллисекундах + "detail_page_fade_duration_exit": 350, + + # Длительность анимации slide при выходе из детальной страницы + # Влияет на скорость скольжения страницы при slide-анимации + # Значение в миллисекундах + "detail_page_slide_duration_exit": 500, + + # Длительность анимации bounce при выходе из детальной страницы + # Влияет на скорость "сжатия" страницы при bounce-анимации + # Значение в миллисекундах + "detail_page_bounce_duration_exit": 400, + + # Тип кривой сглаживания для анимации при входе на детальную страницу + # Применяется к slide и bounce анимациям, влияет на "чувство" движения + # Возможные значения: строки, соответствующие QEasingCurve.Type + "detail_page_easing_curve": "OutCubic", + + # Тип кривой сглаживания для анимации при выходе из детальной страницы + # Применяется к slide и bounce анимациям, влияет на "чувство" движения + # Возможные значения: строки, соответствующие QEasingCurve.Type + "detail_page_easing_curve_exit": "InCubic" +} diff --git a/portprotonqt/themes/standart/styles/detail_page.py b/portprotonqt/themes/standart/styles/detail_page.py new file mode 100644 index 0000000..d0c1349 --- /dev/null +++ b/portprotonqt/themes/standart/styles/detail_page.py @@ -0,0 +1,115 @@ +from .constants import * + +# ФОН ДЛЯ ДЕТАЛЬНОЙ СТРАНИЦЫ, ЕСЛИ ОБЛОЖКА НЕ ЗАГРУЖЕНА +DETAIL_PAGE_NO_COVER_STYLE = f"background: rgba(20,20,20,0.95); border-radius: {border_radius_b};" + +# СТИЛЬ КНОПКИ "ДОБАВИТЬ ИГРУ" И "НАЗАД" НА ДЕТАЛЬНОЙ СТРАНИЦЕ И БИБЛИОТЕКИ +ADDGAME_BACK_BUTTON_STYLE = f""" + QPushButton {{ + background: rgba(20, 20, 20, 0.40); + border: {border_b} rgba(255, 255, 255, 0.5); + border-radius: {border_radius_a}; + color: {color_f}; + font-size: {font_size_a}; + font-family: '{font_family}'; + padding: 8px 16px; + }} + QPushButton:hover {{ + background: {color_a}; + }} + QPushButton:pressed {{ + background: {color_a}; + }} +""" + +# ОСНОВНОЙ ФРЕЙМ ДЕТАЛЕЙ ИГРЫ +DETAIL_CONTENT_FRAME_STYLE = f""" + 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: {border_a} {color_g}; + border-radius: {border_radius_b}; + }} +""" + +# ФРЕЙМ ПОД ОБЛОЖКОЙ +COVER_FRAME_STYLE = f""" + QFrame {{ + background: rgba(30, 30, 30, 0.80); + border-radius: {border_radius_b}; + border: {border_a} {color_g}; + }} +""" + +# СКРУГЛЕНИЕ LABEL ПОД ОБЛОЖКУ +COVER_LABEL_STYLE = f"border-radius: {border_radius_b};" + +# ВИДЖЕТ ДЕТАЛЕЙ (ТЕКСТ, ОПИСАНИЕ) +DETAILS_WIDGET_STYLE = f"background: rgba(20,20,20,0.40); border-radius: {border_radius_b}; padding: 10px;" + +# НАЗВАНИЕ (ЗАГОЛОВОК) НА ДЕТАЛЬНОЙ СТРАНИЦЕ +DETAIL_PAGE_TITLE_STYLE = f"font-family: '{font_family}'; font-size: 32px; color: #007AFF;" + +# ЛИНИЯ-РАЗДЕЛИТЕЛЬ +DETAIL_PAGE_LINE_STYLE = "color: rgba(255,255,255,0.12); margin: 10px 0;" + +# ТЕКСТ ОПИСАНИЯ +DETAIL_PAGE_DESC_STYLE = f"font-family: '{font_family}'; font-size: {font_size_a}; color: {color_f}; line-height: 1.5;" + +# СТИЛЬ КНОПКИ "ИГРАТЬ" +PLAY_BUTTON_STYLE = f""" + QPushButton {{ + background: rgba(20, 20, 20, 0.40); + border: {border_b} rgba(255, 255, 255, 0.5); + border-radius: {border_radius_a}; + font-size: 18px; + color: {color_f}; + font-weight: bold; + font-family: '{font_family}'; + padding: 8px 16px; + min-width: 120px; + min-height: 40px; + }} + QPushButton:hover {{ + background: {color_a}; + }} + QPushButton:pressed {{ + background: {color_a}; + }} + QPushButton:focus {{ + background: {color_a}; + }} +""" + +ADDGAME_INPUT_STYLE = f""" + QLineEdit {{ + background: {color_c}; + border: {border_c} {color_g}; + border-radius: {border_radius_a}; + height: 34px; + padding-left: 12px; + color: {color_f}; + font-family: '{font_family}'; + font-size: {font_size_a}; + }} + QLineEdit:hover {{ + background: {color_c}; + border: {border_c} {color_a}; + }} + QLineEdit:focus {{ + border: {border_c} {color_a}; + background-color: {color_e}; + }} +""" + +# ФУНКЦИЯ ДЛЯ ДИНАМИЧЕСКОГО ГРАДИЕНТА (ДЕТАЛИ ИГР) +# Функции из этой темы срабатывает всегда вне зависимости от выбранной темы, функции из других тем работают только в этих темах +def detail_page_style(stops): + return f""" + QWidget {{ + background: qlineargradient(x1:0, y1:0, x2:1, y2:1, + {stops}); + border-radius: {border_radius_b}; + }} +""" diff --git a/portprotonqt/themes/standart/styles/game_card.py b/portprotonqt/themes/standart/styles/game_card.py new file mode 100644 index 0000000..ae6400f --- /dev/null +++ b/portprotonqt/themes/standart/styles/game_card.py @@ -0,0 +1,87 @@ +from .constants import * + +# СТИЛЬ КАРТОЧКИ ИГРЫ (GAMECARD) +GAME_CARD_WINDOW_STYLE = f""" + QFrame {{ + border-radius: 20px; + background: rgba(20, 20, 20, 0.40); + border: {border_a} {color_g}; + }} +""" + +# НАЗВАНИЕ В КАРТОЧКЕ (QLabel) +GAME_CARD_NAME_LABEL_STYLE = f""" + QLabel {{ + color: {color_f}; + font-family: '{font_family}'; + font-size: {font_size_a}; + font-weight: bold; + background-color: {color_g}; + border-bottom-left-radius: 20px; + border-bottom-right-radius: 20px; + padding: 14px, 7px, 3px, 7px; + qproperty-wordWrap: true; + }} +""" + +# СТИЛИ БЕЙДЖА 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: '{font_family}'; + font-weight: bold; + """ + +# СТИЛИ БЕЙДЖА WEANTICHEATYET +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"]}; + font-size: {font_size_a}; + border-radius: 5px; + font-weight: bold; + """ + +# СТИЛИ БЕЙДЖА STEAM +STEAM_BADGE_STYLE= f""" + qproperty-alignment: AlignCenter; + background: rgba(0, 0, 0, 0.5); + color: white; + border-radius: 5px; + font-family: '{font_family}'; + font-weight: bold; +""" + +# ДОПОЛНИТЕЛЬНЫЕ СТИЛИ ИНФОРМАЦИИ НА СТРАНИЦЕ ИГР +LAST_LAUNCH_TITLE_STYLE = f"font-family: '{font_family}'; font-size: 11px; color: #bbbbbb; text-transform: uppercase; letter-spacing: 0.75px; margin-bottom: 2px;" +LAST_LAUNCH_VALUE_STYLE = f"font-family: '{font_family}'; font-size: 13px; color: {color_f}; font-weight: 600; letter-spacing: 0.75px;" +PLAY_TIME_TITLE_STYLE = f"font-family: '{font_family}'; font-size: 11px; color: #bbbbbb; text-transform: uppercase; letter-spacing: 0.75px; margin-bottom: 2px;" +PLAY_TIME_VALUE_STYLE = f"font-family: '{font_family}'; font-size: 13px; color: {color_f}; font-weight: 600; letter-spacing: 0.75px;" +GAMEPAD_SUPPORT_VALUE_STYLE = f""" + font-family: '{font_family}'; font-size: {font_size_a}; color: #00ff00; + font-weight: bold; background: {color_g}; + border-radius: 5px; padding: 4px 8px; +""" diff --git a/portprotonqt/themes/standart/styles/settings.py b/portprotonqt/themes/standart/styles/settings.py new file mode 100644 index 0000000..cfff111 --- /dev/null +++ b/portprotonqt/themes/standart/styles/settings.py @@ -0,0 +1,111 @@ +from .constants import * + +SETTINGS_COMBO_STYLE = f""" + QComboBox {{ + background: {color_c}; + border: {border_c} {color_g}; + border-radius: {border_radius_a}; + height: 34px; + padding-left: 12px; + color: {color_f}; + font-family: '{font_family}'; + font-size: {font_size_a}; + min-width: 120px; + combobox-popup: 0; + }} + QComboBox:on {{ + background: {color_b}; + border: {border_c} {color_a}; + border-bottom-style: none; + border-top-left-radius: 10px; + border-top-right-radius: 10px; + border-bottom-left-radius: 0px; + border-bottom-right-radius: 0px; + }} + QComboBox:hover {{ + border: {border_c} {color_a}; + background: {color_a}; + }} + /* Состояние фокуса */ + QComboBox:focus {{ + border: {border_c} {color_a}; + background-color: {color_a}; + }} + QComboBox::drop-down {{ + subcontrol-origin: padding; + subcontrol-position: center right; + border-left: {border_b} rgba(255, 255, 255, 0.05); + 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: {border_c} {color_a}; + border-top-style: none; + border-top-left-radius: 0px; + border-top-right-radius: 0px; + border-bottom-left-radius: 10px; + border-bottom-right-radius: 10px; + }} + QListView {{ + background: {color_c}; + }} + QListView::item {{ + padding: 7px 7px 7px 12px; + margin: 3px; + border-radius: {border_radius_a}; + color: {color_f}; + }} + QListView::item:hover {{ + background: {color_b}; + }} + QListView::item:selected {{ + background: {color_b}; + }} + /* Выделение в списке при фокусе на элементе */ + QListView::item:focus {{ + background: {color_a}; + color: {color_f}; + }} +""" + +SETTINGS_CHECKBOX_STYLE = f""" + QCheckBox {{ + height: 34px; + color: {color_f}; + font-family: '{font_family}'; + font-size: {font_size_a}; + }} + QCheckBox::indicator {{ + width: 24px; + height: 24px; + border: {border_c} {color_g}; + border-radius: {border_radius_a}; + background: {color_b}; + }} + QCheckBox::indicator:hover {{ + background: {color_c}; + border: {border_c} {color_a}; + }} + QCheckBox::indicator:focus {{ + border: {border_c} {color_a}; + }} + QCheckBox::indicator:checked {{ + image: url({theme_manager.get_icon("check", current_theme_name, as_path=True)}); + border: {border_c} {color_a}; + }} +""" diff --git a/portprotonqt/themes/standart/styles/theme_utils.py b/portprotonqt/themes/standart/styles/theme_utils.py new file mode 100644 index 0000000..16a9104 --- /dev/null +++ b/portprotonqt/themes/standart/styles/theme_utils.py @@ -0,0 +1,84 @@ +from .constants import * + +CONTEXT_MENU_STYLE = f""" + QMenu {{ + background: {color_b}; + color: {color_f}; + font-family: '{font_family}'; + font-size: {font_size_a}; + padding: 5px; + min-width: 150px; + }} + QMenu::icon {{ + margin-left: 15px; + }} + QMenu::item {{ + padding: 10px 20px 10px 10px; + background: {color_h}; + border-radius: {border_radius_a}; + color: {color_f}; + }} + QMenu::item:selected {{ + background: {color_a}; + color: {color_f}; + }} + QMenu::item:disabled {{ + color: #7f7f7f; + }} + QMenu::item:hover {{ + background: {color_a}; + color: {color_f}; + }} + QMenu::item:focus {{ + background: {color_a}; + color: {color_f}; + border: {border_b} rgba(255, 255, 255, 0.3); + border-radius: {border_radius_a}; + }} + QMenu::separator {{ + height: 1px; + background-color: #7f7f7f; + margin: 3px 6px; + }} +""" + +VIRTUAL_KEYBOARD_STYLE = f""" +QWidget {{ + background: {color_i}; +}} +QPushButton {{ + font-size: 14px; + border: {border_a} {color_h}; + border-radius: {border_radius_a}; + min-width: 30px; + min-height: 30px; + padding: 5px; + background-color: {color_c}; + color: {color_f}; +}} +QPushButton:hover {{ + background-color: {color_a}; + border: {border_b} {color_a}; +}} +QPushButton:focus {{ + border: {border_b} {color_a}; + background-color: {color_a}; +}} +QPushButton:pressed {{ + background-color: {color_c}; + border: {border_a} {color_h}; +}} +QPushButton[checked="true"] {{ + background-color: {color_a}; + color: {color_f}; + border: {border_a} {color_h}; +}} +QPushButton[checked="true"]:focus {{ + border: {border_b} {color_f}; +}} +""" + +# СТИЛИ ПОЛНОЭКРАНОГО ПРЕВЬЮ СКРИНШОТОВ ТЕМЫ +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=f"color: white; font-size: {font_size_a};" diff --git a/portprotonqt/themes/standart/styles/winetricks.py b/portprotonqt/themes/standart/styles/winetricks.py new file mode 100644 index 0000000..272e341 --- /dev/null +++ b/portprotonqt/themes/standart/styles/winetricks.py @@ -0,0 +1,317 @@ +from .constants import * + +WINETRICKS_TAB_STYLE = f""" +QTabWidget::pane {{ + border-top: 1px solid {color_c}; + background: {color_h}; +}} +QTabBar::tab {{ + background: {color_c}; + color: {color_f}; + padding: 8px 16px; + border-top-left-radius: {border_radius_a}; + border-top-right-radius: {border_radius_a}; + margin-right: 2px; +}} +QTabBar::tab:selected {{ + background: {color_a}; + color: {color_f}; +}} +QTabBar::tab:hover {{ + background: {color_a}; +}} +""" + +WINETRICKS_TABBLE_STYLE = f""" +QComboBox {{ + background: {color_c}; + border: {border_c} {color_g}; + border-radius: {border_radius_a}; + padding-left: 12px; + color: {color_f}; + font-family: '{font_family}'; + font-size: {font_size_a}; + min-width: 120px; + combobox-popup: 0; +}} +QComboBox:on {{ + background: {color_b}; + border: {border_c} {color_a}; + border-bottom-style: none; + border-top-left-radius: 10px; + border-top-right-radius: 10px; + border-bottom-left-radius: 0px; + border-bottom-right-radius: 0px; +}} +QComboBox:hover {{ + border: {border_c} {color_a}; + background: {color_a}; +}} +/* Состояние фокуса */ +QComboBox:focus {{ + border: {border_c} {color_a}; + background-color: {color_a}; +}} +QComboBox:disabled {{ + background: #2a2c35; + border: {border_c} #2a2c35; + color: #777a84; +}} +QComboBox::drop-down {{ + subcontrol-origin: padding; + subcontrol-position: center right; + border-left: {border_b} rgba(255, 255, 255, 0.05); + 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; + background: {color_c}; + border: {border_c} {color_a}; + border-top-style: none; + border-top-left-radius: 0px; + border-top-right-radius: 0px; + border-bottom-left-radius: 10px; + border-bottom-right-radius: 10px; +}} +QListView {{ + background: {color_c}; +}} +QListView::item {{ + padding: 7px 7px 7px 12px; + margin: 3px; + border-radius: {border_radius_a}; + color: {color_f}; +}} +QListView::item:hover {{ + background: {color_b}; +}} +QListView::item:selected {{ + background: {color_b}; +}} +/* Выделение в списке при фокусе на элементе */ +QListView::item:focus {{ + background: {color_a}; + color: {color_f}; +}} +QLineEdit {{ + background: {color_c}; + border: {border_c} rgba(255, 255, 255, 0.01); + border-radius: {border_radius_a}; + height: 34px; + padding-left: 12px; + color: {color_f}; + font-family: '{font_family}'; + font-size: {font_size_a}; +}} +QLineEdit:hover {{ + background: {color_c}; + border: {border_c} {color_a}; +}} +QLineEdit:focus {{ + border: {border_c} {color_a}; + background-color: {color_e}; +}} +QTableWidget {{ + background: {color_h}; + color: {color_f}; + gridline-color: {color_h}; + alternate-background-color: {color_d}; + border: {border_a}; + border-radius: {border_radius_a}; + font-family: '{font_family}'; + font-size: {font_size_a}; +}} +QHeaderView::section {{ + background: {color_d}; + color: {color_f}; + padding: 5px; + border: {border_a}; + font-weight: bold; +}} +QTableWidget::item {{ + padding: 8px; + border-bottom: {border_a } {color_c}; + height: 36px; +}} +QTableWidget::item:selected, +QTableWidget::item:focus, +QTableWidget::item:selected:focus {{ + background: {color_a}; + color: {color_f}; + selection-background-color: {color_a}; +}} +QTableWidget::item:hover {{ + background: {color_h}; +}} +QTableWidget::indicator {{ + width: 24px; + height: 24px; + border: {border_c} {color_h}; + border-radius: {border_radius_a}; + background: {color_b}; +}} +QTableWidget::indicator:unchecked {{ + background: rgba(255, 255, 255, 0.1); + image: none; +}} +QTableWidget::indicator:checked {{ + background: {color_b}; + image: url({theme_manager.get_icon("check", current_theme_name, as_path=True)}); + border: {border_c} {color_a}; +}} +QTableWidget::indicator:hover {{ + background: rgba(255, 255, 255, 0.2); + border: {border_c} {color_a}; +}} +QTableWidget::indicator:focus {{ + background: rgba(255, 255, 255, 0.2); + border: {border_c} {color_a}; +}} +QScrollBar:vertical {{ + width: 10px; + border: {border_a}; + border-radius: 5px; + background: rgba(20, 20, 20, 0.30); +}} +QScrollBar::handle:vertical {{ + background: #bebebe; + border: {border_a}; + border-radius: 5px; +}} +QScrollBar::add-line:vertical {{ + border: {border_a}; + background: none; +}} +QScrollBar::sub-line:vertical {{ + border: {border_a}; + background: none; +}} +QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical {{ + border: {border_a}; + width: 3px; + height: 3px; + background: none; +}} +QScrollBar:horizontal {{ + height: 10px; + border: {border_a}; + border-radius: 5px; + background: rgba(20, 20, 20, 0.30); +}} +QScrollBar::handle:horizontal {{ + background: #bebebe; + border: {border_a}; + border-radius: 5px; +}} +QScrollBar::add-line:horizontal {{ + border: {border_a}; + background: none; +}} +QScrollBar::sub-line:horizontal {{ + border: {border_a}; + background: none; +}} +QScrollBar::up-arrow:horizontal, QScrollBar::down-arrow:horizontal {{ + border: {border_a}; + width: 3px; + height: 3px; + background: none; +}} +""" + +WINETRICKS_LOG_STYLE = f""" +QTextEdit {{ + background: {color_c}; + border: {border_a}; + border-radius: {border_radius_a}; + color: {color_f}; + font-family: '{font_family}'; + font-size: {font_size_a}; + padding: 5px; +}} +""" + +FILE_EXPLORER_STYLE = f""" + QListView {{ + font-size: {font_size_a}; + font-family: {font_family}; + background: {color_c}; + alternate-background-color: {color_c}; + color: {color_f}; + border-top-left-radius: 5px; + border-bottom-left-radius: 5px; + }} + QListView::item {{ + padding: 8px; + margin: 0px 5px; + }} + QListView::item:alternate {{ + margin: 0px 5px; + background: {color_d}; + }} + QListView::item:selected {{ + background: {color_a}; + color: {color_f}; + border-radius: {border_radius_a}; + }} + QListView::item:hover {{ + background: {color_a}; + color: {color_f}; + border-radius: {border_radius_a}; + }} + QListView::item:focus {{ + background: {color_a}; + color: {color_f}; + border-radius: {border_radius_a}; + }} + QScrollBar:vertical {{ + width: 10px; + border: {border_a}; + border-radius: 5px; + background: {color_c}; + }} + QScrollBar::handle:vertical {{ + background: #bebebe; + border: {border_a}; + border-radius: 5px; + }} + QScrollBar::add-line:vertical {{ + border: {border_a}; + background: {color_c}; + border-bottom-right-radius: 5px; + }} + QScrollBar::sub-line:vertical {{ + border: {border_a}; + background: {color_c}; + border-top-right-radius: 5px; + }} + QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical {{ + border: {border_a}; + width: 3px; + height: 3px; + background: none; + }} +""" + +FILE_EXPLORER_PATH_LABEL_STYLE = f""" + QLabel {{ + color: {color_a}; + font-size: {font_size_a}; + font-family: {font_family}; + }} +"""