@ -248,6 +248,8 @@ set(MINECRAFT_SOURCES
|
|||||||
minecraft/gameoptions/GameOptions.cpp
|
minecraft/gameoptions/GameOptions.cpp
|
||||||
minecraft/gameoptions/GameOptionsSchema.h
|
minecraft/gameoptions/GameOptionsSchema.h
|
||||||
minecraft/gameoptions/GameOptionsSchema.cpp
|
minecraft/gameoptions/GameOptionsSchema.cpp
|
||||||
|
minecraft/gameoptions/GameOptionDelegate.h
|
||||||
|
minecraft/gameoptions/GameOptionDelegate.cpp
|
||||||
|
|
||||||
minecraft/update/AssetUpdateTask.h
|
minecraft/update/AssetUpdateTask.h
|
||||||
minecraft/update/AssetUpdateTask.cpp
|
minecraft/update/AssetUpdateTask.cpp
|
||||||
|
199
launcher/minecraft/gameoptions/GameOptionDelegate.cpp
Normal file
199
launcher/minecraft/gameoptions/GameOptionDelegate.cpp
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (C) 2023 Tayou <tayou@gmx.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include "GameOptionDelegate.h"
|
||||||
|
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QCheckBox>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QSpinBox>
|
||||||
|
#include <QDoubleSpinBox>
|
||||||
|
#include <QSlider>
|
||||||
|
#include <QKeySequenceEdit>
|
||||||
|
|
||||||
|
QWidget* GameOptionDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const {
|
||||||
|
std::shared_ptr<GameOption> knownOption = contents->at(index.row()).knownOption;
|
||||||
|
|
||||||
|
switch (contents->at(index.row()).type) {
|
||||||
|
case OptionType::String: {
|
||||||
|
if (knownOption != nullptr && !knownOption->validValues.isEmpty()) {
|
||||||
|
QComboBox* comboBox = new QComboBox(parent);
|
||||||
|
for (auto value : knownOption->validValues) {
|
||||||
|
comboBox->addItem(value);
|
||||||
|
}
|
||||||
|
comboBox->setGeometry(option.rect);
|
||||||
|
return comboBox;
|
||||||
|
} else {
|
||||||
|
QLineEdit* textField = new QLineEdit(parent);
|
||||||
|
textField->setGeometry(option.rect);
|
||||||
|
return textField;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case OptionType::Int: {
|
||||||
|
if (knownOption != nullptr && (knownOption->getIntRange().max != 0 || knownOption->getIntRange().min != 0)) {
|
||||||
|
QSlider* slider = new QSlider(parent);
|
||||||
|
slider->setMinimum(knownOption->getIntRange().min);
|
||||||
|
slider->setMaximum(knownOption->getIntRange().max);
|
||||||
|
slider->setOrientation(Qt::Horizontal);
|
||||||
|
slider->setGeometry(option.rect);
|
||||||
|
return slider;
|
||||||
|
} else {
|
||||||
|
QSpinBox* intInput = new QSpinBox(parent);
|
||||||
|
intInput->setGeometry(option.rect);
|
||||||
|
return intInput;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case OptionType::Bool: {
|
||||||
|
QCheckBox* checkBox = new QCheckBox(parent);
|
||||||
|
checkBox->setGeometry(option.rect);
|
||||||
|
return checkBox;
|
||||||
|
}
|
||||||
|
case OptionType::Float: {
|
||||||
|
if (knownOption != nullptr && (knownOption->getFloatRange().max != 0 || knownOption->getFloatRange().min != 0)) {
|
||||||
|
QSlider* slider = new QSlider(parent);
|
||||||
|
slider->setMinimum(knownOption->getFloatRange().min*100);
|
||||||
|
slider->setMaximum(knownOption->getFloatRange().max*100);
|
||||||
|
slider->setOrientation(Qt::Horizontal);
|
||||||
|
slider->setGeometry(option.rect);
|
||||||
|
return slider;
|
||||||
|
} else {
|
||||||
|
QDoubleSpinBox* floatInput = new QDoubleSpinBox(parent);
|
||||||
|
floatInput->setGeometry(option.rect);
|
||||||
|
return floatInput;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case OptionType::KeyBind: {
|
||||||
|
QKeySequenceEdit* keySequenceEdit = new QKeySequenceEdit(parent);
|
||||||
|
keySequenceEdit->setGeometry(option.rect);
|
||||||
|
return keySequenceEdit;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
void GameOptionDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
|
||||||
|
{
|
||||||
|
std::shared_ptr<GameOption> knownOption = contents->at(index.row()).knownOption;
|
||||||
|
|
||||||
|
switch (contents->at(index.row()).type) {
|
||||||
|
case OptionType::String: {
|
||||||
|
QComboBox* comboBox;
|
||||||
|
if ((comboBox = dynamic_cast<QComboBox*>(editor)) != nullptr) {
|
||||||
|
comboBox->setCurrentIndex(comboBox->findText(contents->at(index.row()).value));
|
||||||
|
} else {
|
||||||
|
((QLineEdit*)editor)->setText(contents->at(index.row()).value);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case OptionType::Int: {
|
||||||
|
QSlider* slider;
|
||||||
|
if ((slider = dynamic_cast<QSlider*>(editor)) != nullptr) {
|
||||||
|
slider->setValue(contents->at(index.row()).intValue);
|
||||||
|
} else {
|
||||||
|
((QSpinBox*)editor)->setValue(contents->at(index.row()).intValue);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case OptionType::Bool: {
|
||||||
|
((QCheckBox*)editor)->setText(contents->at(index.row()).value);
|
||||||
|
((QCheckBox*)editor)->setChecked(contents->at(index.row()).boolValue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case OptionType::Float: {
|
||||||
|
QSlider* slider;
|
||||||
|
if ((slider = dynamic_cast<QSlider*>(editor)) != nullptr) {
|
||||||
|
slider->setValue(contents->at(index.row()).floatValue*100);
|
||||||
|
} else {
|
||||||
|
((QDoubleSpinBox*)editor)->setValue(contents->at(index.row()).floatValue);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case OptionType::KeyBind: {
|
||||||
|
// TODO: fall back to QLineEdit if keybind can't be represented, like some mods do (by using another key input API)
|
||||||
|
// TODO: mouse binding? If not possible, fall back as well maybe?
|
||||||
|
Qt::Key key;
|
||||||
|
for (auto& keyBinding : *keybindingOptions) {
|
||||||
|
// this could become a std::find_if eventually, if someone wants to bother making it that.
|
||||||
|
if (keyBinding->minecraftKeyCode == contents->at(index.row()).value) {
|
||||||
|
key = keyBinding->qtKeyCode.keyboardKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
((QKeySequenceEdit*)editor)->setKeySequence(QKeySequence(key));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
void GameOptionDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const {
|
||||||
|
editor->setGeometry(option.rect);
|
||||||
|
};
|
||||||
|
void GameOptionDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const {
|
||||||
|
std::shared_ptr<GameOption> knownOption = contents->at(index.row()).knownOption;
|
||||||
|
|
||||||
|
switch (contents->at(index.row()).type) {
|
||||||
|
case OptionType::String: {
|
||||||
|
QComboBox* comboBox;
|
||||||
|
if ((comboBox = dynamic_cast<QComboBox*>(editor)) != nullptr) {
|
||||||
|
contents->at(index.row()).value = comboBox->currentText();
|
||||||
|
} else {
|
||||||
|
contents->at(index.row()).value = ((QLineEdit*)editor)->text();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case OptionType::Int: {
|
||||||
|
QSlider* slider;
|
||||||
|
if ((slider = dynamic_cast<QSlider*>(editor)) != nullptr) {
|
||||||
|
contents->at(index.row()).intValue = slider->value();
|
||||||
|
} else {
|
||||||
|
contents->at(index.row()).intValue = ((QSpinBox*)editor)->value();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case OptionType::Bool: {
|
||||||
|
((QCheckBox*)editor)->setText(contents->at(index.row()).value);
|
||||||
|
contents->at(index.row()).boolValue = ((QCheckBox*)editor)->isChecked();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case OptionType::Float: {
|
||||||
|
QSlider* slider;
|
||||||
|
if ((slider = dynamic_cast<QSlider*>(editor)) != nullptr) {
|
||||||
|
contents->at(index.row()).floatValue = slider->value()/100.0f;
|
||||||
|
} else {
|
||||||
|
contents->at(index.row()).floatValue = ((QDoubleSpinBox*)editor)->value();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case OptionType::KeyBind: {
|
||||||
|
QKeySequenceEdit* keySequenceEdit = (QKeySequenceEdit*)editor;
|
||||||
|
|
||||||
|
QString minecraftKeyCode;
|
||||||
|
for (auto& keyBinding : *keybindingOptions) {
|
||||||
|
// this could become a std::find_if eventually, if someone wants to bother making it that.
|
||||||
|
if (keyBinding->qtKeyCode.keyboardKey == keySequenceEdit->keySequence()[0].key() ||
|
||||||
|
keyBinding->qtKeyCode.mouseButton == keySequenceEdit->keySequence()[0].key()) {
|
||||||
|
minecraftKeyCode = keyBinding->minecraftKeyCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contents->at(index.row()).value = minecraftKeyCode;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
44
launcher/minecraft/gameoptions/GameOptionDelegate.h
Normal file
44
launcher/minecraft/gameoptions/GameOptionDelegate.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* Prism Launcher - Minecraft Launcher
|
||||||
|
* Copyright (C) 2023 Tayou <tayou@gmx.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QStyledItemDelegate>
|
||||||
|
#include <QString>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
#include "GameOptions.h"
|
||||||
|
|
||||||
|
class GameOptionDelegate : public QStyledItemDelegate {
|
||||||
|
public:
|
||||||
|
GameOptionDelegate(QObject* parent, std::vector<GameOptionItem>* contents) : contents(contents), QStyledItemDelegate(parent)
|
||||||
|
{
|
||||||
|
keybindingOptions = GameOptionsSchema::getKeyBindOptions();
|
||||||
|
};
|
||||||
|
QWidget* createEditor(QWidget* parent,
|
||||||
|
const QStyleOptionViewItem& option,
|
||||||
|
const QModelIndex& index) const override;
|
||||||
|
void setEditorData(QWidget* editor, const QModelIndex& index) const override;
|
||||||
|
void updateEditorGeometry(QWidget* editor,
|
||||||
|
const QStyleOptionViewItem& option,
|
||||||
|
const QModelIndex& index) const override;
|
||||||
|
void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<GameOptionItem>* contents;
|
||||||
|
QList<std::shared_ptr<KeyBindData>>* keybindingOptions;
|
||||||
|
};
|
@ -110,6 +110,9 @@ bool load(const QString& path,
|
|||||||
}
|
}
|
||||||
} else if (item.key.startsWith("key_")) {
|
} else if (item.key.startsWith("key_")) {
|
||||||
item.type = OptionType::KeyBind;
|
item.type = OptionType::KeyBind;
|
||||||
|
} else {
|
||||||
|
// this is really ugly, please suggest how to truncate the start and end
|
||||||
|
item.value = item.value.remove(item.value.length()-1, 1).remove(0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// adds reference to known option from gameOptionsSchema if avaiable to get display name and other metadata
|
// adds reference to known option from gameOptionsSchema if avaiable to get display name and other metadata
|
||||||
@ -210,9 +213,9 @@ Qt::ItemFlags GameOptions::flags(const QModelIndex& index) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
flags = flags | Qt::ItemFlag::ItemIsEditable;
|
flags = flags | Qt::ItemFlag::ItemIsEditable;
|
||||||
if (column == Column::Value || column == Column::DefaultValue) {
|
/*if (column == Column::Value || column == Column::DefaultValue) {
|
||||||
flags = flags | Qt::ItemFlag::ItemIsUserCheckable;
|
flags = flags | Qt::ItemFlag::ItemIsUserCheckable;
|
||||||
}
|
}*/
|
||||||
if (column == Column::DefaultValue) {
|
if (column == Column::DefaultValue) {
|
||||||
flags = flags & ~Qt::ItemFlag::ItemIsEnabled;
|
flags = flags & ~Qt::ItemFlag::ItemIsEnabled;
|
||||||
}
|
}
|
||||||
|
@ -78,6 +78,8 @@ class GameOptions : public QAbstractItemModel {
|
|||||||
bool reload();
|
bool reload();
|
||||||
bool save();
|
bool save();
|
||||||
|
|
||||||
|
std::vector<GameOptionItem>* getContents(){ return &contents; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<GameOptionItem> contents;
|
std::vector<GameOptionItem> contents;
|
||||||
bool loaded = false;
|
bool loaded = false;
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
#include "GameOptionsPage.h"
|
#include "GameOptionsPage.h"
|
||||||
#include "minecraft/MinecraftInstance.h"
|
#include "minecraft/MinecraftInstance.h"
|
||||||
#include "minecraft/gameoptions/GameOptions.h"
|
#include "minecraft/gameoptions/GameOptions.h"
|
||||||
#include "ui_GameOptionsPage.h"
|
#include "minecraft/gameoptions/GameOptionDelegate.h"
|
||||||
|
|
||||||
GameOptionsPage::GameOptionsPage(MinecraftInstance* inst, QWidget* parent) : QWidget(parent), ui(new Ui::GameOptionsPage)
|
GameOptionsPage::GameOptionsPage(MinecraftInstance* inst, QWidget* parent) : QWidget(parent), ui(new Ui::GameOptionsPage)
|
||||||
{
|
{
|
||||||
@ -46,6 +46,8 @@ GameOptionsPage::GameOptionsPage(MinecraftInstance* inst, QWidget* parent) : QWi
|
|||||||
ui->tabWidget->tabBar()->hide();
|
ui->tabWidget->tabBar()->hide();
|
||||||
m_model = inst->gameOptionsModel();
|
m_model = inst->gameOptionsModel();
|
||||||
ui->optionsView->setModel(m_model.get());
|
ui->optionsView->setModel(m_model.get());
|
||||||
|
ui->optionsView->setItemDelegateForColumn(2, new GameOptionDelegate(ui->optionsView, m_model->getContents()));
|
||||||
|
ui->optionsView->setEditTriggers(QAbstractItemView::AllEditTriggers);
|
||||||
auto head = ui->optionsView->header();
|
auto head = ui->optionsView->header();
|
||||||
head->setDefaultSectionSize(250);
|
head->setDefaultSectionSize(250);
|
||||||
if (head->count()) {
|
if (head->count()) {
|
||||||
|
Reference in New Issue
Block a user