car_ui/screens/settings.py
2026-01-09 05:39:32 +03:00

256 lines
8.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from PySide6.QtWidgets import (
QWidget,
QLabel,
QVBoxLayout,
QHBoxLayout,
QPushButton,
QSizePolicy,
QScrollArea,
QStackedWidget,
QApplication,
)
from PySide6.QtCore import Qt, Signal, QSettings
from PySide6.QtGui import QFont
from PySide6.QtWidgets import QScroller
from screens.setting.bluetooth_screen import BluetoothScreen
from screens.setting.about_screen import AboutScreen
from screens.setting.dev_screen import build_dev_screen
from screens.setting.sound_screen import SoundScreen
from screens.setting.eq_screen import EqualizerScreen
from screens.setting.display_screen import DisplayScreen
import build_info
from ui.language_dialog import LanguageDialog
class SettingsRow(QPushButton):
def __init__(self, title: str, subtitle: str):
super().__init__()
self.setObjectName("SettingsRow")
self.setCursor(Qt.PointingHandCursor)
self.setCheckable(False)
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
self.setMinimumHeight(70)
row = QHBoxLayout(self)
row.setContentsMargins(16, 10, 16, 10)
row.setSpacing(12)
text_col = QVBoxLayout()
text_col.setContentsMargins(0, 0, 0, 0)
text_col.setSpacing(2)
lbl_title = QLabel(title)
lbl_title.setObjectName("SettingsRowTitle")
lbl_title.setFont(QFont("", 16, 600))
lbl_sub = QLabel(subtitle)
lbl_sub.setObjectName("SettingsRowSub")
lbl_sub.setFont(QFont("", 12))
lbl_sub.setWordWrap(False)
text_col.addWidget(lbl_title)
text_col.addWidget(lbl_sub)
chevron = QLabel("")
chevron.setObjectName("SettingsChevron")
chevron.setFont(QFont("", 20, 600))
chevron.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
row.addLayout(text_col)
row.addStretch(1)
row.addWidget(chevron)
class SettingsScreen(QWidget):
view_changed = Signal(str, bool)
theme_changed = Signal(str)
def __init__(self):
super().__init__()
self._dev_enabled = build_info.DEV_MODE_ENABLE
self._dev_row: SettingsRow | None = None
root = QVBoxLayout(self)
root.setContentsMargins(18, 0, 18, 16)
root.setSpacing(12)
self.stack = QStackedWidget()
root.addWidget(self.stack, 1)
self._list_screen = QWidget()
list_layout = QVBoxLayout(self._list_screen)
list_layout.setContentsMargins(0, 0, 0, 0)
list_layout.setSpacing(12)
# list_title = QLabel("Настройки")
# list_title.setFont(QFont("", 24, 700))
# list_layout.addWidget(list_title)
scroll = QScrollArea()
scroll.setWidgetResizable(True)
scroll.setFrameShape(QScrollArea.NoFrame)
scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
# === TOUCH SCROLL (Raspberry safe) ===
scroller = QScroller.scroller(scroll.viewport())
scroller.grabGesture(
scroll.viewport(),
QScroller.LeftMouseButtonGesture
)
content = QWidget()
content_layout = QVBoxLayout(content)
content_layout.setContentsMargins(0, 0, 0, 0)
content_layout.setSpacing(12)
bt_rows = self._add_section(
content_layout,
"Сеть",
[
("Wi-Fi", "Доступные сети и подключение"),
("Bluetooth", "Сопряжение и устройства"),
],
)
bt_row = bt_rows.get("Bluetooth")
display_rows = self._add_section(
content_layout,
"Дисплей и звук",
[
("Экран", "Яркость, тема"),
("Звук", "Громкость, эквалайзер"),
("Язык", "Выбор языка интерфейса"),
],
)
display_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(
content_layout,
"Система",
[
("Обновление системы", "Проверка и установка обновлений"),
("Об устройстве", "Версия, память, серийный номер"),
("Параметры разработчика", "Отладка и логирование"),
],
)
about_row = system_rows.get("Об устройстве")
self._dev_row = system_rows.get("Параметры разработчика")
if self._dev_row is not None and not self._dev_enabled:
self._dev_row.setVisible(False)
content_layout.addStretch(1)
scroll.setWidget(content)
list_layout.addWidget(scroll, 1)
self._dev_screen = build_dev_screen(self._exit_app)
self._about_screen = AboutScreen()
self._about_screen.dev_unlocked.connect(self._enable_dev_mode)
self._bt_screen = BluetoothScreen(self._show_list)
self._eq_screen = EqualizerScreen()
self._sound_screen = SoundScreen(self._show_equalizer)
self._display_screen = DisplayScreen()
self._display_screen.theme_changed.connect(self.theme_changed.emit)
self.stack.addWidget(self._list_screen)
if self._dev_enabled:
self.stack.addWidget(self._dev_screen)
self.stack.addWidget(self._about_screen)
self.stack.addWidget(self._bt_screen)
self.stack.addWidget(self._sound_screen)
self.stack.addWidget(self._eq_screen)
self.stack.addWidget(self._display_screen)
if self._dev_row is not None and self._dev_enabled:
self._dev_row.clicked.connect(self._show_dev)
if about_row is not None:
about_row.clicked.connect(self._show_about)
if bt_row is not None:
bt_row.clicked.connect(self._show_bluetooth)
if display_row is not None:
display_row.clicked.connect(self._show_display)
if sound_row is not None:
sound_row.clicked.connect(self._show_sound)
if language_row is not None:
language_row.clicked.connect(self._show_language)
self._show_list()
def _add_section(
self,
root: QVBoxLayout,
title: str,
items: list[tuple[str, str]],
) -> dict[str, SettingsRow]:
section = QLabel(title)
section.setObjectName("SettingsSection")
section.setFont(QFont("", 14, 700))
section.setContentsMargins(2, 8, 2, 0)
root.addWidget(section)
rows: dict[str, SettingsRow] = {}
for row_title, row_subtitle in items:
row = SettingsRow(row_title, row_subtitle)
root.addWidget(row)
rows[row_title] = row
return rows
def _show_dev(self):
self.stack.setCurrentWidget(self._dev_screen)
self.view_changed.emit("Параметры разработчика", True)
def _show_list(self):
self.stack.setCurrentWidget(self._list_screen)
self.view_changed.emit("Настройки", False)
def _show_bluetooth(self):
self.stack.setCurrentWidget(self._bt_screen)
self.view_changed.emit("Bluetooth", True)
def _show_about(self):
self.stack.setCurrentWidget(self._about_screen)
self.view_changed.emit("Об устройстве", True)
def show_list(self):
self._show_list()
def _show_sound(self):
self.stack.setCurrentWidget(self._sound_screen)
self.view_changed.emit("Звук", True)
def _show_display(self):
self.stack.setCurrentWidget(self._display_screen)
self.view_changed.emit("Экран", True)
def _show_equalizer(self):
self.stack.setCurrentWidget(self._eq_screen)
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):
app = QApplication.instance()
if app is not None:
app.quit()
def _enable_dev_mode(self):
if self._dev_enabled:
return
self._dev_enabled = True
if self._dev_row is not None:
self._dev_row.setVisible(True)
self._dev_row.clicked.connect(self._show_dev)
self.stack.addWidget(self._dev_screen)