186 lines
7.2 KiB
QML
186 lines
7.2 KiB
QML
|
|
import QtQuick
|
||
|
|
import QtQuick.Controls 2.15
|
||
|
|
|
||
|
|
// Один модлоадер в карточке сборки: чекбокс и, когда он отмечен, список версий
|
||
|
|
// именно под выбранную версию Minecraft.
|
||
|
|
//
|
||
|
|
// Совместимость проверять не нужно: backend.loaderVersions() отдаёт список уже
|
||
|
|
// под конкретную версию игры, поэтому несовместимой строки в нём не бывает.
|
||
|
|
// Пустой список — это «лоадер не поддерживает эту версию игры», и он тоже
|
||
|
|
// показывается словами, а не пустым выпадающим списком.
|
||
|
|
Column {
|
||
|
|
id: loaderRow
|
||
|
|
|
||
|
|
required property var backend
|
||
|
|
required property string loaderKey
|
||
|
|
required property string title
|
||
|
|
|
||
|
|
// Версия Minecraft, выбранная в карточке. Её смена сбрасывает выбор.
|
||
|
|
property string gameVersion: ""
|
||
|
|
|
||
|
|
property alias checked: box.checked
|
||
|
|
property string selectedVersion: ""
|
||
|
|
property var entries: []
|
||
|
|
|
||
|
|
// Пользователь щёлкнул чекбокс — карточка снимет отметки с остальных
|
||
|
|
// лоадеров: одновременно в .minecraft может жить только один.
|
||
|
|
signal userChecked()
|
||
|
|
// Отметка или версия изменились — карточке пора сохранить сборку.
|
||
|
|
signal changed()
|
||
|
|
|
||
|
|
// Ставится, пока карточка заполняет строку данными сборки: в это время
|
||
|
|
// обработчики не должны считать изменения пользовательскими.
|
||
|
|
property bool applying: false
|
||
|
|
|
||
|
|
spacing: 4
|
||
|
|
|
||
|
|
function versionIndex(version) {
|
||
|
|
for (var i = 0; i < loaderRow.entries.length; ++i) {
|
||
|
|
if (loaderRow.entries[i].version === version)
|
||
|
|
return i
|
||
|
|
}
|
||
|
|
return -1
|
||
|
|
}
|
||
|
|
|
||
|
|
// Самая свежая стабильная сборка, а если стабильных нет — просто самая
|
||
|
|
// свежая. Список отсортирован новыми вперёд, поэтому хватает первого
|
||
|
|
// совпадения.
|
||
|
|
function preferredIndex() {
|
||
|
|
for (var i = 0; i < loaderRow.entries.length; ++i) {
|
||
|
|
if (loaderRow.entries[i].recommended)
|
||
|
|
return i
|
||
|
|
}
|
||
|
|
for (var j = 0; j < loaderRow.entries.length; ++j) {
|
||
|
|
if (loaderRow.entries[j].stable)
|
||
|
|
return j
|
||
|
|
}
|
||
|
|
return loaderRow.entries.length > 0 ? 0 : -1
|
||
|
|
}
|
||
|
|
|
||
|
|
function syncCombo() {
|
||
|
|
const index = loaderRow.versionIndex(loaderRow.selectedVersion)
|
||
|
|
combo.currentIndex = index
|
||
|
|
}
|
||
|
|
|
||
|
|
function reload() {
|
||
|
|
if (!box.checked || loaderRow.gameVersion === "") {
|
||
|
|
loaderRow.entries = []
|
||
|
|
return
|
||
|
|
}
|
||
|
|
// Сначала из кэша — список появляется мгновенно, — потом обновление сети.
|
||
|
|
loaderRow.entries = loaderRow.backend.loaderVersions(loaderRow.loaderKey,
|
||
|
|
loaderRow.gameVersion)
|
||
|
|
loaderRow.syncCombo()
|
||
|
|
loaderRow.backend.refreshLoaderVersions(loaderRow.loaderKey, loaderRow.gameVersion)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Заполнение из сохранённой сборки: без сигналов changed().
|
||
|
|
function applyBuild(loader, loaderVersion) {
|
||
|
|
loaderRow.applying = true
|
||
|
|
box.checked = loader === loaderRow.loaderKey
|
||
|
|
loaderRow.selectedVersion = box.checked ? loaderVersion : ""
|
||
|
|
loaderRow.reload()
|
||
|
|
loaderRow.applying = false
|
||
|
|
}
|
||
|
|
|
||
|
|
onGameVersionChanged: {
|
||
|
|
// Сборка лоадера привязана к версии игры — при её смене выбор
|
||
|
|
// сбрасывается, и список перезапрашивается под новую версию.
|
||
|
|
loaderRow.entries = []
|
||
|
|
loaderRow.selectedVersion = ""
|
||
|
|
combo.currentIndex = -1
|
||
|
|
loaderRow.reload()
|
||
|
|
}
|
||
|
|
|
||
|
|
Connections {
|
||
|
|
target: loaderRow.backend
|
||
|
|
function onLoaderVersionsChanged(key, game) {
|
||
|
|
if (key !== loaderRow.loaderKey || game !== loaderRow.gameVersion || !box.checked)
|
||
|
|
return
|
||
|
|
loaderRow.entries = loaderRow.backend.loaderVersions(key, game)
|
||
|
|
if (loaderRow.selectedVersion === "" || loaderRow.versionIndex(loaderRow.selectedVersion) < 0) {
|
||
|
|
const preferred = loaderRow.preferredIndex()
|
||
|
|
if (preferred >= 0) {
|
||
|
|
loaderRow.selectedVersion = loaderRow.entries[preferred].version
|
||
|
|
if (!loaderRow.applying)
|
||
|
|
loaderRow.changed()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
loaderRow.syncCombo()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
CheckBox {
|
||
|
|
id: box
|
||
|
|
text: loaderRow.title
|
||
|
|
enabled: loaderRow.gameVersion !== ""
|
||
|
|
|
||
|
|
indicator: Rectangle {
|
||
|
|
implicitWidth: 18
|
||
|
|
implicitHeight: 18
|
||
|
|
x: 0
|
||
|
|
y: (box.height - height) / 2
|
||
|
|
radius: 4
|
||
|
|
color: box.checked ? "#91B315" : "#2a2a2a"
|
||
|
|
border.color: box.checked ? "#91B315" : "#444444"
|
||
|
|
border.width: 1
|
||
|
|
|
||
|
|
Text {
|
||
|
|
anchors.centerIn: parent
|
||
|
|
visible: box.checked
|
||
|
|
text: "✓"
|
||
|
|
color: "#1e1e1e"
|
||
|
|
font.pixelSize: 13
|
||
|
|
font.bold: true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
contentItem: Text {
|
||
|
|
leftPadding: box.indicator.width + 8
|
||
|
|
text: box.text
|
||
|
|
color: box.enabled ? "#ffffff" : "#666666"
|
||
|
|
font.pixelSize: 12
|
||
|
|
verticalAlignment: Text.AlignVCenter
|
||
|
|
}
|
||
|
|
|
||
|
|
onToggled: {
|
||
|
|
if (box.checked)
|
||
|
|
loaderRow.userChecked()
|
||
|
|
else
|
||
|
|
loaderRow.selectedVersion = ""
|
||
|
|
loaderRow.reload()
|
||
|
|
loaderRow.changed()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
DarkCombo {
|
||
|
|
id: combo
|
||
|
|
visible: box.checked && loaderRow.entries.length > 0
|
||
|
|
width: loaderRow.width - 26
|
||
|
|
height: 32
|
||
|
|
x: 26
|
||
|
|
model: loaderRow.entries.map(entry => entry.label)
|
||
|
|
|
||
|
|
onActivated: (index) => {
|
||
|
|
if (index < 0 || index >= loaderRow.entries.length)
|
||
|
|
return
|
||
|
|
loaderRow.selectedVersion = loaderRow.entries[index].version
|
||
|
|
loaderRow.changed()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
Text {
|
||
|
|
visible: box.checked && loaderRow.entries.length === 0
|
||
|
|
x: 26
|
||
|
|
width: loaderRow.width - 26
|
||
|
|
wrapMode: Text.Wrap
|
||
|
|
font.pixelSize: 11
|
||
|
|
color: loaderRow.backend.loaderVersionsLoading(loaderRow.loaderKey, loaderRow.gameVersion)
|
||
|
|
? "#888888" : "#cc6666"
|
||
|
|
text: loaderRow.backend.loaderVersionsLoading(loaderRow.loaderKey, loaderRow.gameVersion)
|
||
|
|
? qsTr("Загрузка списка версий %1…").arg(loaderRow.title)
|
||
|
|
: qsTr("%1 не поддерживает Minecraft %2").arg(loaderRow.title)
|
||
|
|
.arg(loaderRow.gameVersion)
|
||
|
|
}
|
||
|
|
}
|