248 lines
8.5 KiB
Python
248 lines
8.5 KiB
Python
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, "Данные", [])
|
||
|
||
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)
|