Files
minecraft-launcher/doc/qml/LoaderRow.md
T
2026-09-03 09:16:56 +03:00

151 lines
12 KiB
Markdown
Raw 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.
# 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()
}
```
---
При создании этого документа использовался ИИ.