151 lines
12 KiB
Markdown
151 lines
12 KiB
Markdown
# LoaderRow
|
||
|
||
## Обзор компонента
|
||
|
||
`Minecraft_launcher` — десктопный лаунчер Minecraft на Qt Quick. Кроме чистой игры он умеет
|
||
ставить модлоадеры: Forge, Fabric, NeoForge и Quilt. В карточке сборки лоадер выбирается
|
||
чекбоксом, а под ним — конкретная версия лоадера.
|
||
|
||
`LoaderRow` — одна такая строка: чекбокс с названием лоадера и, когда он отмечен, выпадающий
|
||
список версий именно под выбранную версию Minecraft. Компонент берёт на себя всю возню со
|
||
списком версий: подтягивает его из кэша, обновляет по сети, следит, чтобы выбранная версия
|
||
всегда существовала под текущую версию игры, и словами объясняет случай «лоадер эту версию игры
|
||
не поддерживает» вместо показа пустого списка.
|
||
|
||
Совместимость компонент не проверяет и проверять не должен: бэкенд отдаёт список, уже собранный
|
||
под конкретную версию игры, поэтому несовместимой строки в нём не бывает. Пустой список — это и
|
||
есть отсутствие поддержки.
|
||
|
||
## Место в проекте и зависимости
|
||
|
||
Импортирует `QtQuick` и `QtQuick.Controls 2.15`.
|
||
|
||
Использует компонент [DarkCombo](DarkCombo.md) из того же QML-модуля — выпадающий список версий в
|
||
тёмном стиле окна.
|
||
|
||
Работает с C++-типом `LauncherBackend` (`launcherbackend.h`, зарегистрирован через `QML_ELEMENT`
|
||
в модуле `Minecraft_launcher`), который передаётся снаружи в свойство `backend`. Из него
|
||
компонент вызывает `loaderVersions()`, `refreshLoaderVersions()` и `loaderVersionsLoading()`, а
|
||
также слушает сигнал `loaderVersionsChanged`.
|
||
|
||
Объявлен в `QML_FILES` модуля `Minecraft_launcher` (`CMakeLists.txt`). Инстанцируется в
|
||
[BuildsDialog](BuildsDialog.md) — по одной строке на каждый поддерживаемый лоадер.
|
||
|
||
## Иерархия и роль
|
||
|
||
Корневой тип — `Column` с расстоянием 4 px. Внутри три потомка, видимость которых
|
||
взаимоисключающая по нижней части:
|
||
|
||
- `CheckBox` с полностью переопределённым индикатором (квадрат со скруглением и галочкой) и
|
||
подписью. Выключен, пока не выбрана версия игры.
|
||
- [DarkCombo](DarkCombo.md) со списком версий лоадера — виден, только когда чекбокс отмечен и
|
||
список непустой.
|
||
- Текстовая строка на месте списка — видна, когда чекбокс отмечен, а список пуст. Пока идёт
|
||
запрос, она серая и говорит о загрузке; когда запрос закончен, она красноватая и сообщает, что
|
||
лоадер не поддерживает выбранную версию Minecraft.
|
||
|
||
Ширина внутренних элементов считается от ширины колонки, поэтому снаружи достаточно задать
|
||
`width`.
|
||
|
||
## Свойства
|
||
|
||
| Свойство | Тип | По умолчанию | Обязательное | Описание |
|
||
|----------|-----|--------------|--------------|----------|
|
||
| `backend` | `var` | — | **Да** | Экземпляр `LauncherBackend`. Через него запрашиваются и обновляются списки версий лоадера. |
|
||
| `loaderKey` | `string` | — | **Да** | Ключ лоадера, которым он опознаётся в бэкенде и в сохранённой сборке: `forge`, `fabric`, `neoforge`, `quilt`. |
|
||
| `title` | `string` | — | **Да** | Человекочитаемое название лоадера рядом с чекбоксом; оно же подставляется в сообщения о загрузке и об отсутствии поддержки. |
|
||
| `gameVersion` | `string` | `""` | Нет | Версия Minecraft, выбранная в карточке. Пустая строка выключает чекбокс. Смена значения сбрасывает выбранную версию лоадера и перезапрашивает список. |
|
||
| `checked` | `bool` (алиас на чекбокс) | `false` | Нет | Отмечен ли лоадер. Чтение даёт текущее состояние, запись переключает чекбокс программно — без сигнала `userChecked()`. |
|
||
| `selectedVersion` | `string` | `""` | Нет | Выбранная версия лоадера. Устанавливается только через `applyEntries()`, поэтому всегда либо пуста, либо присутствует в текущем списке. |
|
||
| `entries` | `var` | `[]` | Нет | Текущий список версий лоадера — массив записей, у каждой есть поля `version` (значение) и `label` (подпись для списка). Заполняется из бэкенда. |
|
||
| `applying` | `bool` | `false` | Нет | Признак того, что строку сейчас заполняет карточка данными сохранённой сборки. Пока он выставлен, изменения не считаются пользовательскими и сигнал `changed()` не испускается. |
|
||
|
||
## Сигналы
|
||
|
||
#### userChecked()
|
||
|
||
Пользователь сам отметил чекбокс (не программная установка `checked`). Карточка сборки в ответ
|
||
снимает отметки с остальных строк лоадеров: одновременно в `.minecraft` может жить только один
|
||
лоадер.
|
||
|
||
#### changed()
|
||
|
||
Отметка или версия лоадера изменились и это изменение пользовательское. Обработчик — карточка
|
||
сборки — сохраняет сборку с новыми значениями.
|
||
|
||
Сигнал сознательно не испускается, пока выставлен `applying`, то есть при заполнении строки из
|
||
уже сохранённой сборки: иначе загрузка карточки сразу же приводила бы к её перезаписи.
|
||
|
||
## Методы
|
||
|
||
#### versionIndex(string version) : int
|
||
|
||
Возвращает позицию версии в текущем массиве `entries` или `-1`, если такой версии в списке нет.
|
||
Вспомогательная функция для синхронизации выбранного значения с выпадающим списком.
|
||
|
||
#### applyEntries(var list) : void
|
||
|
||
Единственное место, где меняются `entries` и `selectedVersion`. Через него проходят все три пути
|
||
получения списка — кэш, ответ сети и заполнение из сохранённой сборки, — потому что выбранная
|
||
версия обязана существовать в списке под текущую версию игры.
|
||
|
||
Записывает новый список, а затем проверяет выбранную версию: если её в списке нет, подставляет
|
||
первую строку (список отсортирован новыми вперёд, поэтому первая — максимально доступная под эту
|
||
версию игры) или пустую строку для пустого списка. Если подстановка изменила значение и строка не
|
||
находится в режиме `applying`, испускает `changed()`. В конце синхронизирует `currentIndex`
|
||
выпадающего списка.
|
||
|
||
#### reload() : void
|
||
|
||
Перезапрашивает список версий. Если лоадер не отмечен или версия игры не выбрана, очищает список
|
||
через `applyEntries([])`. Иначе сначала берёт список из кэша бэкенда (`loaderVersions()`) — он
|
||
появляется мгновенно, — а затем просит обновление по сети (`refreshLoaderVersions()`), результат
|
||
которого придёт позже сигналом.
|
||
|
||
#### applyBuild(string loader, string loaderVersion) : void
|
||
|
||
Заполняет строку данными сохранённой сборки, не испуская `changed()`: на время работы выставляет
|
||
`applying`. Отмечает чекбокс, если ключ лоадера сборки совпадает с `loaderKey`, подставляет версию
|
||
из сборки как пожелание и вызывает `reload()`. Если под выбранную версию игры такой версии
|
||
лоадера нет, `applyEntries()` заменит её на максимально доступную.
|
||
|
||
## Взаимодействие с другими компонентами
|
||
|
||
**Что приходит извне.** Карточка сборки в [BuildsDialog](BuildsDialog.md) задаёт `backend`,
|
||
`loaderKey`, `title` и привязывает `gameVersion` к версии Minecraft, выбранной в карточке.
|
||
Заполнение сохранённой сборкой идёт вызовом `applyBuild()` снаружи.
|
||
|
||
**Что уходит наружу.** По `userChecked()` карточка снимает отметки с остальных строк — набор
|
||
строк она держит в собственном списке. По `changed()` карточка сохраняет сборку, читая `checked` и
|
||
`selectedVersion`.
|
||
|
||
**Бэкенд.** Компонент сам подписан на сигнал `loaderVersionsChanged(key, game)` через
|
||
`Connections`: пришедшее обновление принимается, только если ключ и версия игры совпадают с
|
||
текущими и чекбокс отмечен, — иначе ответ относится к другой строке или устарел. Текст в пустом
|
||
состоянии опрашивает `loaderVersionsLoading()`, чтобы отличать «ещё грузим» от «не поддерживается».
|
||
|
||
**Реакция на смену версии игры.** Обработчик `onGameVersionChanged` сбрасывает `selectedVersion` и
|
||
вызывает `reload()`: сборка лоадера привязана к версии игры, поэтому под новой версией прежний
|
||
выбор недействителен.
|
||
|
||
## Пример использования
|
||
|
||
```qml
|
||
LoaderRow {
|
||
id: forgeRow
|
||
width: parent.width
|
||
|
||
backend: launcherBackend
|
||
loaderKey: "forge"
|
||
title: "Forge"
|
||
gameVersion: buildCard.gameVersion
|
||
|
||
onUserChecked: buildCard.keepOnly(forgeRow)
|
||
onChanged: buildCard.commitSelection()
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
При создании этого документа использовался ИИ.
|