Merge branch 'develop' of https://github.com/PrismLauncher/PrismLauncher into net_job_crash

This commit is contained in:
Trial97 2023-06-18 23:27:41 +03:00
commit 6826f1d605
No known key found for this signature in database
GPG Key ID: 55EF5DA53DB36318
25 changed files with 316 additions and 73 deletions

View File

@ -138,7 +138,7 @@ set(Launcher_NEWS_OPEN_URL "https://prismlauncher.org/news" CACHE STRING "URL th
set(Launcher_HELP_URL "https://prismlauncher.org/wiki/help-pages/%1" CACHE STRING "URL (with arg %1 to be substituted with page-id) that gets opened when the user requests help")
######## Set version numbers ########
set(Launcher_VERSION_MAJOR 7)
set(Launcher_VERSION_MAJOR 8)
set(Launcher_VERSION_MINOR 0)
set(Launcher_VERSION_NAME "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}")

View File

@ -82,6 +82,7 @@ Config::Config()
{
GIT_REFSPEC = "refs/heads/stable";
GIT_TAG = versionString();
GIT_COMMIT = "";
}
if (GIT_REFSPEC.startsWith("refs/heads/"))

View File

@ -45,7 +45,10 @@ QString InstanceName::name() const
{
if (!m_modified_name.isEmpty())
return modifiedName();
return QString("%1 %2").arg(m_original_name, m_original_version);
if (!m_original_version.isEmpty())
return QString("%1 %2").arg(m_original_name, m_original_version);
return m_original_name;
}
QString InstanceName::originalName() const

View File

@ -1,7 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* PolyMC - Minecraft Launcher
* Prism Launcher - Minecraft Launcher
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
*
* 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
@ -54,9 +55,14 @@ public:
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
const auto &filters = m_parent->filters();
const QString &search = m_parent->search();
const QModelIndex idx = sourceModel()->index(source_row, 0, source_parent);
if (!search.isEmpty() && !sourceModel()->data(idx, BaseVersionList::VersionRole).toString().contains(search, Qt::CaseInsensitive))
return false;
for (auto it = filters.begin(); it != filters.end(); ++it)
{
auto idx = sourceModel()->index(source_row, 0, source_parent);
auto data = sourceModel()->data(idx, it.key());
auto match = data.toString();
if(!it.value()->accepts(match))
@ -206,10 +212,6 @@ QVariant VersionProxyModel::data(const QModelIndex &index, int role) const
return tr("Latest");
}
}
else if(index.row() == 0)
{
return tr("Latest");
}
}
}
default:
@ -239,10 +241,6 @@ QVariant VersionProxyModel::data(const QModelIndex &index, int role) const
return APPLICATION->getThemedIcon("bug");
}
}
else if(index.row() == 0)
{
return APPLICATION->getThemedIcon("bug");
}
QPixmap pixmap;
QPixmapCache::find("placeholder", &pixmap);
if(!pixmap)
@ -431,6 +429,7 @@ QModelIndex VersionProxyModel::getVersion(const QString& version) const
void VersionProxyModel::clearFilters()
{
m_filters.clear();
m_search.clear();
filterModel->filterChanged();
}
@ -440,11 +439,21 @@ void VersionProxyModel::setFilter(const BaseVersionList::ModelRoles column, Filt
filterModel->filterChanged();
}
void VersionProxyModel::setSearch(const QString &search) {
m_search = search;
filterModel->filterChanged();
}
const VersionProxyModel::FilterMap &VersionProxyModel::filters() const
{
return m_filters;
}
const QString &VersionProxyModel::search() const
{
return m_search;
}
void VersionProxyModel::sourceAboutToBeReset()
{
beginResetModel();

View File

@ -38,7 +38,9 @@ public:
virtual void setSourceModel(QAbstractItemModel *sourceModel) override;
const FilterMap &filters() const;
const QString &search() const;
void setFilter(const BaseVersionList::ModelRoles column, Filter * filter);
void setSearch(const QString &search);
void clearFilters();
QModelIndex getRecommended() const;
QModelIndex getVersion(const QString & version) const;
@ -59,6 +61,7 @@ private slots:
private:
QList<Column> m_columns;
FilterMap m_filters;
QString m_search;
BaseVersionList::RoleList roles;
VersionFilterModel * filterModel;
bool hasRecommended = false;

View File

@ -1,7 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* PolyMC - Minecraft Launcher
* Prism Launcher - Minecraft Launcher
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
*
* 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
@ -98,6 +99,8 @@ QVariant JavaInstallList::data(const QModelIndex &index, int role) const
auto version = std::dynamic_pointer_cast<JavaInstall>(m_vlist[index.row()]);
switch (role)
{
case SortRole:
return -index.row();
case VersionPointerRole:
return QVariant::fromValue(m_vlist[index.row()]);
case VersionIdRole:

View File

@ -50,7 +50,7 @@ INIFile::INIFile() {}
bool INIFile::saveFile(QString fileName)
{
if (!contains("ConfigVersion"))
insert("ConfigVersion", "1.1");
insert("ConfigVersion", "1.2");
QSettings _settings_obj{ fileName, QSettings::Format::IniFormat };
_settings_obj.setFallbacksEnabled(false);
@ -97,6 +97,20 @@ QString unescape(QString orig)
}
return out;
}
QString unquote(QString str)
{
if ((str.contains(QChar(';')) || str.contains(QChar('=')) || str.contains(QChar(','))) && str.endsWith("\"") && str.startsWith("\"")) {
#if QT_VERSION < QT_VERSION_CHECK(6, 5, 0)
str = str.remove(0, 1);
str = str.remove(str.size() - 1, 1);
#else
str = str.removeFirst().removeLast();
#endif
}
return str;
}
bool parseOldFileFormat(QIODevice& device, QSettings::SettingsMap& map)
{
QTextStream in(device.readAll());
@ -124,7 +138,7 @@ bool parseOldFileFormat(QIODevice& device, QSettings::SettingsMap& map)
QString key = line.left(eqPos).trimmed();
QString valueStr = line.right(line.length() - eqPos - 1).trimmed();
valueStr = unescape(valueStr);
valueStr = unquote(unescape(valueStr));
QVariant value(valueStr);
map.insert(key, value);
@ -154,7 +168,17 @@ bool INIFile::loadFile(QString fileName)
file.close();
for (auto&& key : map.keys())
insert(key, map.value(key));
insert("ConfigVersion", "1.1");
insert("ConfigVersion", "1.2");
} else if (_settings_obj.value("ConfigVersion").toString() == "1.1") {
for (auto&& key : _settings_obj.allKeys()) {
if (auto valueStr = _settings_obj.value(key).toString();
(valueStr.contains(QChar(';')) || valueStr.contains(QChar('=')) || valueStr.contains(QChar(','))) &&
valueStr.endsWith("\"") && valueStr.startsWith("\"")) {
insert(key, unquote(valueStr));
} else
insert(key, _settings_obj.value(key));
}
insert("ConfigVersion", "1.2");
} else
for (auto&& key : _settings_obj.allKeys())
insert(key, _settings_obj.value(key));

View File

@ -1,16 +1,36 @@
/* Copyright 2013-2021 MultiMC Contributors
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
*
* 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
* 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.
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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.
*
* 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.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This file incorporates work covered by the following copyright and
* permission notice:
*
* Copyright 2013-2021 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.
*/
#include "VersionSelectDialog.h"
@ -22,15 +42,10 @@
#include <QtWidgets/QVBoxLayout>
#include <QDebug>
#include "ui/dialogs/ProgressDialog.h"
#include "ui/widgets/VersionSelectWidget.h"
#include "ui/dialogs/CustomMessageBox.h"
#include "BaseVersion.h"
#include "BaseVersionList.h"
#include "tasks/Task.h"
#include "Application.h"
#include "VersionProxyModel.h"
VersionSelectDialog::VersionSelectDialog(BaseVersionList *vlist, QString title, QWidget *parent, bool cancelable)
: QDialog(parent)
@ -40,7 +55,7 @@ VersionSelectDialog::VersionSelectDialog(BaseVersionList *vlist, QString title,
m_verticalLayout = new QVBoxLayout(this);
m_verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
m_versionWidget = new VersionSelectWidget(parent);
m_versionWidget = new VersionSelectWidget(true, parent);
m_verticalLayout->addWidget(m_versionWidget);
m_horizontalLayout = new QHBoxLayout();

View File

@ -6,12 +6,14 @@
#include "minecraft/MinecraftInstance.h"
#include "minecraft/PackProfile.h"
#include "minecraft/mod/ModFolderModel.h"
#include <QMessageBox>
#include <algorithm>
namespace ResourceDownload {
ModModel::ModModel(BaseInstance const& base_inst, ResourceAPI* api) : ResourceModel(api), m_base_instance(base_inst) {}
ModModel::ModModel(BaseInstance& base_inst, ResourceAPI* api) : ResourceModel(api), m_base_instance(base_inst) {}
/******** Make data requests ********/
@ -24,7 +26,7 @@ ResourceAPI::SearchArgs ModModel::createSearchArguments()
std::optional<std::list<Version>> versions{};
{ // Version filter
{ // Version filter
if (!m_filter->versions.empty())
versions = m_filter->versions;
}
@ -67,4 +69,14 @@ void ModModel::searchWithTerm(const QString& term, unsigned int sort, bool filte
refresh();
}
bool ModModel::isPackInstalled(ModPlatform::IndexedPack::Ptr pack) const
{
auto allMods = static_cast<MinecraftInstance&>(m_base_instance).loaderModList()->allMods();
return std::any_of(allMods.cbegin(), allMods.cend(), [pack](Mod* mod) {
if (auto meta = mod->metadata(); meta)
return meta->provider == pack->provider && meta->project_id == pack->addonId;
return false;
});
}
} // namespace ResourceDownload

View File

@ -24,7 +24,7 @@ class ModModel : public ResourceModel {
Q_OBJECT
public:
ModModel(const BaseInstance&, ResourceAPI* api);
ModModel(BaseInstance&, ResourceAPI* api);
/* Ask the API for more information */
void searchWithTerm(const QString& term, unsigned int sort, bool filter_changed);
@ -42,9 +42,10 @@ class ModModel : public ResourceModel {
protected:
auto documentToArray(QJsonDocument& obj) const -> QJsonArray override = 0;
virtual bool isPackInstalled(ModPlatform::IndexedPack::Ptr) const override;
protected:
const BaseInstance& m_base_instance;
BaseInstance& m_base_instance;
std::shared_ptr<ModFilterWidget::Filter> m_filter = nullptr;
};

View File

@ -77,6 +77,8 @@ auto ResourceModel::data(const QModelIndex& index, int role) const -> QVariant
return pack->description;
case UserDataTypes::SELECTED:
return pack->isAnyVersionSelected();
case UserDataTypes::INSTALLED:
return this->isPackInstalled(pack);
default:
break;
}
@ -95,6 +97,7 @@ QHash<int, QByteArray> ResourceModel::roleNames() const
roles[UserDataTypes::TITLE] = "title";
roles[UserDataTypes::DESCRIPTION] = "description";
roles[UserDataTypes::SELECTED] = "selected";
roles[UserDataTypes::INSTALLED] = "installed";
return roles;
}

View File

@ -116,6 +116,8 @@ class ResourceModel : public QAbstractListModel {
virtual void loadExtraPackInfo(ModPlatform::IndexedPack&, QJsonObject&);
virtual void loadIndexedPackVersions(ModPlatform::IndexedPack&, QJsonArray&);
virtual bool isPackInstalled(ModPlatform::IndexedPack::Ptr) const { return false; }
protected:
/* Basic search parameters */
enum class SearchState { None, CanFetchMore, ResetRequested, Finished } m_search_state = SearchState::None;

View File

@ -60,6 +60,8 @@ QVariant ListModel::data(const QModelIndex& index, int role) const
return pack.description;
case UserDataTypes::SELECTED:
return false;
case UserDataTypes::INSTALLED:
return false;
default:
break;
}

View File

@ -11,7 +11,7 @@
namespace ResourceDownload {
FlameModModel::FlameModModel(BaseInstance const& base) : ModModel(base, new FlameAPI) {}
FlameModModel::FlameModModel(BaseInstance& base) : ModModel(base, new FlameAPI) {}
void FlameModModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj)
{

View File

@ -14,7 +14,7 @@ class FlameModModel : public ModModel {
Q_OBJECT
public:
FlameModModel(const BaseInstance&);
FlameModModel(BaseInstance&);
~FlameModModel() override = default;
private:

View File

@ -106,6 +106,8 @@ auto ModpackListModel::data(const QModelIndex& index, int role) const -> QVarian
return pack.description;
case UserDataTypes::SELECTED:
return false;
case UserDataTypes::INSTALLED:
return false;
default:
break;
}

View File

@ -25,7 +25,7 @@
namespace ResourceDownload {
ModrinthModModel::ModrinthModModel(BaseInstance const& base) : ModModel(base, new ModrinthAPI) {}
ModrinthModModel::ModrinthModModel(BaseInstance& base) : ModModel(base, new ModrinthAPI) {}
void ModrinthModModel::loadIndexedPack(ModPlatform::IndexedPack& m, QJsonObject& obj)
{

View File

@ -30,7 +30,7 @@ class ModrinthModModel : public ModModel {
Q_OBJECT
public:
ModrinthModModel(const BaseInstance&);
ModrinthModModel(BaseInstance&);
~ModrinthModModel() override = default;
private:

View File

@ -46,7 +46,7 @@ void JavaSettingsWidget::setupUi()
m_verticalLayout = new QVBoxLayout(this);
m_verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
m_versionWidget = new VersionSelectWidget(this);
m_versionWidget = new VersionSelectWidget(true, this);
m_verticalLayout->addWidget(m_versionWidget);
m_horizontalLayout = new QHBoxLayout();

View File

@ -64,6 +64,17 @@ void ProjectItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& o
font.setBold(true);
font.setUnderline(true);
}
if (index.data(UserDataTypes::INSTALLED).toBool()) {
auto hRect = opt.rect;
hRect.setX(hRect.x() + 1);
hRect.setY(hRect.y() + 1);
hRect.setHeight(hRect.height() - 2);
hRect.setWidth(hRect.width() - 2);
// Set nice font
font.setItalic(true);
font.setOverline(true);
painter->drawRect(hRect);
}
font.setPointSize(font.pointSize() + 2);
painter->setFont(font);

View File

@ -6,7 +6,8 @@
enum UserDataTypes {
TITLE = 257, // QString
DESCRIPTION = 258, // QString
SELECTED = 259 // bool
SELECTED = 259, // bool
INSTALLED = 260 // bool
};
/** This is an item delegate composed of:

View File

@ -1,7 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* PolyMC - Minecraft Launcher
* Prism Launcher - Minecraft Launcher
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
*
* 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
@ -125,14 +126,9 @@ void VersionListView::paintEvent(QPaintEvent *event)
QString VersionListView::currentEmptyString() const
{
if(m_itemCount) {
return QString();
}
switch(m_emptyMode)
{
default:
case VersionListView::Empty:
return QString();
case VersionListView::String:
return m_emptyString;
case VersionListView::ErrorString:

View File

@ -1,15 +1,20 @@
#include "VersionSelectWidget.h"
#include <QApplication>
#include <QEvent>
#include <QHeaderView>
#include <QKeyEvent>
#include <QProgressBar>
#include <QVBoxLayout>
#include <QHeaderView>
#include "VersionProxyModel.h"
#include "ui/dialogs/CustomMessageBox.h"
VersionSelectWidget::VersionSelectWidget(QWidget* parent)
: QWidget(parent)
VersionSelectWidget::VersionSelectWidget(QWidget* parent) : VersionSelectWidget(false, parent) {}
VersionSelectWidget::VersionSelectWidget(bool focusSearch, QWidget* parent)
: QWidget(parent), focusSearch(focusSearch)
{
setObjectName(QStringLiteral("VersionSelectWidget"));
verticalLayout = new QVBoxLayout(this);
@ -30,6 +35,21 @@ VersionSelectWidget::VersionSelectWidget(QWidget* parent)
listView->setModel(m_proxyModel);
verticalLayout->addWidget(listView);
search = new QLineEdit(this);
search->setPlaceholderText(tr("Search"));
search->setClearButtonEnabled(true);
verticalLayout->addWidget(search);
connect(search, &QLineEdit::textEdited, [this](const QString& value) {
m_proxyModel->setSearch(value);
if (!value.isEmpty() || !listView->selectionModel()->hasSelection()) {
const QModelIndex first = listView->model()->index(0, 0);
listView->selectionModel()->setCurrentIndex(first, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
listView->scrollToTop();
} else
listView->scrollTo(listView->selectionModel()->currentIndex(), QAbstractItemView::PositionAtCenter);
});
search->installEventFilter(this);
sneakyProgressBar = new QProgressBar(this);
sneakyProgressBar->setObjectName(QStringLiteral("sneakyProgressBar"));
sneakyProgressBar->setFormat(QStringLiteral("%p%"));
@ -72,6 +92,23 @@ void VersionSelectWidget::setResizeOn(int column)
listView->header()->setSectionResizeMode(resizeOnColumn, QHeaderView::Stretch);
}
bool VersionSelectWidget::eventFilter(QObject *watched, QEvent *event) {
if (watched == search && event->type() == QEvent::KeyPress) {
const QKeyEvent* keyEvent = (QKeyEvent*)event;
const bool up = keyEvent->key() == Qt::Key_Up;
const bool down = keyEvent->key() == Qt::Key_Down;
if (up || down) {
const QModelIndex index = listView->model()->index(listView->currentIndex().row() + (up ? -1 : 1), 0);
if (index.row() >= 0 && index.row() < listView->model()->rowCount()) {
listView->selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
return true;
}
}
}
return QObject::eventFilter(watched, event);
}
void VersionSelectWidget::initialize(BaseVersionList *vlist)
{
m_vlist = vlist;
@ -79,6 +116,9 @@ void VersionSelectWidget::initialize(BaseVersionList *vlist)
listView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
listView->header()->setSectionResizeMode(resizeOnColumn, QHeaderView::Stretch);
if (focusSearch)
search->setFocus();
if (!m_vlist->isLoaded())
{
loadList();

View File

@ -1,22 +1,43 @@
/* Copyright 2013-2021 MultiMC Contributors
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
*
* 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
* 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.
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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.
*
* 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.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This file incorporates work covered by the following copyright and
* permission notice:
*
* Copyright 2013-2021 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 <QSortFilterProxyModel>
#include <QLineEdit>
#include "BaseVersionList.h"
#include "VersionListView.h"
@ -30,7 +51,8 @@ class VersionSelectWidget: public QWidget
{
Q_OBJECT
public:
explicit VersionSelectWidget(QWidget *parent = 0);
explicit VersionSelectWidget(QWidget *parent);
explicit VersionSelectWidget(bool focusSearch = false, QWidget *parent = 0);
~VersionSelectWidget();
//! loads the list if needed.
@ -52,6 +74,7 @@ public:
void setEmptyErrorString(QString emptyErrorString);
void setEmptyMode(VersionListView::EmptyMode mode);
void setResizeOn(int column);
bool eventFilter(QObject* watched, QEvent* event) override;
signals:
void selectedVersionChanged(BaseVersion::Ptr version);
@ -75,9 +98,10 @@ private:
int resizeOnColumn = 0;
Task * loadTask;
bool preselectedAlready = false;
bool focusSearch;
private:
QVBoxLayout *verticalLayout = nullptr;
VersionListView *listView = nullptr;
QLineEdit *search;
QProgressBar *sneakyProgressBar = nullptr;
};

View File

@ -2,7 +2,10 @@
#include <settings/INIFile.h>
#include <QList>
#include <QSettings>
#include <QTemporaryFile>
#include <QVariant>
#include "FileSystem.h"
#include <QVariantUtils.h>
@ -72,32 +75,120 @@ class IniFileTest : public QObject {
QCOMPARE(out_list_numbers, list_numbers);
}
void test_SaveAleardyExistingFile()
void test_SaveAlreadyExistingFile()
{
QString fileName = "test_SaveAleardyExistingFile.ini";
QString fileContent = R"(InstanceType=OneSix
iconKey=vanillia_icon
name=Minecraft Vanillia
OverrideCommands=true
PreLaunchCommand="$INST_JAVA" -jar packwiz-installer-bootstrap.jar link
)";
Wrapperommand=)";
fileContent += "\"";
fileContent += +R"(\"$INST_JAVA\" -jar packwiz-installer-bootstrap.jar link =)";
fileContent += "\"\n";
#if defined(Q_OS_WIN)
QString fileName = "test_SaveAlreadyExistingFile.ini";
QFile file(fileName);
if (file.open(QFile::WriteOnly | QFile::Text)) {
QTextStream stream(&file);
stream << fileContent;
file.close();
}
QCOMPARE(file.open(QFile::WriteOnly | QFile::Text), true);
#else
QTemporaryFile file;
QCOMPARE(file.open(), true);
QCOMPARE(file.fileName().isEmpty(), false);
QString fileName = file.fileName();
#endif
QTextStream stream(&file);
stream << fileContent;
file.close();
// load
INIFile f1;
f1.loadFile(fileName);
QCOMPARE(f1.get("PreLaunchCommand", "NOT SET").toString(), "\"$INST_JAVA\" -jar packwiz-installer-bootstrap.jar link");
QCOMPARE(f1.get("Wrapperommand", "NOT SET").toString(), "\"$INST_JAVA\" -jar packwiz-installer-bootstrap.jar link =");
f1.saveFile(fileName);
INIFile f2;
f2.loadFile(fileName);
QCOMPARE(f2.get("PreLaunchCommand", "NOT SET").toString(), "\"$INST_JAVA\" -jar packwiz-installer-bootstrap.jar link");
QCOMPARE(f2.get("ConfigVersion", "NOT SET").toString(), "1.1");
QCOMPARE(f2.get("Wrapperommand", "NOT SET").toString(), "\"$INST_JAVA\" -jar packwiz-installer-bootstrap.jar link =");
QCOMPARE(f2.get("ConfigVersion", "NOT SET").toString(), "1.2");
#if defined(Q_OS_WIN)
FS::deletePath(fileName);
#endif
}
void test_SaveAlreadyExistingFileWithSpecialChars()
{
#if defined(Q_OS_WIN)
QString fileName = "test_SaveAlreadyExistingFileWithSpecialChars.ini";
#else
QTemporaryFile file;
QCOMPARE(file.open(), true);
QCOMPARE(file.fileName().isEmpty(), false);
QString fileName = file.fileName();
file.close();
#endif
QSettings settings{ fileName, QSettings::Format::IniFormat };
settings.setFallbacksEnabled(false);
settings.setValue("simple", "value1");
settings.setValue("withQuotes", R"("value2" with quotes)");
settings.setValue("withSpecialCharacters", "env mesa=true");
settings.setValue("withSpecialCharacters2", "1,2,3,4");
settings.setValue("withSpecialCharacters2", "1;2;3;4");
settings.setValue("withAll", "val=\"$INST_JAVA\" -jar; ls ");
settings.sync();
QCOMPARE(settings.status(), QSettings::Status::NoError);
// load
INIFile f1;
f1.loadFile(fileName);
for (auto key : settings.allKeys())
QCOMPARE(f1.get(key, "NOT SET").toString(), settings.value(key).toString());
f1.saveFile(fileName);
INIFile f2;
f2.loadFile(fileName);
for (auto key : settings.allKeys())
QCOMPARE(f2.get(key, "NOT SET").toString(), settings.value(key).toString());
QCOMPARE(f2.get("ConfigVersion", "NOT SET").toString(), "1.2");
#if defined(Q_OS_WIN)
FS::deletePath(fileName);
#endif
}
void test_SaveAlreadyExistingFileWithSpecialCharsV1()
{
QString fileContent = R"(InstanceType=OneSix
ConfigVersion=1.1
iconKey=vanillia_icon
name=Minecraft Vanillia
OverrideCommands=true
PreLaunchCommand=)";
fileContent += "\"\\\"env mesa=true\\\"\"\n";
#if defined(Q_OS_WIN)
QString fileName = "test_SaveAlreadyExistingFileWithSpecialCharsV1.ini";
QFile file(fileName);
QCOMPARE(file.open(QFile::WriteOnly | QFile::Text), true);
#else
QTemporaryFile file;
QCOMPARE(file.open(), true);
QCOMPARE(file.fileName().isEmpty(), false);
QString fileName = file.fileName();
#endif
QTextStream stream(&file);
stream << fileContent;
file.close();
// load
INIFile f1;
f1.loadFile(fileName);
QCOMPARE(f1.get("PreLaunchCommand", "NOT SET").toString(), "env mesa=true");
QCOMPARE(f1.get("ConfigVersion", "NOT SET").toString(), "1.2");
#if defined(Q_OS_WIN)
FS::deletePath(fileName);
#endif
}
};