from pathlib import Path import subprocess from PySide6.QtCore import Qt, QSettings from PySide6.QtGui import QFont from PySide6.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel import build_info from ui.confirm_dialog import ConfirmDialog def build_dev_screen(on_exit) -> QWidget: screen = QWidget() layout = QVBoxLayout(screen) layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(12) layout.addWidget(_build_persist_toggle()) layout.addWidget(_build_sound_toggles()) hdr = QHBoxLayout() hdr.setContentsMargins(0, 0, 0, 0) hdr.setSpacing(12) exit_btn = QPushButton("Переход к рабочему столу") exit_btn.setObjectName("DevExitBtn") exit_btn.setMinimumHeight(72) exit_btn.clicked.connect(lambda: _confirm_exit(on_exit)) reboot_btn = QPushButton("Выполнить перезагрузку") reboot_btn.setObjectName("DevRebootBtn") reboot_btn.setMinimumHeight(72) reboot_btn.clicked.connect(_confirm_reboot) layout.addLayout(hdr) layout.addWidget(exit_btn) layout.addWidget(reboot_btn) layout.addStretch(1) return screen def _build_persist_toggle() -> QWidget: row = QWidget() layout = QHBoxLayout(row) layout.setContentsMargins(12, 6, 12, 6) layout.setSpacing(12) lbl = QLabel("Показывать после перезагрузки") lbl.setFont(QFont("", 14, 600)) btn = QPushButton("Выкл") btn.setObjectName("SoundToggle") btn.setCheckable(True) btn.setChecked(_dev_flag_path().exists()) 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): flag_path = _dev_flag_path() if is_checked: flag_path.touch(exist_ok=True) else: if flag_path.exists(): flag_path.unlink() 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 _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: return Path(build_info.__file__).resolve().parent / "dev_mode_enable" def _confirm_exit(on_exit): dialog = ConfirmDialog( "Подтверждение", "Закрыть приложение и перейти к рабочему столу?", "Выйти", ) if dialog.exec() == ConfirmDialog.Accepted: on_exit() def _confirm_reboot(): dialog = ConfirmDialog( "Подтверждение", "Выполнить перезагрузку устройства?", "Перезагрузить", ok_object_name="ConfirmOkDanger", ) if dialog.exec() == ConfirmDialog.Accepted: subprocess.run(["sudo", "reboot"], check=False)