Compare commits

..

14 Commits

Author SHA1 Message Date
Your Name
437ac74dba update design dev_screen 2026-01-09 05:39:32 +03:00
Your Name
dcd1b58000 update design dev_screen 2026-01-09 05:19:55 +03:00
Your Name
dfdc791d07 update design dev_screen 2026-01-09 05:17:20 +03:00
Your Name
ecfce9dfcd update design dev_screen 2026-01-09 05:03:25 +03:00
Your Name
d2ace417f3 update design dev_screen 2026-01-09 05:01:03 +03:00
Your Name
b15631339a update design dev_screen 2026-01-09 04:51:32 +03:00
Your Name
7a70203b3d update design dev_screen 2026-01-09 04:49:16 +03:00
Your Name
e2d592d27d update design dev_screen 2026-01-09 04:46:53 +03:00
Your Name
48f2f7e103 update design dev_screen 2026-01-09 04:43:25 +03:00
Your Name
55351a0eb6 update design dev_screen 2026-01-09 04:41:39 +03:00
Your Name
6742269948 update design dev_screen 2026-01-09 04:39:54 +03:00
Your Name
ea943dedbd update design dev_screen 2026-01-09 04:36:44 +03:00
Your Name
3d9230c679 change button location 2026-01-09 04:33:58 +03:00
Your Name
f80cbf7c6e change button location 2026-01-09 04:32:08 +03:00
11 changed files with 233 additions and 126 deletions

2
app.py
View File

@ -49,8 +49,6 @@ def _apply_startup_display_defaults():
settings.setValue("display/brightness", 70) settings.setValue("display/brightness", 70)
if not settings.contains("display/auto_brightness"): if not settings.contains("display/auto_brightness"):
settings.setValue("display/auto_brightness", False) settings.setValue("display/auto_brightness", False)
if not settings.contains("display/sleep_minutes"):
settings.setValue("display/sleep_minutes", 10)
if not settings.contains("display/theme"): if not settings.contains("display/theme"):
settings.setValue("display/theme", "night") settings.setValue("display/theme", "night")

View File

@ -86,6 +86,13 @@ class AboutScreen(QWidget):
self.dev_unlocked.emit() self.dev_unlocked.emit()
self.dev_is_unlocked = True self.dev_is_unlocked = True
def showEvent(self, event):
if not self.dev_is_unlocked:
self._dev_taps = 0
if self._build_row is not None:
self._build_row.set_suffix("")
super().showEvent(event)
class _InfoRow(QWidget): class _InfoRow(QWidget):
clicked = Signal() clicked = Signal()

View File

@ -1,7 +1,7 @@
from pathlib import Path from pathlib import Path
import subprocess import subprocess
from PySide6.QtCore import Qt from PySide6.QtCore import Qt, QSettings
from PySide6.QtGui import QFont from PySide6.QtGui import QFont
from PySide6.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel from PySide6.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel
@ -16,6 +16,7 @@ def build_dev_screen(on_exit) -> QWidget:
layout.setSpacing(12) layout.setSpacing(12)
layout.addWidget(_build_persist_toggle()) layout.addWidget(_build_persist_toggle())
layout.addWidget(_build_sound_toggles())
hdr = QHBoxLayout() hdr = QHBoxLayout()
hdr.setContentsMargins(0, 0, 0, 0) hdr.setContentsMargins(0, 0, 0, 0)
@ -27,13 +28,19 @@ def build_dev_screen(on_exit) -> QWidget:
exit_btn.clicked.connect(lambda: _confirm_exit(on_exit)) exit_btn.clicked.connect(lambda: _confirm_exit(on_exit))
reboot_btn = QPushButton("Выполнить перезагрузку") reboot_btn = QPushButton("Выполнить перезагрузку")
reboot_btn.setObjectName("DevExitBtn") reboot_btn.setObjectName("DevRebootBtn")
reboot_btn.setMinimumHeight(72) reboot_btn.setMinimumHeight(72)
reboot_btn.clicked.connect(_confirm_reboot) reboot_btn.clicked.connect(_confirm_reboot)
reset_btn = QPushButton("Сброс до заводских")
reset_btn.setObjectName("DevResetBtn")
reset_btn.setMinimumHeight(72)
reset_btn.clicked.connect(_confirm_factory_reset)
layout.addLayout(hdr) layout.addLayout(hdr)
layout.addWidget(exit_btn) layout.addWidget(exit_btn)
layout.addWidget(reboot_btn) layout.addWidget(reboot_btn)
layout.addWidget(reset_btn)
layout.addStretch(1) layout.addStretch(1)
return screen return screen
@ -76,6 +83,83 @@ def _build_persist_toggle() -> QWidget:
return row return row
def _build_sound_toggles() -> QWidget:
settings = QSettings("car_ui", "ui")
container = QWidget()
layout = QVBoxLayout(container)
layout.setContentsMargins(12, 6, 12, 6)
layout.setSpacing(8)
layout.addWidget(
_toggle_row(
"Премут",
settings,
"sound/premute_enabled",
False,
)
)
layout.addWidget(
_toggle_row(
"Ducking",
settings,
"sound/ducking_enabled",
False,
)
)
return container
def _toggle_row(
label: str,
settings: QSettings,
key: str,
default: bool,
) -> QWidget:
row = QWidget()
layout = QHBoxLayout(row)
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(12)
lbl = QLabel(label)
lbl.setFont(QFont("", 13, 600))
btn = QPushButton("Выкл")
btn.setObjectName("SoundToggle")
btn.setCheckable(True)
btn.setChecked(_read_bool_setting(settings, key, default))
btn.setMinimumHeight(40)
btn.setMinimumWidth(110)
btn.setFont(QFont("", 12, 700))
def _sync_text(is_checked: bool):
btn.setText("Вкл" if is_checked else "Выкл")
def _persist_flag(is_checked: bool):
settings.setValue(key, is_checked)
btn.toggled.connect(_sync_text)
btn.toggled.connect(_persist_flag)
_sync_text(btn.isChecked())
layout.addWidget(lbl)
layout.addStretch(1)
layout.addWidget(btn)
return row
def _read_bool_setting(settings: QSettings, key: str, default: bool) -> bool:
raw = settings.value(key, default)
if isinstance(raw, bool):
return raw
if isinstance(raw, str):
return raw.strip().lower() in ("1", "true", "yes", "on")
try:
return bool(int(raw))
except (TypeError, ValueError):
return default
def _dev_flag_path() -> Path: def _dev_flag_path() -> Path:
return Path(build_info.__file__).resolve().parent / "dev_mode_enable" return Path(build_info.__file__).resolve().parent / "dev_mode_enable"
@ -95,6 +179,20 @@ def _confirm_reboot():
"Подтверждение", "Подтверждение",
"Выполнить перезагрузку устройства?", "Выполнить перезагрузку устройства?",
"Перезагрузить", "Перезагрузить",
ok_object_name="ConfirmOkDanger",
) )
if dialog.exec() == ConfirmDialog.Accepted: if dialog.exec() == ConfirmDialog.Accepted:
subprocess.run(["sudo", "reboot"], check=False) subprocess.run(["sudo", "reboot"], check=False)
def _confirm_factory_reset():
dialog = ConfirmDialog(
"Подтверждение",
"Сбросить настройки до заводских? Приложение будет закрыто.",
"Сбросить",
ok_object_name="ConfirmOkDanger",
)
if dialog.exec() == ConfirmDialog.Accepted:
reset_marker = Path(build_info.__file__).resolve().parent / "reset"
reset_marker.touch(exist_ok=True)
subprocess.run(["sudo", "reboot"], check=False)

View File

@ -42,7 +42,6 @@ class DisplayScreen(QWidget):
content_layout.setSpacing(12) content_layout.setSpacing(12)
content_layout.addWidget(self._build_brightness_card()) content_layout.addWidget(self._build_brightness_card())
content_layout.addWidget(self._build_sleep_card())
content_layout.addWidget(self._build_theme_card()) content_layout.addWidget(self._build_theme_card())
content_layout.addStretch(1) content_layout.addStretch(1)
@ -59,7 +58,7 @@ class DisplayScreen(QWidget):
) )
row_toggle, toggle_btn = _toggle_row( row_toggle, toggle_btn = _toggle_row(
"Автояркость", "Автояркость (не работает)",
checked=auto_brightness, checked=auto_brightness,
) )
row_slider, slider, value_label = _slider_row( row_slider, slider, value_label = _slider_row(
@ -83,26 +82,6 @@ class DisplayScreen(QWidget):
body.addWidget(row_slider) body.addWidget(row_slider)
return card return card
def _build_sleep_card(self) -> QWidget:
card, body = _card("Сон")
sleep_minutes = _read_int_setting(
self._settings,
"display/sleep_minutes",
10,
)
row, slider, value_label = _slider_row(
"Отключать экран через",
0,
30,
sleep_minutes,
_format_sleep_minutes,
)
slider.valueChanged.connect(
lambda v: self._settings.setValue("display/sleep_minutes", v)
)
body.addWidget(row)
return card
def _build_theme_card(self) -> QWidget: def _build_theme_card(self) -> QWidget:
card, body = _card("Тема") card, body = _card("Тема")
row = QWidget() row = QWidget()

View File

@ -47,8 +47,6 @@ class SoundScreen(QWidget):
content_layout.setSpacing(12) content_layout.setSpacing(12)
content_layout.addWidget(self._build_volume_card()) content_layout.addWidget(self._build_volume_card())
content_layout.addWidget(self._build_premute_card())
content_layout.addWidget(self._build_ducking_card())
content_layout.addWidget(self._build_balance_card()) content_layout.addWidget(self._build_balance_card())
content_layout.addWidget(self._build_tone_card()) content_layout.addWidget(self._build_tone_card())
content_layout.addWidget(self._build_eq_card()) content_layout.addWidget(self._build_eq_card())
@ -90,56 +88,8 @@ class SoundScreen(QWidget):
body.addWidget(row) body.addWidget(row)
return card return card
def _build_premute_card(self) -> QWidget:
card, body = _card("Премут")
premute_enabled = False
premute_value = self._read_int(
"sound/premute_volume",
build_info.DEFAULT_PREMUTE_VOLUME,
)
row_toggle, toggle_btn = _toggle_row("Премут", checked=premute_enabled)
row_slider, slider, value_label = _slider_row(
"Громкость премут",
0,
100,
premute_value,
lambda v: f"{v}%",
)
slider.valueChanged.connect(
lambda v: self._settings.setValue("sound/premute_volume", v)
)
body.addWidget(row_toggle)
body.addWidget(row_slider)
return card
def _build_ducking_card(self) -> QWidget:
card, body = _card("Ducking")
ducking_enabled = True
ducking_value = self._read_int(
"sound/ducking_volume",
build_info.DEFAULT_DUCKING_VOLUME,
)
row_toggle, toggle_btn = _toggle_row("Ducking", checked=ducking_enabled)
row_slider, slider, value_label = _slider_row(
"Громкость при Ducking",
0,
100,
ducking_value,
lambda v: f"{v}%",
)
slider.valueChanged.connect(
lambda v: self._settings.setValue("sound/ducking_volume", v)
)
body.addWidget(row_toggle)
body.addWidget(row_slider)
return card
def _build_balance_card(self) -> QWidget: def _build_balance_card(self) -> QWidget:
card, body = _card("Баланс и фейдер") card, body = _card("Баланс и фейдер (не работает)")
row, slider, value_label = _slider_row( row, slider, value_label = _slider_row(
"Баланс L/R", "Баланс L/R",
-50, -50,
@ -159,7 +109,7 @@ class SoundScreen(QWidget):
return card return card
def _build_tone_card(self) -> QWidget: def _build_tone_card(self) -> QWidget:
card, body = _card("Тон") card, body = _card("Тон (не работает)")
row = QWidget() row = QWidget()
row.setObjectName("SoundToneRow") row.setObjectName("SoundToneRow")
layout = QHBoxLayout(row) layout = QHBoxLayout(row)
@ -184,7 +134,7 @@ class SoundScreen(QWidget):
return card return card
def _build_eq_card(self) -> QWidget: def _build_eq_card(self) -> QWidget:
card, body = _card("Эквалайзер") card, body = _card("Эквалайзер (не работает)")
btn = QPushButton("Открыть эквалайзер") btn = QPushButton("Открыть эквалайзер")
btn.setObjectName("SoundEqBtn") btn.setObjectName("SoundEqBtn")
btn.setMinimumHeight(48) btn.setMinimumHeight(48)
@ -209,36 +159,6 @@ def _card(title: str) -> tuple[QWidget, QVBoxLayout]:
return card, layout return card, layout
def _toggle_row(label: str, checked: bool) -> tuple[QWidget, QPushButton]:
row = QWidget()
row.setObjectName("SoundToggleRow")
layout = QHBoxLayout(row)
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(12)
lbl = QLabel(label)
lbl.setFont(QFont("", 13, 600))
btn = QPushButton("Выкл")
btn.setObjectName("SoundToggle")
btn.setCheckable(True)
btn.setChecked(checked)
btn.setMinimumHeight(36)
btn.setMinimumWidth(86)
btn.setFont(QFont("", 12, 700))
def _sync_text(is_checked: bool):
btn.setText("Вкл" if is_checked else "Выкл")
btn.toggled.connect(_sync_text)
_sync_text(btn.isChecked())
layout.addWidget(lbl)
layout.addStretch(1)
layout.addWidget(btn)
return row, btn
def _slider_row( def _slider_row(
label: str, label: str,
minimum: int, minimum: int,
@ -299,4 +219,3 @@ def _read_int_setting(settings: QSettings, key: str, default: int) -> int:
return int(raw) return int(raw)
except (TypeError, ValueError): except (TypeError, ValueError):
return default return default

View File

@ -9,7 +9,7 @@ from PySide6.QtWidgets import (
QStackedWidget, QStackedWidget,
QApplication, QApplication,
) )
from PySide6.QtCore import Qt, Signal from PySide6.QtCore import Qt, Signal, QSettings
from PySide6.QtGui import QFont from PySide6.QtGui import QFont
from PySide6.QtWidgets import QScroller from PySide6.QtWidgets import QScroller
from screens.setting.bluetooth_screen import BluetoothScreen from screens.setting.bluetooth_screen import BluetoothScreen
@ -19,6 +19,7 @@ from screens.setting.sound_screen import SoundScreen
from screens.setting.eq_screen import EqualizerScreen from screens.setting.eq_screen import EqualizerScreen
from screens.setting.display_screen import DisplayScreen from screens.setting.display_screen import DisplayScreen
import build_info import build_info
from ui.language_dialog import LanguageDialog
class SettingsRow(QPushButton): class SettingsRow(QPushButton):
@ -69,7 +70,7 @@ class SettingsScreen(QWidget):
self._dev_enabled = build_info.DEV_MODE_ENABLE self._dev_enabled = build_info.DEV_MODE_ENABLE
self._dev_row: SettingsRow | None = None self._dev_row: SettingsRow | None = None
root = QVBoxLayout(self) root = QVBoxLayout(self)
root.setContentsMargins(18, 16, 18, 16) root.setContentsMargins(18, 0, 18, 16)
root.setSpacing(12) root.setSpacing(12)
self.stack = QStackedWidget() self.stack = QStackedWidget()
@ -116,17 +117,29 @@ class SettingsScreen(QWidget):
content_layout, content_layout,
"Дисплей и звук", "Дисплей и звук",
[ [
("Экран", "Яркость, сон, тема"), ("Экран", "Яркость, тема"),
("Звук", "Громкость, эквалайзер"), ("Звук", "Громкость, эквалайзер"),
("Язык", "Выбор языка интерфейса"),
], ],
) )
display_row = display_rows.get("Экран") display_row = display_rows.get("Экран")
sound_row = display_rows.get("Звук") sound_row = display_rows.get("Звук")
language_row = display_rows.get("Язык")
self._add_section(
content_layout,
"Данные",
[
("Хранилище данных", "Размер пользовательских данных и очистка"),
("Yobble", "Авторизация и связанные устройства"),
],
)
system_rows = self._add_section( system_rows = self._add_section(
content_layout, content_layout,
"Система", "Система",
[ [
("Обновление системы", "Проверка и установка обновлений"),
("Об устройстве", "Версия, память, серийный номер"), ("Об устройстве", "Версия, память, серийный номер"),
("Параметры разработчика", "Отладка и логирование"), ("Параметры разработчика", "Отладка и логирование"),
], ],
@ -167,6 +180,8 @@ class SettingsScreen(QWidget):
display_row.clicked.connect(self._show_display) display_row.clicked.connect(self._show_display)
if sound_row is not None: if sound_row is not None:
sound_row.clicked.connect(self._show_sound) sound_row.clicked.connect(self._show_sound)
if language_row is not None:
language_row.clicked.connect(self._show_language)
self._show_list() self._show_list()
def _add_section( def _add_section(
@ -219,6 +234,12 @@ class SettingsScreen(QWidget):
self.stack.setCurrentWidget(self._eq_screen) self.stack.setCurrentWidget(self._eq_screen)
self.view_changed.emit("Эквалайзер", True) self.view_changed.emit("Эквалайзер", True)
def _show_language(self):
dialog = LanguageDialog()
if dialog.exec() == LanguageDialog.Accepted:
settings = QSettings("car_ui", "ui")
settings.setValue("ui/language", dialog.selected_language())
def _exit_app(self): def _exit_app(self):
app = QApplication.instance() app = QApplication.instance()
if app is not None: if app is not None:

View File

@ -1,6 +1,7 @@
THEME_DAY = """ THEME_DAY = """
QWidget { background: #F4F6F8; color: #111827; } QWidget { background: #F4F6F8; color: #111827; }
#TopBar, #BottomBar { background: #FFFFFF; } #TopBar, #BottomBar { background: #FFFFFF; }
#TopBar QLabel { background: transparent; }
#Divider { background: #E5E7EB; } #Divider { background: #E5E7EB; }
#MenuButton, #SettingsButton { #MenuButton, #SettingsButton {
@ -51,8 +52,19 @@ QMenu::item:selected { background: #F3F4F6; }
border-radius: 14px; border-radius: 14px;
border: 1px solid #E5E7EB; border: 1px solid #E5E7EB;
} }
#SoundCardTitle { color: rgba(55,65,81,0.9); } #SoundCard QLabel { background: transparent; }
#SoundValue { color: rgba(107,114,128,0.95); } #SoundToggleRow { background: transparent; }
#SoundSliderRow { background: transparent; }
#SoundSliderRow QWidget { background: transparent; }
#SoundToggleRow QPushButton { background-clip: padding; }
#SoundSliderRow QSlider { background: transparent; }
QScrollArea { background: transparent; }
QScrollArea::viewport { background: transparent; }
QScrollArea > QWidget > QWidget { background: transparent; }
#SoundCardTitle { color: rgba(55,65,81,0.9); background: transparent; }
#SoundValue { color: rgba(107,114,128,0.95); background: transparent; }
#SoundToggleRow QLabel { background: transparent; }
#SoundSliderRow QLabel { background: transparent; }
#SoundSlider::groove:horizontal { height: 8px; background: #E5E7EB; border-radius: 4px; } #SoundSlider::groove:horizontal { height: 8px; background: #E5E7EB; border-radius: 4px; }
#SoundSlider::handle:horizontal { width: 18px; margin: -6px 0; background: #111827; border-radius: 9px; } #SoundSlider::handle:horizontal { width: 18px; margin: -6px 0; background: #111827; border-radius: 9px; }
#SoundToggle { #SoundToggle {
@ -101,6 +113,24 @@ QMenu::item:selected { background: #F3F4F6; }
font-weight: 600; font-weight: 600;
} }
#DevExitBtn:hover { background: #E5E7EB; } #DevExitBtn:hover { background: #E5E7EB; }
#DevRebootBtn {
background: #FEE2E2;
color: #991B1B;
border-radius: 14px;
border: 1px solid #FCA5A5;
font-size: 16px;
font-weight: 700;
}
#DevRebootBtn:hover { background: #FECACA; }
#DevResetBtn {
background: #FEE2E2;
color: #991B1B;
border-radius: 14px;
border: 1px solid #FCA5A5;
font-size: 16px;
font-weight: 700;
}
#DevResetBtn:hover { background: #FECACA; }
#BluetoothStatus { color: rgba(107,114,128,0.95); } #BluetoothStatus { color: rgba(107,114,128,0.95); }
#BluetoothList { #BluetoothList {
@ -191,14 +221,14 @@ QMenu::item:selected { background: #F3F4F6; }
} }
#LanguageConfirm:hover { background: #0B1220; } #LanguageConfirm:hover { background: #0B1220; }
#ConfirmDialog { background: #F4F6F8; } #ConfirmDialog { background: transparent; }
#ConfirmCard { #ConfirmCard {
background: #FFFFFF; background: #FFFFFF;
border-radius: 16px; border-radius: 16px;
border: 1px solid #E5E7EB; border: 1px solid #E5E7EB;
} }
#ConfirmTitle { color: #111827; } #ConfirmTitle { color: #111827; background: transparent; }
#ConfirmMessage { color: rgba(107,114,128,0.95); } #ConfirmMessage { color: rgba(107,114,128,0.95); background: transparent; }
#ConfirmCancel { #ConfirmCancel {
background: #FFFFFF; background: #FFFFFF;
color: #111827; color: #111827;
@ -214,4 +244,12 @@ QMenu::item:selected { background: #F3F4F6; }
padding: 8px 14px; padding: 8px 14px;
} }
#ConfirmOk:hover { background: #0B1220; } #ConfirmOk:hover { background: #0B1220; }
#ConfirmOkDanger {
background: #DC2626;
color: #FFFFFF;
border-radius: 12px;
padding: 8px 14px;
font-weight: 700;
}
#ConfirmOkDanger:hover { background: #B91C1C; }
""" """

View File

@ -1,6 +1,7 @@
THEME_NIGHT = """ THEME_NIGHT = """
QWidget { background: #0B0E11; color: #E6EAF0; } QWidget { background: #0B0E11; color: #E6EAF0; }
#TopBar, #BottomBar { background: #0F1318; } #TopBar, #BottomBar { background: #0F1318; }
#TopBar QLabel { background: transparent; }
#Divider { background: #1B2330; } #Divider { background: #1B2330; }
#MenuButton, #SettingsButton { #MenuButton, #SettingsButton {
@ -47,8 +48,19 @@ QMenu::item:selected { background: #1B2330; }
background: #141A22; background: #141A22;
border-radius: 14px; border-radius: 14px;
} }
#SoundCardTitle { color: rgba(138,147,166,0.95); } #SoundCard QLabel { background: transparent; }
#SoundValue { color: rgba(138,147,166,0.95); } #SoundToggleRow { background: transparent; }
#SoundSliderRow { background: transparent; }
#SoundSliderRow QWidget { background: transparent; }
#SoundToggleRow QPushButton { background-clip: padding; }
#SoundSliderRow QSlider { background: transparent; }
QScrollArea { background: transparent; }
QScrollArea::viewport { background: transparent; }
QScrollArea > QWidget > QWidget { background: transparent; }
#SoundCardTitle { color: rgba(138,147,166,0.95); background: transparent; }
#SoundValue { color: rgba(138,147,166,0.95); background: transparent; }
#SoundToggleRow QLabel { background: transparent; }
#SoundSliderRow QLabel { background: transparent; }
#SoundSlider::groove:horizontal { height: 8px; background: #1B2330; border-radius: 4px; } #SoundSlider::groove:horizontal { height: 8px; background: #1B2330; border-radius: 4px; }
#SoundSlider::handle:horizontal { width: 18px; margin: -6px 0; background: #E6EAF0; border-radius: 9px; } #SoundSlider::handle:horizontal { width: 18px; margin: -6px 0; background: #E6EAF0; border-radius: 9px; }
#SoundToggle { #SoundToggle {
@ -93,6 +105,22 @@ QMenu::item:selected { background: #1B2330; }
font-weight: 600; font-weight: 600;
} }
#DevExitBtn:hover { background: #263142; } #DevExitBtn:hover { background: #263142; }
#DevRebootBtn {
background: #7F1D1D;
color: #FEE2E2;
border-radius: 14px;
font-size: 16px;
font-weight: 700;
}
#DevRebootBtn:hover { background: #991B1B; }
#DevResetBtn {
background: #7F1D1D;
color: #FEE2E2;
border-radius: 14px;
font-size: 16px;
font-weight: 700;
}
#DevResetBtn:hover { background: #991B1B; }
#BluetoothStatus { color: rgba(138,147,166,0.95); } #BluetoothStatus { color: rgba(138,147,166,0.95); }
#BluetoothList { #BluetoothList {
@ -177,13 +205,13 @@ QMenu::item:selected { background: #1B2330; }
} }
#LanguageConfirm:hover { background: #344968; } #LanguageConfirm:hover { background: #344968; }
#ConfirmDialog { background: #0B0E11; } #ConfirmDialog { background: transparent; }
#ConfirmCard { #ConfirmCard {
background: #141A22; background: #141A22;
border-radius: 16px; border-radius: 16px;
} }
#ConfirmTitle { color: #E6EAF0; } #ConfirmTitle { color: #E6EAF0; background: transparent; }
#ConfirmMessage { color: rgba(138,147,166,0.95); } #ConfirmMessage { color: rgba(138,147,166,0.95); background: transparent; }
#ConfirmCancel { #ConfirmCancel {
background: #141A22; background: #141A22;
color: #E6EAF0; color: #E6EAF0;
@ -199,4 +227,12 @@ QMenu::item:selected { background: #1B2330; }
padding: 8px 14px; padding: 8px 14px;
} }
#ConfirmOk:hover { background: #344968; } #ConfirmOk:hover { background: #344968; }
#ConfirmOkDanger {
background: #B91C1C;
color: #FEE2E2;
border-radius: 12px;
padding: 8px 14px;
font-weight: 700;
}
#ConfirmOkDanger:hover { background: #DC2626; }
""" """

View File

@ -13,11 +13,18 @@ from PySide6.QtWidgets import (
class ConfirmDialog(QDialog): class ConfirmDialog(QDialog):
def __init__(self, title: str, message: str, confirm_text: str): def __init__(
self,
title: str,
message: str,
confirm_text: str,
ok_object_name: str | None = None,
):
super().__init__() super().__init__()
self.setObjectName("ConfirmDialog") self.setObjectName("ConfirmDialog")
self.setWindowFlags(Qt.FramelessWindowHint | Qt.Dialog) self.setWindowFlags(Qt.FramelessWindowHint | Qt.Dialog)
self.setWindowModality(Qt.ApplicationModal) self.setWindowModality(Qt.ApplicationModal)
self.setAttribute(Qt.WA_TranslucentBackground)
self.setMinimumSize(QSize(1024, 600)) self.setMinimumSize(QSize(1024, 600))
root = QVBoxLayout(self) root = QVBoxLayout(self)
@ -52,7 +59,7 @@ class ConfirmDialog(QDialog):
cancel_btn.clicked.connect(self.reject) cancel_btn.clicked.connect(self.reject)
ok_btn = QPushButton(confirm_text) ok_btn = QPushButton(confirm_text)
ok_btn.setObjectName("ConfirmOk") ok_btn.setObjectName(ok_object_name or "ConfirmOk")
ok_btn.setMinimumHeight(50) ok_btn.setMinimumHeight(50)
ok_btn.setFont(QFont("", 14, 700)) ok_btn.setFont(QFont("", 14, 700))
ok_btn.clicked.connect(self.accept) ok_btn.clicked.connect(self.accept)

View File

@ -1,5 +1,5 @@
from PySide6.QtWidgets import QMainWindow, QWidget, QVBoxLayout, QStackedWidget, QHBoxLayout, QLabel, QPushButton from PySide6.QtWidgets import QMainWindow, QWidget, QVBoxLayout, QStackedWidget, QHBoxLayout, QLabel, QPushButton
from PySide6.QtCore import QTimer from PySide6.QtCore import QTimer, Qt
from themes import THEME_DAY, THEME_NIGHT from themes import THEME_DAY, THEME_NIGHT
from ui.components.divider import divider from ui.components.divider import divider
from ui.components.nav_button import NavButton from ui.components.nav_button import NavButton
@ -34,6 +34,8 @@ class MainWindow(QMainWindow):
# Top bar # Top bar
self.topbar = QWidget() self.topbar = QWidget()
self.topbar.setObjectName("TopBar") self.topbar.setObjectName("TopBar")
self.topbar.setAttribute(Qt.WA_StyledBackground, True)
self.topbar.setAutoFillBackground(True)
self.topbar.setMinimumHeight(72) self.topbar.setMinimumHeight(72)
top = QHBoxLayout(self.topbar) top = QHBoxLayout(self.topbar)
top.setContentsMargins(18, 12, 18, 12) top.setContentsMargins(18, 12, 18, 12)

View File

@ -37,6 +37,8 @@ class MainWindowNew(QMainWindow):
self.topbar = QWidget() self.topbar = QWidget()
self.topbar.setObjectName("TopBar") self.topbar.setObjectName("TopBar")
self.topbar.setAttribute(Qt.WA_StyledBackground, True)
self.topbar.setAutoFillBackground(True)
self.topbar.setMinimumHeight(86) self.topbar.setMinimumHeight(86)
top = QHBoxLayout(self.topbar) top = QHBoxLayout(self.topbar)
top.setContentsMargins(18, 14, 18, 14) top.setContentsMargins(18, 14, 18, 14)