diff options
-rw-r--r-- | api/logic/CMakeLists.txt | 2 | ||||
-rw-r--r-- | api/logic/minecraft/MinecraftInstance.cpp | 10 | ||||
-rw-r--r-- | api/logic/minecraft/MinecraftInstance.h | 4 | ||||
-rw-r--r-- | api/logic/minecraft/gameoptions/GameOptions.cpp | 144 | ||||
-rw-r--r-- | api/logic/minecraft/gameoptions/GameOptions.h | 34 | ||||
-rw-r--r-- | application/CMakeLists.txt | 3 | ||||
-rw-r--r-- | application/InstancePageProvider.h | 2 | ||||
-rw-r--r-- | application/pages/instance/GameOptionsPage.cpp | 40 | ||||
-rw-r--r-- | application/pages/instance/GameOptionsPage.h | 63 | ||||
-rw-r--r-- | application/pages/instance/GameOptionsPage.ui | 88 |
10 files changed, 389 insertions, 1 deletions
diff --git a/api/logic/CMakeLists.txt b/api/logic/CMakeLists.txt index 45b01b9f..57a197be 100644 --- a/api/logic/CMakeLists.txt +++ b/api/logic/CMakeLists.txt @@ -211,6 +211,8 @@ set(MINECRAFT_SOURCES minecraft/auth/flows/RefreshTask.cpp minecraft/auth/flows/ValidateTask.h minecraft/auth/flows/ValidateTask.cpp + minecraft/gameoptions/GameOptions.h + minecraft/gameoptions/GameOptions.cpp minecraft/update/AssetUpdateTask.h minecraft/update/AssetUpdateTask.cpp minecraft/update/FMLLibrariesTask.cpp diff --git a/api/logic/minecraft/MinecraftInstance.cpp b/api/logic/minecraft/MinecraftInstance.cpp index fecb951a..bf4eb1bd 100644 --- a/api/logic/minecraft/MinecraftInstance.cpp +++ b/api/logic/minecraft/MinecraftInstance.cpp @@ -35,6 +35,7 @@ #include "AssetsUtils.h" #include "MinecraftUpdate.h" #include "MinecraftLoadAndCheck.h" +#include <minecraft/gameoptions/GameOptions.h> #define IBUS "@im=ibus" @@ -935,6 +936,15 @@ std::shared_ptr<WorldList> MinecraftInstance::worldList() const return m_world_list; } +std::shared_ptr<GameOptions> MinecraftInstance::gameOptionsModel() const +{ + if (!m_game_options) + { + m_game_options.reset(new GameOptions(FS::PathCombine(gameRoot(), "options.txt"))); + } + return m_game_options; +} + QList< Mod > MinecraftInstance::getJarMods() const { auto profile = m_components->getProfile(); diff --git a/api/logic/minecraft/MinecraftInstance.h b/api/logic/minecraft/MinecraftInstance.h index 5f0fa353..091d1bf7 100644 --- a/api/logic/minecraft/MinecraftInstance.h +++ b/api/logic/minecraft/MinecraftInstance.h @@ -9,6 +9,7 @@ class ModsModel; class SimpleModList; class WorldList; +class GameOptions; class LaunchStep; class ComponentList; @@ -72,7 +73,7 @@ public: std::shared_ptr<SimpleModList> resourcePackList() const; std::shared_ptr<SimpleModList> texturePackList() const; std::shared_ptr<WorldList> worldList() const; - + std::shared_ptr<GameOptions> gameOptionsModel() const; ////// Launch stuff ////// shared_qobject_ptr<Task> createUpdateTask(Net::Mode mode) override; @@ -130,6 +131,7 @@ protected: // data mutable std::shared_ptr<SimpleModList> m_resource_pack_list; mutable std::shared_ptr<SimpleModList> m_texture_pack_list; mutable std::shared_ptr<WorldList> m_world_list; + mutable std::shared_ptr<GameOptions> m_game_options; }; typedef std::shared_ptr<MinecraftInstance> MinecraftInstancePtr; diff --git a/api/logic/minecraft/gameoptions/GameOptions.cpp b/api/logic/minecraft/gameoptions/GameOptions.cpp new file mode 100644 index 00000000..5dab8b86 --- /dev/null +++ b/api/logic/minecraft/gameoptions/GameOptions.cpp @@ -0,0 +1,144 @@ +#include "GameOptions.h" +#include "FileSystem.h" +#include <QDebug> +#include <QSaveFile> + +namespace { +bool load(const QString& path, std::vector<GameOptionItem> &contents, int & version) +{ + contents.clear(); + QFile file(path); + if (!file.open(QFile::ReadOnly)) + { + qWarning() << "Failed to read options file."; + return false; + } + version = 0; + while(!file.atEnd()) + { + auto line = file.readLine(); + if(line.back() == '\n') + { + line.chop(1); + } + auto separatorIndex = line.indexOf(':'); + if(separatorIndex == -1) + { + continue; + } + auto key = QString::fromUtf8(line.data(), separatorIndex); + auto value = QString::fromUtf8(line.data() + separatorIndex + 1, line.size() - 1 - separatorIndex); + qDebug() << "!!" << key << "!!"; + if(key == "version") + { + version = value.toInt(); + continue; + } + contents.emplace_back(GameOptionItem{key, value}); + } + qDebug() << "Loaded" << path << "with version:" << version; + return true; +} +bool save(const QString& path, std::vector<GameOptionItem> &mapping, int version) +{ + QSaveFile out(path); + if(!out.open(QIODevice::WriteOnly)) + { + return false; + } + if(version != 0) + { + QString versionLine = QString("version:%1\n").arg(version); + out.write(versionLine.toUtf8()); + } + auto iter = mapping.begin(); + while (iter != mapping.end()) + { + out.write(iter->key.toUtf8()); + out.write(":"); + out.write(iter->value.toUtf8()); + out.write("\n"); + iter++; + } + return out.commit(); +} +} + +GameOptions::GameOptions(const QString& path): + path(path) +{ + reload(); +} + +QVariant GameOptions::headerData(int section, Qt::Orientation orientation, int role) const +{ + if(role != Qt::DisplayRole) + { + return QAbstractListModel::headerData(section, orientation, role); + } + switch(section) + { + case 0: + return tr("Key"); + case 1: + return tr("Value"); + default: + return QVariant(); + } +} + +QVariant GameOptions::data(const QModelIndex& index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + int row = index.row(); + int column = index.column(); + + if (row < 0 || row >= int(contents.size())) + return QVariant(); + + switch (role) + { + case Qt::DisplayRole: + if(column == 0) + { + return contents[row].key; + } + else + { + return contents[row].value; + } + default: + return QVariant(); + } + return QVariant(); +} + +int GameOptions::rowCount(const QModelIndex&) const +{ + return contents.size(); +} + +int GameOptions::columnCount(const QModelIndex&) const +{ + return 2; +} + +bool GameOptions::isLoaded() const +{ + return loaded; +} + +bool GameOptions::reload() +{ + beginResetModel(); + loaded = load(path, contents, version); + endResetModel(); + return loaded; +} + +bool GameOptions::save() +{ + return ::save(path, contents, version); +} diff --git a/api/logic/minecraft/gameoptions/GameOptions.h b/api/logic/minecraft/gameoptions/GameOptions.h new file mode 100644 index 00000000..c6d25492 --- /dev/null +++ b/api/logic/minecraft/gameoptions/GameOptions.h @@ -0,0 +1,34 @@ +#pragma once + +#include <map> +#include <QString> +#include <QAbstractListModel> + +struct GameOptionItem +{ + QString key; + QString value; +}; + +class GameOptions : public QAbstractListModel +{ + Q_OBJECT +public: + explicit GameOptions(const QString& path); + virtual ~GameOptions() = default; + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex & parent) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + + bool isLoaded() const; + bool reload(); + bool save(); + +private: + std::vector<GameOptionItem> contents; + bool loaded = false; + QString path; + int version = 0; +}; diff --git a/application/CMakeLists.txt b/application/CMakeLists.txt index 30ef7268..26852df0 100644 --- a/application/CMakeLists.txt +++ b/application/CMakeLists.txt @@ -84,6 +84,8 @@ SET(MULTIMC_SOURCES pages/BasePageProvider.h # GUI - instance pages + pages/instance/GameOptionsPage.cpp + pages/instance/GameOptionsPage.h pages/instance/VersionPage.cpp pages/instance/VersionPage.h pages/instance/TexturePackPage.h @@ -229,6 +231,7 @@ SET(MULTIMC_SOURCES ######## UIs ######## SET(MULTIMC_UIS # Instance pages + pages/instance/GameOptionsPage.ui pages/instance/VersionPage.ui pages/instance/ModFolderPage.ui pages/instance/LogPage.ui diff --git a/application/InstancePageProvider.h b/application/InstancePageProvider.h index e72ba797..db57941e 100644 --- a/application/InstancePageProvider.h +++ b/application/InstancePageProvider.h @@ -16,6 +16,7 @@ #include "pages/instance/LegacyUpgradePage.h" #include "pages/instance/WorldListPage.h" #include "pages/instance/ServersPage.h" +#include "pages/instance/GameOptionsPage.h" #include "Env.h" @@ -46,6 +47,7 @@ public: values.append(new NotesPage(onesix.get())); values.append(new WorldListPage(onesix.get(), onesix->worldList(), "worlds", "worlds", tr("Worlds"), "Worlds")); values.append(new ServersPage(onesix.get())); + values.append(new GameOptionsPage(onesix.get())); values.append(new ScreenshotsPage(FS::PathCombine(onesix->gameRoot(), "screenshots"))); values.append(new InstanceSettingsPage(onesix.get())); } diff --git a/application/pages/instance/GameOptionsPage.cpp b/application/pages/instance/GameOptionsPage.cpp new file mode 100644 index 00000000..5555fc79 --- /dev/null +++ b/application/pages/instance/GameOptionsPage.cpp @@ -0,0 +1,40 @@ +#include "GameOptionsPage.h" +#include "ui_GameOptionsPage.h" +#include "minecraft/MinecraftInstance.h" +#include "minecraft/gameoptions/GameOptions.h" + +GameOptionsPage::GameOptionsPage(MinecraftInstance * inst, QWidget* parent) + : QWidget(parent), ui(new Ui::GameOptionsPage) +{ + ui->setupUi(this); + ui->tabWidget->tabBar()->hide(); + m_model = inst->gameOptionsModel(); + ui->optionsView->setModel(m_model.get()); + auto head = ui->optionsView->header(); + if(head->count()) + { + head->setSectionResizeMode(0, QHeaderView::ResizeToContents); + for(int i = 1; i < head->count(); i++) + { + head->setSectionResizeMode(i, QHeaderView::Stretch); + } + } +} + +GameOptionsPage::~GameOptionsPage() +{ + // m_model->save(); +} + +void GameOptionsPage::openedImpl() +{ + // m_model->observe(); +} + +void GameOptionsPage::closedImpl() +{ + // m_model->unobserve(); +} + +#include "GameOptionsPage.moc" + diff --git a/application/pages/instance/GameOptionsPage.h b/application/pages/instance/GameOptionsPage.h new file mode 100644 index 00000000..ae47747f --- /dev/null +++ b/application/pages/instance/GameOptionsPage.h @@ -0,0 +1,63 @@ +/* Copyright 2013-2019 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <QWidget> +#include <QString> + +#include "pages/BasePage.h" +#include <MultiMC.h> + +namespace Ui +{ +class GameOptionsPage; +} + +class GameOptions; +class MinecraftInstance; + +class GameOptionsPage : public QWidget, public BasePage +{ + Q_OBJECT + +public: + explicit GameOptionsPage(MinecraftInstance *inst, QWidget *parent = 0); + virtual ~GameOptionsPage(); + + void openedImpl() override; + void closedImpl() override; + + virtual QString displayName() const override + { + return tr("Game Options"); + } + virtual QIcon icon() const override + { + return MMC->getThemedIcon("settings"); + } + virtual QString id() const override + { + return "gameoptions"; + } + virtual QString helpPage() const override + { + return "Game-Options-management"; + } + +private: // data + Ui::GameOptionsPage *ui = nullptr; + std::shared_ptr<GameOptions> m_model; +}; diff --git a/application/pages/instance/GameOptionsPage.ui b/application/pages/instance/GameOptionsPage.ui new file mode 100644 index 00000000..f0a5ce0e --- /dev/null +++ b/application/pages/instance/GameOptionsPage.ui @@ -0,0 +1,88 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>GameOptionsPage</class> + <widget class="QWidget" name="GameOptionsPage"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>706</width> + <height>575</height> + </rect> + </property> + <layout class="QGridLayout" name="gridLayout"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item row="0" column="0"> + <widget class="QTabWidget" name="tabWidget"> + <property name="currentIndex"> + <number>0</number> + </property> + <widget class="QWidget" name="tab"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <attribute name="title"> + <string notr="true">Tab 1</string> + </attribute> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="0" colspan="2"> + <widget class="QTreeView" name="optionsView"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="acceptDrops"> + <bool>true</bool> + </property> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::SingleSelection</enum> + </property> + <property name="selectionBehavior"> + <enum>QAbstractItemView::SelectRows</enum> + </property> + <property name="iconSize"> + <size> + <width>64</width> + <height>64</height> + </size> + </property> + <property name="rootIsDecorated"> + <bool>false</bool> + </property> + <attribute name="headerStretchLastSection"> + <bool>false</bool> + </attribute> + </widget> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> + <tabstops> + <tabstop>tabWidget</tabstop> + <tabstop>optionsView</tabstop> + </tabstops> + <resources/> + <connections/> +</ui> |