From 2d251d1131625fbeac37e1f97cbbf394a5656082 Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 9 Jan 2026 01:01:45 +0300 Subject: [PATCH] add about device --- build_info.py | 124 ++++++++++++++++++++++++++++++++++++++++++++ screens/settings.py | 54 ++++++++++++++----- 2 files changed, 164 insertions(+), 14 deletions(-) diff --git a/build_info.py b/build_info.py index 7b0accb..9390ffe 100644 --- a/build_info.py +++ b/build_info.py @@ -1,3 +1,9 @@ +import os +import platform +import shutil +import socket + + APP_NAME = "Car UI" VERSION = "0.1.0-dev" BUILD_DATE = "dev" @@ -15,3 +21,121 @@ def get_device_model() -> str: except OSError: continue return DEVICE_MODEL + + +def get_os_pretty_name() -> str: + for path in ("/etc/os-release", "/usr/lib/os-release"): + try: + with open(path, "r", encoding="utf-8") as f: + for line in f: + if line.startswith("PRETTY_NAME="): + value = line.split("=", 1)[1].strip().strip('"') + return value or "—" + except OSError: + continue + return platform.system() or "—" + + +def get_kernel_version() -> str: + return platform.release() or "—" + + +def _read_meminfo() -> dict[str, int]: + info: dict[str, int] = {} + try: + with open("/proc/meminfo", "r", encoding="utf-8") as f: + for line in f: + if ":" not in line: + continue + key, rest = line.split(":", 1) + parts = rest.strip().split() + if not parts: + continue + try: + value_kb = int(parts[0]) + except ValueError: + continue + info[key] = value_kb * 1024 + except OSError: + return {} + return info + + +def _format_bytes(num_bytes: int) -> str: + if num_bytes <= 0: + return "—" + gib = num_bytes / (1024 ** 3) + if gib >= 1: + return f"{gib:.1f} GB" + mib = num_bytes / (1024 ** 2) + return f"{mib:.0f} MB" + + +def get_ram_info() -> str: + info = _read_meminfo() + total = info.get("MemTotal", 0) + free = info.get("MemFree", 0) + if total <= 0: + return "—" + return f"{_format_bytes(free)} / {_format_bytes(total)}" + + +def get_disk_info() -> str: + try: + usage = shutil.disk_usage("/") + except OSError: + return "—" + return f"{_format_bytes(usage.used)} / {_format_bytes(usage.total)}" + + +def get_serial_number() -> str: + for path in ("/proc/device-tree/serial-number",): + try: + with open(path, "rb") as f: + raw = f.read().strip(b"\x00").strip() + if raw: + return raw.decode("utf-8", errors="replace") + except OSError: + continue + try: + with open("/proc/cpuinfo", "r", encoding="utf-8") as f: + for line in f: + if line.lower().startswith("serial"): + return line.split(":", 1)[1].strip() or "—" + except OSError: + pass + return "—" + + +def get_ip_address() -> str: + try: + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + try: + sock.connect(("8.8.8.8", 80)) + ip = sock.getsockname()[0] + finally: + sock.close() + if ip and not ip.startswith("127."): + return ip + except OSError: + pass + try: + ip = socket.gethostbyname(socket.gethostname()) + if ip and not ip.startswith("127."): + return ip + except OSError: + pass + return "—" + + +def get_cpu_temp() -> str: + for path in ("/sys/class/thermal/thermal_zone0/temp",): + try: + with open(path, "r", encoding="utf-8") as f: + raw = f.read().strip() + if raw: + temp_c = float(raw) / 1000.0 + return f"{temp_c:.1f} C" + except (OSError, ValueError): + continue + return "—" diff --git a/screens/settings.py b/screens/settings.py index 5f61d40..3b38086 100644 --- a/screens/settings.py +++ b/screens/settings.py @@ -104,6 +104,15 @@ class SettingsScreen(QWidget): ) bt_row = bt_rows.get("Bluetooth") + self._add_section( + content_layout, + "Дисплей и звук", + [ + ("Экран", "Яркость, сон, тема"), + ("Звук", "Громкость, эквалайзер"), + ], + ) + system_rows = self._add_section( content_layout, "Система", @@ -115,15 +124,6 @@ class SettingsScreen(QWidget): about_row = system_rows.get("Об устройстве") dev_row = system_rows.get("Параметры разработчика") - self._add_section( - content_layout, - "Дисплей и звук", - [ - ("Экран", "Яркость, сон, тема"), - ("Звук", "Громкость, эквалайзер"), - ], - ) - content_layout.addStretch(1) scroll.setWidget(content) list_layout.addWidget(scroll, 1) @@ -201,9 +201,22 @@ class SettingsScreen(QWidget): layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(12) - title = QLabel("Об устройстве") - title.setFont(QFont("", 22, 700)) - layout.addWidget(title) + 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) info = QVBoxLayout() info.setContentsMargins(0, 0, 0, 0) @@ -214,9 +227,22 @@ class SettingsScreen(QWidget): info.addWidget(self._info_row("Сборка", build_info.BUILD_DATE)) info.addWidget(self._info_row("Коммит", build_info.GIT_HASH)) info.addWidget(self._info_row("Устройство", build_info.get_device_model())) + info.addWidget(self._info_row("ОС", build_info.get_os_pretty_name())) + info.addWidget(self._info_row("Ядро", build_info.get_kernel_version())) + info.addWidget(self._info_row("RAM (используется/всего)", build_info.get_ram_info())) + info.addWidget(self._info_row("Диск (используется/всего)", build_info.get_disk_info())) + info.addWidget(self._info_row("Серийный номер", build_info.get_serial_number())) + info.addWidget(self._info_row("IP", build_info.get_ip_address())) + info.addWidget(self._info_row("Температура CPU", build_info.get_cpu_temp())) - layout.addLayout(info) - layout.addStretch(1) + # title = QLabel("Об устройстве") + # title.setFont(QFont("", 22, 700)) + # content_layout.addWidget(title) + content_layout.addLayout(info) + content_layout.addStretch(1) + + scroll.setWidget(content) + layout.addWidget(scroll) return screen def _info_row(self, label: str, value: str) -> QWidget: