add display info
This commit is contained in:
parent
6a9bfd4faf
commit
f2e5126fb7
43
app.py
43
app.py
@ -1,4 +1,5 @@
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from PySide6.QtCore import QSettings
|
||||
from PySide6.QtWidgets import QApplication
|
||||
@ -10,7 +11,9 @@ from ui.main_window_new import MainWindowNew
|
||||
|
||||
def run_app():
|
||||
app = QApplication(sys.argv)
|
||||
_apply_reset_if_requested()
|
||||
_apply_startup_sound_defaults()
|
||||
_apply_startup_display_defaults()
|
||||
window = MainWindowNew(app)
|
||||
window.show()
|
||||
sys.exit(app.exec())
|
||||
@ -22,7 +25,39 @@ def _apply_startup_sound_defaults():
|
||||
premute_volume = build_info.DEFAULT_PREMUTE_VOLUME
|
||||
ducking_volume = build_info.DEFAULT_DUCKING_VOLUME
|
||||
|
||||
settings.setValue("sound/base_volume", base_volume)
|
||||
settings.setValue("sound/premute_volume", premute_volume)
|
||||
settings.setValue("sound/ducking_volume", ducking_volume)
|
||||
set_volume(base_volume)
|
||||
if not settings.contains("sound/base_volume"):
|
||||
settings.setValue("sound/base_volume", base_volume)
|
||||
if not settings.contains("sound/premute_volume"):
|
||||
settings.setValue("sound/premute_volume", premute_volume)
|
||||
if not settings.contains("sound/ducking_volume"):
|
||||
settings.setValue("sound/ducking_volume", ducking_volume)
|
||||
|
||||
applied_volume = settings.value("sound/base_volume", base_volume)
|
||||
try:
|
||||
applied_volume = int(applied_volume)
|
||||
except (TypeError, ValueError):
|
||||
applied_volume = base_volume
|
||||
set_volume(applied_volume)
|
||||
|
||||
|
||||
def _apply_startup_display_defaults():
|
||||
settings = QSettings("car_ui", "ui")
|
||||
if not settings.contains("display/brightness"):
|
||||
settings.setValue("display/brightness", 70)
|
||||
if not settings.contains("display/auto_brightness"):
|
||||
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"):
|
||||
settings.setValue("display/theme", "night")
|
||||
|
||||
|
||||
def _apply_reset_if_requested():
|
||||
reset_marker = Path(__file__).resolve().parent / "reset"
|
||||
if not reset_marker.exists():
|
||||
return
|
||||
settings = QSettings("car_ui", "ui")
|
||||
settings_path = Path(settings.fileName())
|
||||
if settings_path.exists():
|
||||
settings_path.unlink()
|
||||
reset_marker.unlink()
|
||||
|
||||
249
screens/setting/display_screen.py
Normal file
249
screens/setting/display_screen.py
Normal file
@ -0,0 +1,249 @@
|
||||
from PySide6.QtCore import Qt, QSettings, Signal
|
||||
from PySide6.QtGui import QFont
|
||||
from PySide6.QtWidgets import (
|
||||
QWidget,
|
||||
QLabel,
|
||||
QVBoxLayout,
|
||||
QHBoxLayout,
|
||||
QPushButton,
|
||||
QSlider,
|
||||
QButtonGroup,
|
||||
QScrollArea,
|
||||
QScroller,
|
||||
)
|
||||
|
||||
|
||||
class DisplayScreen(QWidget):
|
||||
theme_changed = Signal(str)
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._settings = QSettings("car_ui", "ui")
|
||||
|
||||
root = QVBoxLayout(self)
|
||||
root.setContentsMargins(0, 0, 0, 0)
|
||||
root.setSpacing(12)
|
||||
|
||||
scroll = QScrollArea()
|
||||
scroll.setWidgetResizable(True)
|
||||
scroll.setFrameShape(QScrollArea.NoFrame)
|
||||
scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||
scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||
|
||||
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)
|
||||
|
||||
content_layout.addWidget(self._build_brightness_card())
|
||||
content_layout.addWidget(self._build_sleep_card())
|
||||
content_layout.addWidget(self._build_theme_card())
|
||||
content_layout.addStretch(1)
|
||||
|
||||
scroll.setWidget(content)
|
||||
root.addWidget(scroll, 1)
|
||||
|
||||
def _build_brightness_card(self) -> QWidget:
|
||||
card, body = _card("Яркость")
|
||||
brightness = _read_int_setting(self._settings, "display/brightness", 70)
|
||||
auto_brightness = _read_bool_setting(
|
||||
self._settings,
|
||||
"display/auto_brightness",
|
||||
False,
|
||||
)
|
||||
|
||||
row_toggle, toggle_btn = _toggle_row(
|
||||
"Автояркость",
|
||||
checked=auto_brightness,
|
||||
)
|
||||
row_slider, slider, value_label = _slider_row(
|
||||
"Яркость экрана",
|
||||
10,
|
||||
100,
|
||||
brightness,
|
||||
lambda v: f"{v}%",
|
||||
)
|
||||
slider.setEnabled(not auto_brightness)
|
||||
|
||||
toggle_btn.toggled.connect(
|
||||
lambda v: self._settings.setValue("display/auto_brightness", v)
|
||||
)
|
||||
toggle_btn.toggled.connect(lambda v: slider.setEnabled(not v))
|
||||
slider.valueChanged.connect(
|
||||
lambda v: self._settings.setValue("display/brightness", v)
|
||||
)
|
||||
|
||||
body.addWidget(row_toggle)
|
||||
body.addWidget(row_slider)
|
||||
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:
|
||||
card, body = _card("Тема")
|
||||
row = QWidget()
|
||||
row.setObjectName("SoundToneRow")
|
||||
layout = QHBoxLayout(row)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
layout.setSpacing(10)
|
||||
|
||||
group = QButtonGroup(row)
|
||||
group.setExclusive(True)
|
||||
|
||||
current_theme = self._settings.value("display/theme", "night")
|
||||
theme_map = {}
|
||||
for label, key in (("День", "day"), ("Ночь", "night")):
|
||||
btn = QPushButton(label)
|
||||
btn.setObjectName("SoundToneBtn")
|
||||
btn.setCheckable(True)
|
||||
btn.setMinimumHeight(40)
|
||||
btn.setFont(QFont("", 13, 600))
|
||||
if key == current_theme:
|
||||
btn.setChecked(True)
|
||||
group.addButton(btn)
|
||||
theme_map[btn] = key
|
||||
layout.addWidget(btn, 1)
|
||||
|
||||
def _apply_theme(btn: QPushButton):
|
||||
theme_key = theme_map.get(btn, "night")
|
||||
self._settings.setValue("display/theme", theme_key)
|
||||
self.theme_changed.emit(theme_key)
|
||||
|
||||
group.buttonClicked.connect(_apply_theme)
|
||||
|
||||
body.addWidget(row)
|
||||
return card
|
||||
|
||||
|
||||
def _card(title: str) -> tuple[QWidget, QVBoxLayout]:
|
||||
card = QWidget()
|
||||
card.setObjectName("SoundCard")
|
||||
layout = QVBoxLayout(card)
|
||||
layout.setContentsMargins(14, 12, 14, 12)
|
||||
layout.setSpacing(10)
|
||||
|
||||
header = QLabel(title)
|
||||
header.setObjectName("SoundCardTitle")
|
||||
header.setFont(QFont("", 14, 700))
|
||||
|
||||
layout.addWidget(header)
|
||||
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(
|
||||
label: str,
|
||||
minimum: int,
|
||||
maximum: int,
|
||||
value: int,
|
||||
formatter,
|
||||
) -> tuple[QWidget, QSlider, QLabel]:
|
||||
row = QWidget()
|
||||
row.setObjectName("SoundSliderRow")
|
||||
layout = QVBoxLayout(row)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
layout.setSpacing(6)
|
||||
|
||||
header = QWidget()
|
||||
header_layout = QHBoxLayout(header)
|
||||
header_layout.setContentsMargins(0, 0, 0, 0)
|
||||
header_layout.setSpacing(8)
|
||||
|
||||
lbl = QLabel(label)
|
||||
lbl.setFont(QFont("", 13, 600))
|
||||
val = QLabel(formatter(value))
|
||||
val.setObjectName("SoundValue")
|
||||
val.setFont(QFont("", 12, 600))
|
||||
val.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
|
||||
|
||||
header_layout.addWidget(lbl)
|
||||
header_layout.addStretch(1)
|
||||
header_layout.addWidget(val)
|
||||
|
||||
slider = QSlider(Qt.Horizontal)
|
||||
slider.setObjectName("SoundSlider")
|
||||
slider.setRange(minimum, maximum)
|
||||
slider.setValue(value)
|
||||
slider.valueChanged.connect(lambda v: val.setText(formatter(v)))
|
||||
|
||||
layout.addWidget(header)
|
||||
layout.addWidget(slider)
|
||||
return row, slider, val
|
||||
|
||||
|
||||
def _format_sleep_minutes(value: int) -> str:
|
||||
if value <= 0:
|
||||
return "Никогда"
|
||||
return f"{value} мин"
|
||||
|
||||
|
||||
def _read_int_setting(settings: QSettings, key: str, default: int) -> int:
|
||||
raw = settings.value(key, default)
|
||||
try:
|
||||
return int(raw)
|
||||
except (TypeError, ValueError):
|
||||
return default
|
||||
|
||||
|
||||
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, (int, float)):
|
||||
return bool(raw)
|
||||
if isinstance(raw, str):
|
||||
return raw.strip().lower() in {"1", "true", "yes", "on"}
|
||||
return default
|
||||
@ -17,6 +17,7 @@ from screens.setting.about_screen import build_about_screen
|
||||
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
|
||||
|
||||
|
||||
class SettingsRow(QPushButton):
|
||||
@ -60,6 +61,7 @@ class SettingsRow(QPushButton):
|
||||
|
||||
class SettingsScreen(QWidget):
|
||||
view_changed = Signal(str, bool)
|
||||
theme_changed = Signal(str)
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
@ -115,6 +117,7 @@ class SettingsScreen(QWidget):
|
||||
("Звук", "Громкость, эквалайзер"),
|
||||
],
|
||||
)
|
||||
display_row = display_rows.get("Экран")
|
||||
sound_row = display_rows.get("Звук")
|
||||
|
||||
system_rows = self._add_section(
|
||||
@ -137,12 +140,15 @@ class SettingsScreen(QWidget):
|
||||
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)
|
||||
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 dev_row is not None:
|
||||
dev_row.clicked.connect(self._show_dev)
|
||||
@ -150,6 +156,8 @@ class SettingsScreen(QWidget):
|
||||
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)
|
||||
self._show_list()
|
||||
@ -196,6 +204,10 @@ class SettingsScreen(QWidget):
|
||||
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)
|
||||
|
||||
@ -10,7 +10,7 @@ from PySide6.QtWidgets import (
|
||||
QPushButton,
|
||||
QLabel,
|
||||
)
|
||||
from PySide6.QtCore import QSize, Qt, QTimer
|
||||
from PySide6.QtCore import QSize, Qt, QTimer, QSettings
|
||||
from PySide6.QtGui import QFont
|
||||
from themes import THEME_DAY, THEME_NIGHT
|
||||
from screens.media import MediaScreen
|
||||
@ -22,7 +22,9 @@ class MainWindowNew(QMainWindow):
|
||||
def __init__(self, app: QApplication):
|
||||
super().__init__()
|
||||
self.app = app
|
||||
self.is_night = True
|
||||
self._settings = QSettings("car_ui", "ui")
|
||||
theme_pref = self._settings.value("display/theme", "night")
|
||||
self.is_night = theme_pref != "day"
|
||||
|
||||
self.setWindowTitle("Car UI (New)")
|
||||
self.setMinimumSize(QSize(1024, 600))
|
||||
@ -100,6 +102,7 @@ class MainWindowNew(QMainWindow):
|
||||
self.act_maps.triggered.connect(lambda: self.go(2))
|
||||
self.media_screen.source_changed.connect(self.lbl_bt.setText)
|
||||
self.settings_screen.view_changed.connect(self._on_settings_view_changed)
|
||||
self.settings_screen.theme_changed.connect(self._on_theme_changed)
|
||||
self.btn_back.clicked.connect(self._settings_back)
|
||||
|
||||
outer.addWidget(self.topbar)
|
||||
@ -118,6 +121,10 @@ class MainWindowNew(QMainWindow):
|
||||
def apply_theme(self):
|
||||
self.app.setStyleSheet(THEME_NIGHT if self.is_night else THEME_DAY)
|
||||
|
||||
def _on_theme_changed(self, theme_key: str):
|
||||
self.is_night = theme_key != "day"
|
||||
self.apply_theme()
|
||||
|
||||
def _sync_topbar(self, idx: int):
|
||||
is_settings = idx == self.settings_idx
|
||||
self.menu_button.setVisible(not is_settings)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user