LED-mapper/README.md
Danil Iarosh 30ac54f77f feat: Release v3.5.0 with free-form text comments
- Добавлены свободные многострочные комментарии на схеме: создание через меню, перемещение мышью, редактирование и удаление.
- Реализовано хранение комментариев в JSON с устойчивыми идентификаторами, координатами и сохранением неизвестных полей.
- Все операции с комментариями включены в Undo/Redo; поддержаны схемы только с заметками и сохранение удаления последней заметки.
- Исправлены границы общего вида, неограниченный масштаб схемы с одной заметкой и завершение перетаскивания при панорамировании пробелом.
- Добавлены семь smoke-сценариев, проверки совместимости генератора и обновлено руководство пользователя.
- Версия приложения обновлена до 3.5.0.
2026-11-05 08:50:36 +03:00

216 lines
19 KiB
Markdown
Raw Permalink 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.

# LED Mapper
LED Mapper — настольное приложение на Python и PySide6 для разметки LED-точек на схеме, распределения их по физическим линиям светодиодных лент и генерации `vm_map.h` для прошивки.
Приложение помогает вручную или полуавтоматически собрать адресацию светодиодов: выбрать точки на схеме, создать линии, разбить их на блоки, проверить индексацию и сгенерировать готовые файлы маппинга.
## Возможности
- Загрузка карты LED-точек из JSON.
- Отображение схемы в реальных координатах.
- Выделение точек мышью и работа через таблицу выбранных LED.
- До 4 физических линий светодиодных лент.
- Нумерация линий и блоков с `0`.
- Блоки внутри линий, включая пустые блоки.
- Индексация LED отдельно для каждой линии, начиная с `0`.
- Индексация внутри каждого блока.
- Добавление блоков вручную, из выделения, автоблоками и кистью.
- Продолжение существующего блока кистью от последней точки блока.
- Предпросмотр зоны действия кисти и точек, которые будут добавлены.
- Сетка с настраиваемым шагом (по умолчанию 34 мм) во всех режимах редактирования и генерации.
- Настраиваемые абсолютные размеры LED-точек и текста их индексов: визуальный размер не меняется при приближении.
- Свободные многострочные текстовые комментарии на схеме.
- Undo/redo для операций разметки и комментариев.
- Удаление назначений через `Del` и контекстные меню.
- Пакетное удаление выбранных блоков через дерево одной операцией с единым Undo.
- Сворачивание боковой панели.
- Сортировка таблицы выбранных точек по столбцам.
- Генерация `vm_map.h`, `ordered_circles.json`, `validation_report.txt` и README для результата.
- Сборка самостоятельного Windows EXE через PyInstaller.
- Проверка и установка Windows-обновлений из релизов Gitea.
## Структура приложения
```text
main.py Точка входа GUI-приложения
main_window.py Главное окно, меню, действия, таблица и дерево линий
canvas.py Холст схемы, выделение, кисть, сетка и связи
models.py Модель карты, линий, блоков и алгоритмы маршрутов
panel_mapping_generator.py Генерация файлов маппинга
update_service.py Проверка релизов и безопасная установка Windows EXE
version.py Базовая версия приложения при запуске из исходников
icons.py Встроенные lucide-иконки
unfolding.py Описание развертки линий и блоков
qa_smoke.py Smoke-тесты приложения
requirements.txt Runtime-зависимости
LEDMapper.spec PyInstaller-конфигурация для сборки EXE
```
## Требования
- Windows.
- Python 3.10 или новее.
- PySide6.
Для разработки и запуска используется локальное виртуальное окружение проекта.
## Быстрый старт
Из корневой папки проекта создайте окружение:
```powershell
python -m venv .venv
```
Установите зависимости:
```powershell
.\.venv\Scripts\python.exe -m pip install -r app\requirements.txt
```
Запустите приложение:
```powershell
.\.venv\Scripts\python.exe app\main.py
```
Если вы находитесь внутри папки `app`, запуск выглядит так:
```powershell
..\.venv\Scripts\python.exe main.py
```
## Основной сценарий работы
1. Откройте JSON-карту точек через `Файл -> Открыть`.
2. Создайте линию кнопкой `Линия` или через меню `Инструменты -> Новая линия`.
3. Выберите точки на схеме или в таблице.
4. Создайте блок из выбранных точек, автоблоки или включите инструмент `Кисть`.
5. Повторите разметку для остальных линий и блоков.
6. Проверьте счетчики в верхней части боковой панели: количество линий, блоков и назначенных LED.
7. Сгенерируйте скрипт через `Файл -> Сгенерировать скрипт`.
Шаг сетки, диаметр точек и размер текста индексов меняются в `Файл -> Параметры -> Внешний вид`. Для каждого значения рядом есть кнопка `Сбросить`. Размер текста индексов обновляется на схеме сразу во время настройки; при отмене возвращается прежнее значение. Шаг сетки сохраняется в JSON текущей схемы, а диаметр точек и размер текста индексов — в пользовательских параметрах приложения. Визуальные размеры точек и подписей не меняются при приближении схемы. Изменение шага не перемещает уже существующие LED автоматически.
Чтобы удалить несколько блоков, выделите их в дереве с `Ctrl` или `Shift`, затем нажмите `Ctrl+Del` или выберите удаление в контекстном меню. Приложение показывает одно подтверждение и создаёт одну операцию Undo.
В режиме редактирования выбранные светодиоды можно скопировать через `Ctrl+C` и вставить через `Ctrl+V`. Вставленные LED остаются свободными, сохраняют взаимное расположение и пользовательские поля исходных точек. Первая копия смещается на один шаг сетки вправо и вниз, а следующие вставки образуют каскад. Вся группа вставляется одной операцией Undo и сразу становится текущим выделением.
В собранном Windows EXE приложение проверяет наличие нового стабильного релиза после запуска. В меню `Справка` можно запустить проверку вручную и, если новая версия найдена, выбрать `Установить обновление`. Загружается только артефакт вида `LEDMapper-vX.Y.Z.exe` из репозитория `Robotail/LED-mapper` на `git.robotail.pro`. После проверки размера и формата EXE приложение предлагает сохранить изменённую схему, закрывается, а отдельный процесс заменяет EXE по прежнему пути и запускает новую версию — существующие ярлыки продолжают работать. Версия релизной сборки хранится внутри EXE, поэтому переименование файла не вызывает повторную установку того же обновления. При неудачном запуске старая версия восстанавливается; причина записывается рядом с EXE в `update-error.log`. Для обновления нужны доступ к серверу релизов и право записи в каталог приложения. Из исходников можно проверить наличие версии, но автоустановка недоступна.
Перед загрузкой проверяются права записи в каталог приложения. Перенаправления на страницу входа, другой сайт или неожиданный путь того же сервера отклоняются; объявленный сервером размер файла должен совпадать с размером артефакта в данных релиза.
Если не назначен ни один светодиод, генерация не запускается. Если назначены не все светодиоды, приложение показывает предупреждение и предлагает либо сгенерировать неполный маппинг, либо продолжить редактирование.
## Текстовые комментарии на схеме
Чтобы разместить заметку, нажмите правой кнопкой мыши в нужном месте схемы и выберите `Добавить комментарий…`. Команда `Инструменты -> Добавить комментарий…` создаёт заметку в центре видимой области. Введите многострочный текст и подтвердите ввод.
Комментарий можно свободно перетаскивать левой кнопкой мыши в любом режиме. Двойной щелчок открывает редактирование текста; в контекстном меню комментария доступны изменение и удаление. Размер текста остаётся читаемым при изменении масштаба. Команда `Показать всё` учитывает комментарии, в том числе за пределами LED-схемы.
Добавление, изменение, перемещение и удаление поддерживают Undo/Redo. Отмена диалога и пустой текст не изменяют схему. Комментарии сохраняются в JSON в списке `comments`: `id`, `text`, `x`, `y`; координаты используют единицы схемы. Старые JSON без этого списка открываются без комментариев. Можно сохранить схему, содержащую только комментарии.
Комментарии не привязаны к линиям, блокам или LED и не влияют на физические адреса в `VM_MAPPINGS`. Экспорт изображения маппинга через меню `Файл` по-прежнему показывает LED и легенду; текстовые комментарии сохраняются в JSON и отображаются в редакторе.
## Горячие клавиши
| Действие | Клавиши |
| --- | --- |
| Открыть | `Ctrl+O` |
| Сохранить | `Ctrl+S` |
| Сохранить как | `Ctrl+Shift+S` |
| Сгенерировать скрипт | `Ctrl+G` |
| Отменить | `Ctrl+Z` |
| Повторить | `Ctrl+Y` |
| Копировать выбранные LED | `Ctrl+C` |
| Вставить скопированные LED | `Ctrl+V` |
| Удалить фиксацию | `Del` |
| Удалить выбранные точки или блоки | `Ctrl+Del` |
| Удалить все | `Ctrl+Shift+Del` |
| Очистить выбор | `Esc` |
| Показать всю схему | `Ctrl+0` |
| Сетка | `G` |
| Стрелки направления | `Ctrl+Shift+A` |
| Скрыть/показать боковую панель | `F9` |
| Новая линия | `Ctrl+L` |
| Автоблоки | `Ctrl+Shift+B` |
| Кисть | `B` |
## Генерация файлов маппинга
Генератор создает:
- `vm_map.h` — основной header для прошивки.
- `ordered_circles.json` — нормализованные точки и координаты виртуальной матрицы.
- `validation_report.txt` — отчет о проверках маршрутов и ячеек.
- `README.md` — краткое описание результата генерации.
Устаревший `virtual_matrix_legacy.ino.txt` больше не создаётся. Если файл с этим точным именем остался в выходной папке от прежней версии, следующая успешная генерация удалит его. Другие `.ino`-файлы не затрагиваются.
JSON схемы хранит `coordinate_unit`, `grid_step_mm` и `index_base: 0`. При первом открытии старого файла без единицы координат приложение определяет её один раз и затем сохраняет явно. Старые схемы с 1-based ID линий и блоков при загрузке переводятся на 0-based; сохранение записывает маркер `index_base: 0`, чтобы повторная загрузка не сдвигала ID. Сохранение выполняется через временный файл и атомарную замену, поэтому исходный JSON не повреждается при ошибке записи.
Если у схемы есть подложка, при сохранении исходное изображение встраивается в секцию `background.embedded_image` внутри JSON вместе с именем, MIME-типом и контрольной суммой. Диалог выбора показывает все форматы, которые доступны в поставляемой версии Qt (включая PNG, JPEG/JFIF, BMP, GIF, WebP, TIFF и SVG), распознаёт содержимое независимо от регистра и расширения файла и учитывает EXIF-ориентацию. Большие изображения безопасно уменьшаются для отображения. Если изображение повреждено или его декодер недоступен, приложение показывает причину и сохраняет прежнюю подложку. После сохранения схема не зависит от внешнего файла, а размеры и параметры подложки сохраняются при редактировании и переносе JSON. Для уже встроенного и не заменённого изображения диалог `Подложка` показывает в поле пути значение `Встроенная`. Чтобы заменить его, нажмите `Выбрать` и укажите новый файл; новое изображение будет встроено при следующем сохранении схемы.
В `vm_map.h` используются физические адреса из GUI:
- `strip = line_id`
- `led_id = line_index`
Неназначенные точки не попадают в рабочий `VM_MAPPINGS`, но исходные точки могут оставаться в служебных метаданных.
## Ориентация виртуальной матрицы
Текущий формат явно описывает преобразование координат:
```cpp
#define VM_ROW_FROM_GRID_COL(col) (GRID_COL_MAX - (col))
#define VM_COL_FROM_GRID_ROW(row) ((row) - GRID_ROW_MIN)
```
То есть строка виртуальной матрицы получается из исходной колонки с отражением, а колонка виртуальной матрицы получается из исходного ряда.
## Проверка качества
Из корня проекта:
```powershell
.\.venv\Scripts\python.exe app\qa_smoke.py
```
Проверка компиляции основных модулей:
```powershell
.\.venv\Scripts\python.exe -m py_compile app\main.py app\main_window.py app\canvas.py app\models.py app\panel_mapping_generator.py app\qa_smoke.py
```
## Сборка EXE
Установите PyInstaller в `.venv`:
```powershell
.\.venv\Scripts\python.exe -m pip install pyinstaller
```
Сборка из корня проекта:
```powershell
.\.venv\Scripts\python.exe -m PyInstaller --noconfirm --clean app\LEDMapper.spec
```
Сборочный `spec` ограничивает поиск DLL каталогами Python, виртуального окружения и Windows. Это защищает EXE от несовместимых системных библиотек сторонних программ, добавленных в `PATH`. После сборки проверяйте готовый файл командой `dist\LEDMapper-vX.Y.Z.exe --verify-bundle`: успешная проверка завершается с кодом `0` без открытия окна приложения.
В чистой сборке из релизного тега файл будет называться:
```text
dist/LEDMapper-vX.Y.Z.exe
```
`build/` и `dist/` не коммитятся, потому что это воспроизводимые артефакты сборки.
## Примечания для разработки
- Для работы с приложением использовать только Python из `.venv`.
- Не коммитить `.venv`, `build`, `dist`, `output` и `__pycache__`.
- Перед коммитом желательно запускать `app\qa_smoke.py`.
- Максимальное количество линий светодиодных лент: 4.