180 lines
14 KiB
Markdown
180 lines
14 KiB
Markdown
# BuildsDialog
|
||
|
||
## Обзор компонента
|
||
|
||
`Minecraft_launcher` — десктопный лаунчер Minecraft на Qt Quick. Сборка в нём — это именованный
|
||
набор «версия игры + модлоадер + адрес сервера» вместе с собственным содержимым `.minecraft`:
|
||
модами, конфигами и мирами. Активная сборка одна, её содержимое лежит в `.minecraft`, остальные
|
||
хранятся в архивах и разворачиваются при переключении.
|
||
|
||
`BuildsDialog` — окно управления этими сборками: слева список со сменой активной, справа карточка
|
||
выбранной — имя, сервер, версия Minecraft и модлоадеры. Отсюда же сборка ставится (скачивание
|
||
версии игры и модлоадера) и удаляется.
|
||
|
||
Карточка сохраняет правки по ходу редактирования, отдельной кнопки «Сохранить» нет: иначе
|
||
появляется неочевидное несохранённое состояние, пока пользователь переключается между сборками в
|
||
левом списке.
|
||
|
||
## Место в проекте и зависимости
|
||
|
||
В начале файла объявлена `pragma ComponentBehavior: Bound`. Импортирует `QtQuick`,
|
||
`QtQuick.Controls 2.15` и `QtQuick.Layouts 2.15`.
|
||
|
||
Использует три компонента из того же QML-модуля:
|
||
|
||
- [LabelledField](LabelledField.md) — поля названия сборки и адреса сервера;
|
||
- [LoaderRow](LoaderRow.md) — по одной строке на каждый из четырёх модлоадеров;
|
||
- [VersionPickerDialog](VersionPickerDialog.md) — вложенное окно выбора версии Minecraft.
|
||
|
||
Работает с C++-типом `LauncherBackend` (`launcherbackend.h`, `QML_ELEMENT` в модуле
|
||
`Minecraft_launcher`) через свойство `backend`. Читает свойства `customBuildNames`,
|
||
`activeBuildIndex`, `switching` и `busy`; вызывает `customBuildAt()`, `addCustomBuild()`,
|
||
`updateCustomBuild()`, `customBuildRemovalInfo()`, `removeCustomBuild()`, `checkInstallation()`,
|
||
`installCustomBuild()` и `refreshVersionCatalog()`; слушает сигнал `installedVersionsChanged`.
|
||
|
||
Объявлен в `QML_FILES` модуля (`CMakeLists.txt`); использует ресурс `images/Trash.svg`.
|
||
Инстанцируется в [Main](Main.md).
|
||
|
||
## Иерархия и роль
|
||
|
||
Корневой тип — `Dialog`: модальный, 880×600 px, нулевой внутренний отступ, тёмный фон со
|
||
скруглением и акцентной рамкой. Пока идёт смена активной сборки (`backend.switching`), окно
|
||
закрывается только кнопкой: архивация и распаковка `.minecraft` не должны прерываться случайным
|
||
щелчком мимо.
|
||
|
||
Содержимое — `RowLayout` из двух частей:
|
||
|
||
- **Слева** (260 px) список сборок и строка «+ Новая сборка» под ним. Строка списка показывает имя,
|
||
пометку «активна» у активной сборки и корзину, появляющуюся при наведении. Вся колонка
|
||
выключается на время смены активной сборки.
|
||
- **Справа** карточка выбранной сборки внутри `Flickable` — она может не поместиться по высоте.
|
||
Карточка выключается и приглушается, когда сборка не выбрана или идёт переключение.
|
||
|
||
Карточка сверху вниз: название, адрес сервера, поле версии Minecraft, панель модлоадеров и строка
|
||
состояния комплектности. Поле версии — не выпадающий список, а прямоугольник, который только
|
||
показывает выбор и открывает отдельное окно: версий около тысячи, и разбираться в них удобнее в
|
||
окне с категориями.
|
||
|
||
Отдельно объявлен вложенный `Dialog` подтверждения удаления шириной 420 px с красной рамкой,
|
||
привязанный к тому же родителю, что и само окно.
|
||
|
||
Подвал несёт три кнопки: «Установить», «Сделать активной» и «Закрыть».
|
||
|
||
## Свойства
|
||
|
||
| Свойство | Тип | По умолчанию | Обязательное | Описание |
|
||
|----------|-----|--------------|--------------|----------|
|
||
| `backend` | `var` | — | **Да** | Экземпляр `LauncherBackend` — хранилище сборок и исполнитель установки, удаления и переключения. |
|
||
| `editIndex` | `int` | `-1` | Нет | Индекс сборки, открытой в карточке справа. Значение `-1` означает, что карточка пуста и выключена. С активной сборкой не связан: активную меняет отдельная кнопка, чтобы случайный клик по списку не запускал архивацию `.minecraft`. |
|
||
| `loading` | `bool` | `false` | Нет | Признак того, что карточка сейчас заполняется данными сборки. Пока он выставлен, обработчики полей не должны писать обратно — иначе открытие сборки немедленно перезаписывало бы её. |
|
||
|
||
### Внутренняя панель модлоадеров
|
||
|
||
Панель `loaderPanel` — это `Column` с четырьмя строками [LoaderRow](LoaderRow.md) и собственным
|
||
маленьким API. Лоадеры несовместимы между собой: игра запускается ровно с одним профилем
|
||
`versions/<id>`, поэтому отметка одного снимает остальные, а «ничего не отмечено» — это чистая
|
||
ваниль.
|
||
|
||
| Свойство панели | Тип | Описание |
|
||
|-----------------|-----|----------|
|
||
| `rows` | `var` | Массив из четырёх строк лоадеров в порядке показа: Minecraft Forge (`forge`), Fabric Loader (`fabric`), NeoForge (`neoforge`), Quilt Loader (`quilt`). |
|
||
|
||
Функции панели: `applyBuild(loader, loaderVersion)` раздаёт данные сборки всем строкам;
|
||
`selectedRow()` возвращает отмеченную строку или `null`; `keepOnly(row)` очищает все строки,
|
||
кроме переданной; `commitSelection()` сохраняет выбор в сборку, записывая ключ лоадера, его версию
|
||
и пустой `resolvedVersionId` — профиль появится только после установки, а до неё сборка
|
||
запускается на чистой ванили.
|
||
|
||
## Сигналы
|
||
|
||
Собственных сигналов компонент не объявляет: все изменения уходят прямо в бэкенд, и о них
|
||
остальной интерфейс узнаёт по его сигналам.
|
||
|
||
## Методы
|
||
|
||
#### selectBuild(int index) : void
|
||
|
||
Открывает сборку с указанным индексом в карточке. Читает данные через `customBuildAt()`,
|
||
выставляет `loading` на время заполнения полей, раздаёт лоадеры панели через `applyBuild()` и в
|
||
конце обновляет строку состояния.
|
||
|
||
#### askRemove(int index) : void
|
||
|
||
Спрашивает подтверждение перед удалением: оно необратимо и уносит с собой архив сборки. Запрашивает
|
||
`customBuildRemovalInfo()` и наполняет окно подтверждения именем сборки и тремя признаками — есть
|
||
ли у неё архив, активна ли она сейчас и последняя ли она. Индекс запоминается в самом окне
|
||
подтверждения, потому что к моменту ответа строка списка под курсором может быть уже другой.
|
||
|
||
Окно подтверждения объясняет последствия по этим признакам: вместе со сборкой удалится её архив, и
|
||
моды, конфиги и миры восстановить будет нельзя; активная сборка владеет содержимым `.minecraft`,
|
||
оно будет очищено, а на его место развернётся следующая сборка; для последней сборки содержимое
|
||
`.minecraft` остаётся на месте.
|
||
|
||
#### performRemove(int index) : void
|
||
|
||
Удаляет сборку через бэкенд и восстанавливает состояние карточки: если сборок не осталось,
|
||
сбрасывает `editIndex` в `-1`, иначе открывает соседнюю — ту же позицию или последнюю оставшуюся.
|
||
|
||
#### commit(var fields) : void
|
||
|
||
Сохраняет часть полей сборки: передаёт `QVariantMap` в `updateCustomBuild()` и обновляет строку
|
||
состояния. Ничего не делает во время заполнения карточки (`loading`) и при пустом `editIndex` —
|
||
это и есть защита от записи при открытии сборки.
|
||
|
||
Вызывается по завершении правки каждого поля: имени, адреса сервера, версии Minecraft и выбора
|
||
модлоадера.
|
||
|
||
#### refreshStatus() : void
|
||
|
||
Пересчитывает строку комплектности под карточкой. Спрашивает у бэкенда `checkInstallation()` и
|
||
показывает либо сообщение о готовности к запуску, либо число недостающих файлов вместе с первым из
|
||
них. При пустом `editIndex` очищает строку.
|
||
|
||
#### newBuildName() : string
|
||
|
||
Придумывает имя для новой сборки: перебирает «Сборка 1», «Сборка 2» и так далее, пока не найдёт
|
||
свободное среди существующих имён.
|
||
|
||
## Взаимодействие с другими компонентами
|
||
|
||
**Со стороны родителя.** [Main](Main.md) задаёт `backend` и открывает окно. Начальное состояние
|
||
окно выбирает само в обработчике `onAboutToShow`: просит обновить каталог версий и открывает
|
||
активную сборку, а при пустом списке оставляет карточку выключенной.
|
||
|
||
**Внутрь — к вложенным компонентам.** Поля [LabelledField](LabelledField.md) сообщают о правке
|
||
сигналом `editingFinished`, и карточка сразу вызывает `commit()` с обрезанным по краям значением.
|
||
Поле версии открывает [VersionPickerDialog](VersionPickerDialog.md) вызовом `openFor()` и получает
|
||
результат сигналом `versionChosen`; запись выбранной версии сама вызывает `commit()` через
|
||
обработчик изменения. Строки [LoaderRow](LoaderRow.md) получают `gameVersion` привязкой к
|
||
выбранной версии игры, поэтому смена версии Minecraft автоматически перезапрашивает списки версий
|
||
лоадеров.
|
||
|
||
**Наружу — к бэкенду.** Кнопка «Установить» вызывает `installCustomBuild()`, кнопка «Сделать
|
||
активной» пишет в свойство `activeBuildIndex`. Обе выключены, пока лаунчер занят (`busy`), а
|
||
кнопка активации — ещё и когда выбранная сборка уже активна. Ход установки и переключения
|
||
показывает плашка [ProgressPanel](ProgressPanel.md) главного окна, а не это окно.
|
||
|
||
**Обратная связь от бэкенда.** Окно подписано на `installedVersionsChanged` через `Connections`:
|
||
установка версии или модлоадера меняет комплектность сборки, и строка состояния должна это
|
||
заметить, не дожидаясь переоткрытия окна.
|
||
|
||
## Пример использования
|
||
|
||
```qml
|
||
BuildsDialog {
|
||
id: buildsDialog
|
||
parent: Overlay.overlay
|
||
anchors.centerIn: parent
|
||
backend: launcherBackend
|
||
}
|
||
|
||
Button {
|
||
text: qsTr("Сборки")
|
||
onClicked: buildsDialog.open()
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
При создании этого документа использовался ИИ.
|