summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md6
-rw-r--r--cmake/UnitTest/TestUtil.h3
-rw-r--r--launcher/ApplicationMessage.cpp4
-rw-r--r--launcher/BaseInstance.cpp3
-rw-r--r--launcher/BaseVersionList.cpp2
-rw-r--r--launcher/CMakeLists.txt14
-rw-r--r--launcher/Commandline.cpp2
-rw-r--r--launcher/FileSystem.cpp3
-rw-r--r--launcher/GZip.cpp2
-rw-r--r--launcher/InstanceImportTask.cpp3
-rw-r--r--launcher/InstanceList.cpp6
-rw-r--r--launcher/JavaCommon.cpp3
-rw-r--r--launcher/Json.cpp16
-rw-r--r--launcher/LaunchController.cpp4
-rw-r--r--launcher/LoggedProcess.cpp8
-rw-r--r--launcher/MMCZip.cpp44
-rw-r--r--launcher/MMCZip.h9
-rw-r--r--launcher/QObjectPtr.h8
-rw-r--r--launcher/UpdateController.cpp3
-rw-r--r--launcher/Version.h4
-rw-r--r--launcher/VersionProxyModel.cpp7
-rw-r--r--launcher/icons/IconList.cpp4
-rw-r--r--launcher/java/JavaChecker.cpp6
-rw-r--r--launcher/java/JavaInstallList.cpp3
-rw-r--r--launcher/java/JavaVersion.cpp6
-rw-r--r--launcher/java/JavaVersion.h6
-rw-r--r--launcher/minecraft/ComponentUpdateTask.cpp8
-rw-r--r--launcher/minecraft/GradleSpecifier.h8
-rw-r--r--launcher/minecraft/Library_test.cpp3
-rw-r--r--launcher/minecraft/MinecraftInstance.cpp19
-rw-r--r--launcher/minecraft/MojangVersionFormat_test.cpp6
-rw-r--r--launcher/minecraft/OneSixVersionFormat.cpp2
-rw-r--r--launcher/minecraft/PackProfile.cpp2
-rw-r--r--launcher/minecraft/ProfileUtils.cpp2
-rw-r--r--launcher/minecraft/World.cpp2
-rw-r--r--launcher/minecraft/WorldList.cpp4
-rw-r--r--launcher/minecraft/auth/AccountData.cpp157
-rw-r--r--launcher/minecraft/auth/AccountData.h17
-rw-r--r--launcher/minecraft/auth/AccountList.cpp59
-rw-r--r--launcher/minecraft/auth/AccountList.h2
-rw-r--r--launcher/minecraft/auth/AccountTask.h3
-rw-r--r--launcher/minecraft/auth/AuthRequest.cpp4
-rw-r--r--launcher/minecraft/auth/AuthStep.h3
-rw-r--r--launcher/minecraft/auth/MinecraftAccount.cpp54
-rw-r--r--launcher/minecraft/auth/MinecraftAccount.h32
-rw-r--r--launcher/minecraft/auth/Yggdrasil.cpp331
-rw-r--r--launcher/minecraft/auth/Yggdrasil.h102
-rw-r--r--launcher/minecraft/auth/flows/AuthFlow.cpp3
-rw-r--r--launcher/minecraft/auth/flows/AuthFlow.h5
-rw-r--r--launcher/minecraft/auth/flows/Mojang.cpp27
-rw-r--r--launcher/minecraft/auth/flows/Mojang.h26
-rw-r--r--launcher/minecraft/auth/steps/MSAStep.cpp125
-rw-r--r--launcher/minecraft/auth/steps/MSAStep.h10
-rw-r--r--launcher/minecraft/auth/steps/MigrationEligibilityStep.cpp45
-rw-r--r--launcher/minecraft/auth/steps/MigrationEligibilityStep.h22
-rw-r--r--launcher/minecraft/auth/steps/MinecraftProfileStep.cpp9
-rw-r--r--launcher/minecraft/auth/steps/YggdrasilStep.cpp51
-rw-r--r--launcher/minecraft/auth/steps/YggdrasilStep.h28
-rw-r--r--launcher/minecraft/mod/ModFolderModel.cpp10
-rw-r--r--launcher/minecraft/services/CapeChange.cpp4
-rw-r--r--launcher/minecraft/services/SkinDelete.cpp2
-rw-r--r--launcher/minecraft/services/SkinUpload.cpp2
-rw-r--r--launcher/modplatform/atlauncher/ATLPackInstallTask.cpp16
-rw-r--r--launcher/modplatform/flame/FlamePackIndex.cpp9
-rw-r--r--launcher/modplatform/flame/PackManifest.h2
-rw-r--r--launcher/modplatform/legacy_ftb/PackFetchTask.cpp2
-rw-r--r--launcher/modplatform/legacy_ftb/PackInstallTask.cpp12
-rw-r--r--launcher/modplatform/legacy_ftb/PrivatePackManager.cpp5
-rw-r--r--launcher/net/Download.cpp2
-rw-r--r--launcher/net/HttpMetaCache.cpp3
-rw-r--r--launcher/net/NetJob.cpp4
-rw-r--r--launcher/net/PasteUpload.cpp2
-rw-r--r--launcher/news/NewsChecker.cpp2
-rw-r--r--launcher/screenshots/ImgurAlbumCreation.cpp2
-rw-r--r--launcher/screenshots/ImgurUpload.cpp2
-rw-r--r--launcher/settings/INIFile.cpp10
-rw-r--r--launcher/translations/TranslationsModel.cpp12
-rw-r--r--launcher/ui/MainWindow.cpp8
-rw-r--r--launcher/ui/dialogs/AboutDialog.cpp15
-rw-r--r--launcher/ui/dialogs/AboutDialog.ui15
-rw-r--r--launcher/ui/dialogs/CopyInstanceDialog.cpp4
-rw-r--r--launcher/ui/dialogs/ExportInstanceDialog.cpp12
-rw-r--r--launcher/ui/dialogs/LoginDialog.cpp119
-rw-r--r--launcher/ui/dialogs/LoginDialog.h59
-rw-r--r--launcher/ui/dialogs/LoginDialog.ui77
-rw-r--r--launcher/ui/dialogs/MSALoginDialog.cpp45
-rw-r--r--launcher/ui/dialogs/MSALoginDialog.h9
-rw-r--r--launcher/ui/dialogs/NewComponentDialog.cpp3
-rw-r--r--launcher/ui/dialogs/NewInstanceDialog.cpp4
-rw-r--r--launcher/ui/dialogs/ProfileSetupDialog.cpp6
-rw-r--r--launcher/ui/dialogs/SkinUploadDialog.cpp5
-rw-r--r--launcher/ui/dialogs/UpdateDialog.cpp3
-rw-r--r--launcher/ui/instanceview/InstanceDelegate.cpp2
-rw-r--r--launcher/ui/instanceview/InstanceView.cpp2
-rw-r--r--launcher/ui/instanceview/InstanceView.h6
-rw-r--r--launcher/ui/pages/global/AccountListPage.cpp25
-rw-r--r--launcher/ui/pages/global/AccountListPage.h1
-rw-r--r--launcher/ui/pages/global/AccountListPage.ui6
-rw-r--r--launcher/ui/pages/global/ProxyPage.cpp2
-rw-r--r--launcher/ui/pages/instance/LogPage.cpp2
-rw-r--r--launcher/ui/pages/instance/ModFolderPage.cpp6
-rw-r--r--launcher/ui/pages/instance/ScreenshotsPage.cpp5
-rw-r--r--launcher/ui/pages/instance/ServersPage.cpp4
-rw-r--r--launcher/ui/pages/modplatform/flame/FlamePage.cpp14
-rw-r--r--launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp2
-rw-r--r--launcher/ui/pages/modplatform/legacy_ftb/Page.cpp2
-rw-r--r--launcher/ui/themes/BrightTheme.cpp2
-rw-r--r--launcher/ui/themes/DarkTheme.cpp2
-rw-r--r--launcher/ui/widgets/LabeledToolButton.cpp2
-rw-r--r--launcher/ui/widgets/LogView.cpp2
-rw-r--r--launcher/ui/widgets/PageContainer.cpp4
-rw-r--r--launcher/ui/widgets/VersionListView.cpp2
-rw-r--r--libraries/LocalPeer/src/LocalPeer.cpp3
-rw-r--r--libraries/classparser/src/classparser.cpp2
-rw-r--r--libraries/iconfix/internal/qiconloader.cpp43
-rw-r--r--libraries/iconfix/internal/qiconloader_p.h3
-rw-r--r--libraries/systeminfo/src/distroutils.cpp11
117 files changed, 418 insertions, 1574 deletions
diff --git a/README.md b/README.md
index f5d4ad7d7f..7177e8858d 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,5 @@
-<p align="center">
- <img src="https://avatars2.githubusercontent.com/u/5411890" alt="MeshMC logo"/>
-</p>
-
MeshMC
-=======
+======
MeshMC is a custom launcher for Minecraft that focuses on predictability, long term stability and simplicity.
diff --git a/cmake/UnitTest/TestUtil.h b/cmake/UnitTest/TestUtil.h
index ebe3c662d1..0a11313951 100644
--- a/cmake/UnitTest/TestUtil.h
+++ b/cmake/UnitTest/TestUtil.h
@@ -14,7 +14,8 @@ public:
static QByteArray readFile(const QString &fileName)
{
QFile f(fileName);
- f.open(QFile::ReadOnly);
+ if (!f.open(QFile::ReadOnly))
+ return QByteArray();
return f.readAll();
}
static QString readFileUtf8(const QString &fileName)
diff --git a/launcher/ApplicationMessage.cpp b/launcher/ApplicationMessage.cpp
index e22bf13c81..a01324dfc7 100644
--- a/launcher/ApplicationMessage.cpp
+++ b/launcher/ApplicationMessage.cpp
@@ -4,7 +4,7 @@
#include <QJsonObject>
void ApplicationMessage::parse(const QByteArray & input) {
- auto doc = QJsonDocument::fromBinaryData(input);
+ auto doc = QJsonDocument::fromJson(input);
auto root = doc.object();
command = root.value("command").toString();
@@ -27,5 +27,5 @@ QByteArray ApplicationMessage::serialize() {
QJsonDocument out;
out.setObject(root);
- return out.toBinaryData();
+ return out.toJson(QJsonDocument::Compact);
}
diff --git a/launcher/BaseInstance.cpp b/launcher/BaseInstance.cpp
index 374d4a29c6..54197fff03 100644
--- a/launcher/BaseInstance.cpp
+++ b/launcher/BaseInstance.cpp
@@ -18,6 +18,7 @@
#include <QFileInfo>
#include <QDir>
#include <QDebug>
+#include <QRegularExpression>
#include "settings/INISettingsObject.h"
#include "settings/Setting.h"
@@ -261,7 +262,7 @@ QString BaseInstance::name() const
QString BaseInstance::windowTitle() const
{
- return BuildConfig.LAUNCHER_NAME + ": " + name().replace(QRegExp("[ \n\r\t]+"), " ");
+ return BuildConfig.LAUNCHER_NAME + ": " + name().replace(QRegularExpression("[ \n\r\t]+"), " ");
}
// FIXME: why is this here? move it to MinecraftInstance!!!
diff --git a/launcher/BaseVersionList.cpp b/launcher/BaseVersionList.cpp
index aa9cb6cf14..506844093a 100644
--- a/launcher/BaseVersionList.cpp
+++ b/launcher/BaseVersionList.cpp
@@ -51,7 +51,7 @@ QVariant BaseVersionList::data(const QModelIndex &index, int role) const
switch (role)
{
case VersionPointerRole:
- return qVariantFromValue(version);
+ return QVariant::fromValue(version);
case VersionRole:
return version->name();
diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt
index c1d4fc6877..1f9bbb7fe4 100644
--- a/launcher/CMakeLists.txt
+++ b/launcher/CMakeLists.txt
@@ -212,13 +212,8 @@ set(MINECRAFT_SOURCES
minecraft/auth/MinecraftAccount.h
minecraft/auth/Parsers.cpp
minecraft/auth/Parsers.h
- minecraft/auth/Yggdrasil.cpp
- minecraft/auth/Yggdrasil.h
-
minecraft/auth/flows/AuthFlow.cpp
minecraft/auth/flows/AuthFlow.h
- minecraft/auth/flows/Mojang.cpp
- minecraft/auth/flows/Mojang.h
minecraft/auth/flows/MSA.cpp
minecraft/auth/flows/MSA.h
@@ -228,8 +223,6 @@ set(MINECRAFT_SOURCES
minecraft/auth/steps/GetSkinStep.h
minecraft/auth/steps/LauncherLoginStep.cpp
minecraft/auth/steps/LauncherLoginStep.h
- minecraft/auth/steps/MigrationEligibilityStep.cpp
- minecraft/auth/steps/MigrationEligibilityStep.h
minecraft/auth/steps/MinecraftProfileStep.cpp
minecraft/auth/steps/MinecraftProfileStep.h
minecraft/auth/steps/MSAStep.cpp
@@ -240,9 +233,6 @@ set(MINECRAFT_SOURCES
minecraft/auth/steps/XboxProfileStep.h
minecraft/auth/steps/XboxUserStep.cpp
minecraft/auth/steps/XboxUserStep.h
- minecraft/auth/steps/YggdrasilStep.cpp
- minecraft/auth/steps/YggdrasilStep.h
-
minecraft/gameoptions/GameOptions.h
minecraft/gameoptions/GameOptions.cpp
@@ -767,8 +757,6 @@ SET(LAUNCHER_SOURCES
ui/dialogs/ExportInstanceDialog.h
ui/dialogs/IconPickerDialog.cpp
ui/dialogs/IconPickerDialog.h
- ui/dialogs/LoginDialog.cpp
- ui/dialogs/LoginDialog.h
ui/dialogs/MSALoginDialog.cpp
ui/dialogs/MSALoginDialog.h
ui/dialogs/NewComponentDialog.cpp
@@ -883,7 +871,6 @@ qt6_wrap_ui(LAUNCHER_UI
ui/dialogs/IconPickerDialog.ui
ui/dialogs/MSALoginDialog.ui
ui/dialogs/AboutDialog.ui
- ui/dialogs/LoginDialog.ui
ui/dialogs/EditAccountDialog.ui
)
@@ -910,7 +897,6 @@ endif()
add_library(Launcher_logic STATIC ${LOGIC_SOURCES} ${LAUNCHER_SOURCES} ${LAUNCHER_UI} ${LAUNCHER_RESOURCES})
target_link_libraries(Launcher_logic
systeminfo
- Launcher_quazip
Launcher_classparser
${NBT_NAME}
${ZLIB_LIBRARIES}
diff --git a/launcher/Commandline.cpp b/launcher/Commandline.cpp
index 2c0fde64b2..8c89cd3b2b 100644
--- a/launcher/Commandline.cpp
+++ b/launcher/Commandline.cpp
@@ -47,7 +47,7 @@ QStringList splitArgs(QString args)
if (cchar == '\\')
escape = true;
else if (cchar == inquotes)
- inquotes = 0;
+ inquotes = QChar();
else
current += cchar;
// otherwise
diff --git a/launcher/FileSystem.cpp b/launcher/FileSystem.cpp
index 6de20de6ff..62e6c1e27f 100644
--- a/launcher/FileSystem.cpp
+++ b/launcher/FileSystem.cpp
@@ -407,7 +407,8 @@ bool createShortCut(QString location, QString dest, QStringList args, QString na
location = PathCombine(location, name + ".desktop");
QFile f(location);
- f.open(QIODevice::WriteOnly | QIODevice::Text);
+ if (!f.open(QIODevice::WriteOnly | QIODevice::Text))
+ return false;
QTextStream stream(&f);
QString argstring;
diff --git a/launcher/GZip.cpp b/launcher/GZip.cpp
index 0368c32d60..c5c5e7a730 100644
--- a/launcher/GZip.cpp
+++ b/launcher/GZip.cpp
@@ -67,7 +67,7 @@ bool GZip::zip(const QByteArray &uncompressedBytes, QByteArray &compressedBytes)
return true;
}
- unsigned compLength = std::min(uncompressedBytes.size(), 16);
+ unsigned compLength = std::min(static_cast<qsizetype>(16), uncompressedBytes.size());
compressedBytes.clear();
compressedBytes.resize(compLength);
diff --git a/launcher/InstanceImportTask.cpp b/launcher/InstanceImportTask.cpp
index 990cc9840e..37d20c99a8 100644
--- a/launcher/InstanceImportTask.cpp
+++ b/launcher/InstanceImportTask.cpp
@@ -21,6 +21,7 @@
#include "NullInstance.h"
#include "settings/INISettingsObject.h"
#include "icons/IconUtils.h"
+#include <QRegularExpression>
#include <QtConcurrentRun>
// FIXME: this does not belong here, it's Minecraft/Flame specific
@@ -268,7 +269,7 @@ void InstanceImportTask::processFlame()
// Hack to correct some 'special sauce'...
if(mcVersion.endsWith('.'))
{
- mcVersion.remove(QRegExp("[.]+$"));
+ mcVersion.remove(QRegularExpression("[.]+$"));
logWarning(tr("Mysterious trailing dots removed from Minecraft version while importing pack."));
}
auto components = instance.getPackProfile();
diff --git a/launcher/InstanceList.cpp b/launcher/InstanceList.cpp
index ad18740b63..045afb0e80 100644
--- a/launcher/InstanceList.cpp
+++ b/launcher/InstanceList.cpp
@@ -133,7 +133,7 @@ QVariant InstanceList::data(const QModelIndex &index, int role) const
{
case InstancePointerRole:
{
- QVariant v = qVariantFromValue((void *)pdata);
+ QVariant v = QVariant::fromValue((void *)pdata);
return v;
}
case InstanceIDRole:
@@ -249,7 +249,7 @@ void InstanceList::setInstanceGroup(const InstanceId& id, const GroupId& name)
QStringList InstanceList::getGroups()
{
- return m_groupNameCache.toList();
+ return m_groupNameCache.values();
}
void InstanceList::deleteGroup(const QString& name)
@@ -350,7 +350,7 @@ QList< InstanceId > InstanceList::discoverInstances()
out.append(id);
qDebug() << "Found instance ID" << id;
}
- instanceSet = out.toSet();
+ instanceSet = QSet<QString>(out.begin(), out.end());
m_instancesProbed = true;
return out;
}
diff --git a/launcher/JavaCommon.cpp b/launcher/JavaCommon.cpp
index 6fa5851b1f..d946921276 100644
--- a/launcher/JavaCommon.cpp
+++ b/launcher/JavaCommon.cpp
@@ -1,10 +1,11 @@
#include "JavaCommon.h"
#include "ui/dialogs/CustomMessageBox.h"
#include <MMCStrings.h>
+#include <QRegularExpression>
bool JavaCommon::checkJVMArgs(QString jvmargs, QWidget *parent)
{
- if (jvmargs.contains("-XX:PermSize=") || jvmargs.contains(QRegExp("-Xm[sx]"))
+ if (jvmargs.contains("-XX:PermSize=") || jvmargs.contains(QRegularExpression("-Xm[sx]"))
|| jvmargs.contains("-XX-MaxHeapSize") || jvmargs.contains("-XX:InitialHeapSize"))
{
auto warnStr = QObject::tr(
diff --git a/launcher/Json.cpp b/launcher/Json.cpp
index 37ada1aa23..800f06cfea 100644
--- a/launcher/Json.cpp
+++ b/launcher/Json.cpp
@@ -24,11 +24,11 @@ void write(const QJsonArray &array, const QString &filename)
QByteArray toBinary(const QJsonObject &obj)
{
- return QJsonDocument(obj).toBinaryData();
+ return QJsonDocument(obj).toJson(QJsonDocument::Compact);
}
QByteArray toBinary(const QJsonArray &array)
{
- return QJsonDocument(array).toBinaryData();
+ return QJsonDocument(array).toJson(QJsonDocument::Compact);
}
QByteArray toText(const QJsonObject &obj)
{
@@ -41,19 +41,15 @@ QByteArray toText(const QJsonArray &array)
static bool isBinaryJson(const QByteArray &data)
{
- decltype(QJsonDocument::BinaryFormatTag) tag = QJsonDocument::BinaryFormatTag;
- return memcmp(data.constData(), &tag, sizeof(QJsonDocument::BinaryFormatTag)) == 0;
+ // Binary JSON is no longer supported in Qt6
+ Q_UNUSED(data);
+ return false;
}
QJsonDocument requireDocument(const QByteArray &data, const QString &what)
{
if (isBinaryJson(data))
{
- QJsonDocument doc = QJsonDocument::fromBinaryData(data);
- if (doc.isNull())
- {
- throw JsonException(what + ": Invalid JSON (binary JSON detected)");
- }
- return doc;
+ throw JsonException(what + ": Binary JSON format is no longer supported");
}
else
{
diff --git a/launcher/LaunchController.cpp b/launcher/LaunchController.cpp
index 7750be1a2a..9a7c0c6c4e 100644
--- a/launcher/LaunchController.cpp
+++ b/launcher/LaunchController.cpp
@@ -55,7 +55,7 @@ void LaunchController::decideAccount()
auto reply = CustomMessageBox::selectable(
m_parentWidget,
tr("No Accounts"),
- tr("In order to play Minecraft, you must have at least one Mojang or Minecraft "
+ tr("In order to play Minecraft, you must have at least one Microsoft "
"account logged in."
"Would you like to open the account manager to add an account now?"),
QMessageBox::Information,
@@ -275,7 +275,7 @@ void LaunchController::launchInstance()
online_mode = "online";
// Prepend Server Status
- QStringList servers = {"authserver.mojang.com", "session.minecraft.net", "textures.minecraft.net", "api.mojang.com"};
+ QStringList servers = {"session.minecraft.net", "textures.minecraft.net", "api.mojang.com"};
QString resolved_servers = "";
QHostInfo host_info;
diff --git a/launcher/LoggedProcess.cpp b/launcher/LoggedProcess.cpp
index 2479f4ff4b..a53ebf446d 100644
--- a/launcher/LoggedProcess.cpp
+++ b/launcher/LoggedProcess.cpp
@@ -8,7 +8,7 @@ LoggedProcess::LoggedProcess(QObject *parent) : QProcess(parent)
connect(this, &QProcess::readyReadStandardOutput, this, &LoggedProcess::on_stdOut);
connect(this, &QProcess::readyReadStandardError, this, &LoggedProcess::on_stdErr);
connect(this, SIGNAL(finished(int,QProcess::ExitStatus)), SLOT(on_exit(int,QProcess::ExitStatus)));
- connect(this, SIGNAL(error(QProcess::ProcessError)), this, SLOT(on_error(QProcess::ProcessError)));
+ connect(this, SIGNAL(errorOccurred(QProcess::ProcessError)), this, SLOT(on_error(QProcess::ProcessError)));
connect(this, &QProcess::stateChanged, this, &LoggedProcess::on_stateChange);
}
@@ -163,11 +163,7 @@ void LoggedProcess::on_stateChange(QProcess::ProcessState state)
qint64 LoggedProcess::processId() const
{
-#ifdef Q_OS_WIN
- return pid() ? pid()->dwProcessId : 0;
-#else
- return pid();
-#endif
+ return QProcess::processId();
}
void LoggedProcess::setDetachable(bool detachable)
diff --git a/launcher/MMCZip.cpp b/launcher/MMCZip.cpp
index b25c61e759..f893c32133 100644
--- a/launcher/MMCZip.cpp
+++ b/launcher/MMCZip.cpp
@@ -21,9 +21,49 @@
#include "FileSystem.h"
#include <QDebug>
+#include <QDirIterator>
+
+bool MMCZip::compressDir(QString zipFile, QString dir, FilterFunction excludeFilter)
+{
+ QuaZip zip(zipFile);
+ if (!zip.open(QuaZip::mdCreate))
+ {
+ return false;
+ }
+
+ QDir directory(dir);
+ if (!directory.exists())
+ {
+ return false;
+ }
+
+ QDirIterator it(dir, QDir::Files | QDir::Hidden, QDirIterator::Subdirectories);
+ bool success = true;
+ while (it.hasNext())
+ {
+ it.next();
+ QString relPath = directory.relativeFilePath(it.filePath());
+ if (excludeFilter && excludeFilter(relPath))
+ {
+ continue;
+ }
+ if (!JlCompress::compressFile(&zip, it.filePath(), relPath))
+ {
+ success = false;
+ break;
+ }
+ }
+
+ zip.close();
+ if (zip.getZipError() != 0)
+ {
+ return false;
+ }
+ return success;
+}
// ours
-bool MMCZip::mergeZipFiles(QuaZip *into, QFileInfo from, QSet<QString> &contained, const JlCompress::FilterFunction filter)
+bool MMCZip::mergeZipFiles(QuaZip *into, QFileInfo from, QSet<QString> &contained, const FilterFunction filter)
{
QuaZip modZip(from.filePath());
modZip.open(QuaZip::mdUnzip);
@@ -128,7 +168,7 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const
QDir dir(what_to_zip);
dir.cdUp();
QString parent_dir = dir.absolutePath();
- if (!JlCompress::compressSubDir(&zipOut, what_to_zip, parent_dir, addedFiles))
+ if (!JlCompress::compressSubDir(&zipOut, what_to_zip, parent_dir, true, QDir::NoFilter))
{
zipOut.close();
QFile::remove(targetJarPath);
diff --git a/launcher/MMCZip.h b/launcher/MMCZip.h
index 9c47fa11f2..e5f9a7ea02 100644
--- a/launcher/MMCZip.h
+++ b/launcher/MMCZip.h
@@ -26,12 +26,13 @@
namespace MMCZip
{
+ using FilterFunction = std::function<bool(const QString &)>;
/**
* Merge two zip files, using a filter function
*/
bool mergeZipFiles(QuaZip *into, QFileInfo from, QSet<QString> &contained,
- const JlCompress::FilterFunction filter = nullptr);
+ const FilterFunction filter = nullptr);
/**
* take a source jar, add mods to it, resulting in target jar
@@ -56,6 +57,12 @@ namespace MMCZip
/**
* Extract a subdirectory from an archive
*/
+
+ /**
+ * Compress a directory, using a filter function to exclude entries
+ */
+ bool compressDir(QString zipFile, QString dir, FilterFunction excludeFilter);
+
nonstd::optional<QStringList> extractSubDir(QuaZip *zip, const QString & subdir, const QString &target);
bool extractRelFile(QuaZip *zip, const QString & file, const QString &target);
diff --git a/launcher/QObjectPtr.h b/launcher/QObjectPtr.h
index 57974939f1..1e45e90249 100644
--- a/launcher/QObjectPtr.h
+++ b/launcher/QObjectPtr.h
@@ -46,8 +46,12 @@ public:
public:
void reset(T * wrap)
{
- using namespace std::placeholders;
- m_ptr.reset(wrap, std::bind(&QObject::deleteLater, _1));
+ if(wrap) {
+ using namespace std::placeholders;
+ m_ptr.reset(wrap, std::bind(&QObject::deleteLater, _1));
+ } else {
+ m_ptr.reset();
+ }
}
void reset(const shared_qobject_ptr<T> &other)
{
diff --git a/launcher/UpdateController.cpp b/launcher/UpdateController.cpp
index f9b7d34995..1bcd837770 100644
--- a/launcher/UpdateController.cpp
+++ b/launcher/UpdateController.cpp
@@ -245,7 +245,8 @@ void UpdateController::installUpdates()
// we save it
QFile scriptFile(scriptPath);
- scriptFile.open(QIODevice::WriteOnly);
+ if (!scriptFile.open(QIODevice::WriteOnly))
+ return;
scriptFile.write(script.toLocal8Bit().replace("\n", "\r\n"));
scriptFile.close();
diff --git a/launcher/Version.h b/launcher/Version.h
index 9fe12d6dad..02b4244e01 100644
--- a/launcher/Version.h
+++ b/launcher/Version.h
@@ -39,13 +39,13 @@ private:
break;
}
}
- auto numPart = m_fullString.leftRef(cutoff);
+ auto numPart = QStringView{m_fullString}.left(cutoff);
if(numPart.size())
{
numValid = true;
m_numPart = numPart.toInt();
}
- auto stringPart = m_fullString.midRef(cutoff);
+ auto stringPart = QStringView{m_fullString}.mid(cutoff);
if(stringPart.size())
{
m_stringPart = stringPart.toString();
diff --git a/launcher/VersionProxyModel.cpp b/launcher/VersionProxyModel.cpp
index b9a87c9c20..3e457d1268 100644
--- a/launcher/VersionProxyModel.cpp
+++ b/launcher/VersionProxyModel.cpp
@@ -208,15 +208,15 @@ QVariant VersionProxyModel::data(const QModelIndex &index, int role) const
{
return APPLICATION->getThemedIcon("bug");
}
- auto pixmap = QPixmapCache::find("placeholder");
- if(!pixmap)
+ QPixmap pixmap;
+ if(!QPixmapCache::find("placeholder", &pixmap))
{
QPixmap px(16,16);
px.fill(Qt::transparent);
QPixmapCache::insert("placeholder", px);
return px;
}
- return *pixmap;
+ return pixmap;
}
}
default:
@@ -309,6 +309,7 @@ void VersionProxyModel::setSourceModel(QAbstractItemModel *replacingRaw)
{
roles.clear();
filterModel->setSourceModel(replacing);
+ endResetModel();
return;
}
diff --git a/launcher/icons/IconList.cpp b/launcher/icons/IconList.cpp
index 584edd69e0..e9558c8f29 100644
--- a/launcher/icons/IconList.cpp
+++ b/launcher/icons/IconList.cpp
@@ -74,7 +74,7 @@ void IconList::directoryChanged(const QString &path)
QString &foo = (*it);
foo = m_dir.filePath(foo);
}
- auto new_set = new_list.toSet();
+ auto new_set = QSet<QString>(new_list.begin(), new_list.end());
QList<QString> current_list;
for (auto &it : icons)
{
@@ -82,7 +82,7 @@ void IconList::directoryChanged(const QString &path)
continue;
current_list.push_back(it.m_images[IconType::FileBased].filename);
}
- QSet<QString> current_set = current_list.toSet();
+ QSet<QString> current_set(current_list.begin(), current_list.end());
QSet<QString> to_remove = current_set;
to_remove -= new_set;
diff --git a/launcher/java/JavaChecker.cpp b/launcher/java/JavaChecker.cpp
index 35ddc35c23..1bb2efe1f9 100644
--- a/launcher/java/JavaChecker.cpp
+++ b/launcher/java/JavaChecker.cpp
@@ -47,7 +47,7 @@ void JavaChecker::performCheck()
qDebug() << "Running java checker: " + m_path + args.join(" ");;
connect(process.get(), SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(finished(int, QProcess::ExitStatus)));
- connect(process.get(), SIGNAL(error(QProcess::ProcessError)), this, SLOT(error(QProcess::ProcessError)));
+ connect(process.get(), SIGNAL(errorOccurred(QProcess::ProcessError)), this, SLOT(error(QProcess::ProcessError)));
connect(process.get(), SIGNAL(readyReadStandardOutput()), this, SLOT(stdoutReady()));
connect(process.get(), SIGNAL(readyReadStandardError()), this, SLOT(stderrReady()));
connect(&killTimer, SIGNAL(timeout()), SLOT(timeout()));
@@ -99,7 +99,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
bool success = true;
QMap<QString, QString> results;
- QStringList lines = m_stdout.split("\n", QString::SkipEmptyParts);
+ QStringList lines = m_stdout.split("\n", Qt::SkipEmptyParts);
for(QString line : lines)
{
line = line.trimmed();
@@ -108,7 +108,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
continue;
}
- auto parts = line.split('=', QString::SkipEmptyParts);
+ auto parts = line.split('=', Qt::SkipEmptyParts);
if(parts.size() != 2 || parts[0].isEmpty() || parts[1].isEmpty())
{
continue;
diff --git a/launcher/java/JavaInstallList.cpp b/launcher/java/JavaInstallList.cpp
index 07f2bd8cb4..66fa26dd88 100644
--- a/launcher/java/JavaInstallList.cpp
+++ b/launcher/java/JavaInstallList.cpp
@@ -15,7 +15,6 @@
#include <QtNetwork>
#include <QtXml>
-#include <QRegExp>
#include <QDebug>
@@ -81,7 +80,7 @@ QVariant JavaInstallList::data(const QModelIndex &index, int role) const
switch (role)
{
case VersionPointerRole:
- return qVariantFromValue(m_vlist[index.row()]);
+ return QVariant::fromValue(m_vlist[index.row()]);
case VersionIdRole:
return version->descriptor();
case VersionRole:
diff --git a/launcher/java/JavaVersion.cpp b/launcher/java/JavaVersion.cpp
index 179ccd8d9e..b6687001b0 100644
--- a/launcher/java/JavaVersion.cpp
+++ b/launcher/java/JavaVersion.cpp
@@ -56,7 +56,7 @@ bool JavaVersion::requiresPermGen()
return true;
}
-bool JavaVersion::operator<(const JavaVersion &rhs)
+bool JavaVersion::operator<(const JavaVersion &rhs) const
{
if(m_parseable && rhs.m_parseable)
{
@@ -106,7 +106,7 @@ bool JavaVersion::operator<(const JavaVersion &rhs)
else return Strings::naturalCompare(m_string, rhs.m_string, Qt::CaseSensitive) < 0;
}
-bool JavaVersion::operator==(const JavaVersion &rhs)
+bool JavaVersion::operator==(const JavaVersion &rhs) const
{
if(m_parseable && rhs.m_parseable)
{
@@ -115,7 +115,7 @@ bool JavaVersion::operator==(const JavaVersion &rhs)
return m_string == rhs.m_string;
}
-bool JavaVersion::operator>(const JavaVersion &rhs)
+bool JavaVersion::operator>(const JavaVersion &rhs) const
{
return (!operator<(rhs)) && (!operator==(rhs));
}
diff --git a/launcher/java/JavaVersion.h b/launcher/java/JavaVersion.h
index 9bbf064257..298b92b4a1 100644
--- a/launcher/java/JavaVersion.h
+++ b/launcher/java/JavaVersion.h
@@ -19,9 +19,9 @@ public:
JavaVersion & operator=(const QString & rhs);
- bool operator<(const JavaVersion & rhs);
- bool operator==(const JavaVersion & rhs);
- bool operator>(const JavaVersion & rhs);
+ bool operator<(const JavaVersion & rhs) const;
+ bool operator==(const JavaVersion & rhs) const;
+ bool operator>(const JavaVersion & rhs) const;
bool requiresPermGen();
diff --git a/launcher/minecraft/ComponentUpdateTask.cpp b/launcher/minecraft/ComponentUpdateTask.cpp
index 8bc05a1bce..d6a2e23637 100644
--- a/launcher/minecraft/ComponentUpdateTask.cpp
+++ b/launcher/minecraft/ComponentUpdateTask.cpp
@@ -189,11 +189,11 @@ void ComponentUpdateTask::loadComponents()
RemoteLoadStatus status;
status.type = RemoteLoadStatus::Type::Index;
d->remoteLoadStatusList.append(status);
- connect(indexLoadTask.get(), &Task::succeeded, [=]()
+ connect(indexLoadTask.get(), &Task::succeeded, [this, taskIndex]()
{
remoteLoadSucceeded(taskIndex);
});
- connect(indexLoadTask.get(), &Task::failed, [=](const QString & error)
+ connect(indexLoadTask.get(), &Task::failed, [this, taskIndex](const QString & error)
{
remoteLoadFailed(taskIndex, error);
});
@@ -235,11 +235,11 @@ void ComponentUpdateTask::loadComponents()
if (loadTask)
{
qDebug() << "Remote loading is being run for" << component->getName();
- connect(loadTask.get(), &Task::succeeded, [=]()
+ connect(loadTask.get(), &Task::succeeded, [this, taskIndex]()
{
remoteLoadSucceeded(taskIndex);
});
- connect(loadTask.get(), &Task::failed, [=](const QString & error)
+ connect(loadTask.get(), &Task::failed, [this, taskIndex](const QString & error)
{
remoteLoadFailed(taskIndex, error);
});
diff --git a/launcher/minecraft/GradleSpecifier.h b/launcher/minecraft/GradleSpecifier.h
index 415fb54cfd..072e3925ec 100644
--- a/launcher/minecraft/GradleSpecifier.h
+++ b/launcher/minecraft/GradleSpecifier.h
@@ -2,6 +2,7 @@
#include <QString>
#include <QStringList>
+#include <QRegularExpression>
#include "DefaultVariable.h"
struct GradleSpecifier
@@ -25,13 +26,14 @@ struct GradleSpecifier
4 "jdk15"
5 "jar"
*/
- QRegExp matcher("([^:@]+):([^:@]+):([^:@]+)" "(?::([^:@]+))?" "(?:@([^:@]+))?");
- m_valid = matcher.exactMatch(value);
+ QRegularExpression matcher("^([^:@]+):([^:@]+):([^:@]+)" "(?::([^:@]+))?" "(?:@([^:@]+))?$");
+ auto match = matcher.match(value);
+ m_valid = match.hasMatch();
if(!m_valid) {
m_invalidValue = value;
return *this;
}
- auto elements = matcher.capturedTexts();
+ auto elements = match.capturedTexts();
m_groupId = elements[1];
m_artifactId = elements[2];
m_version = elements[3];
diff --git a/launcher/minecraft/Library_test.cpp b/launcher/minecraft/Library_test.cpp
index 47531ad6f3..76f8547924 100644
--- a/launcher/minecraft/Library_test.cpp
+++ b/launcher/minecraft/Library_test.cpp
@@ -15,7 +15,8 @@ private:
{
auto path = QFINDTESTDATA(file);
QFile jsonFile(path);
- jsonFile.open(QIODevice::ReadOnly);
+ if (!jsonFile.open(QIODevice::ReadOnly))
+ return nullptr;
auto data = jsonFile.readAll();
jsonFile.close();
ProblemContainer problems;
diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp
index ff70728839..6408e0ec27 100644
--- a/launcher/minecraft/MinecraftInstance.cpp
+++ b/launcher/minecraft/MinecraftInstance.cpp
@@ -5,6 +5,7 @@
#include "settings/Setting.h"
#include "settings/SettingsObject.h"
#include "Application.h"
+#include <QRegularExpression>
#include "MMCStrings.h"
#include "pathmatcher/RegexpMatcher.h"
@@ -392,22 +393,20 @@ QProcessEnvironment MinecraftInstance::createEnvironment()
static QString replaceTokensIn(QString text, QMap<QString, QString> with)
{
QString result;
- QRegExp token_regexp("\\$\\{(.+)\\}");
- token_regexp.setMinimal(true);
- QStringList list;
+ QRegularExpression token_regexp("\\$\\{(.+?)\\}");
+ QRegularExpressionMatchIterator it = token_regexp.globalMatch(text);
int tail = 0;
- int head = 0;
- while ((head = token_regexp.indexIn(text, head)) != -1)
+ while (it.hasNext())
{
- result.append(text.mid(tail, head - tail));
- QString key = token_regexp.cap(1);
+ QRegularExpressionMatch match = it.next();
+ result.append(text.mid(tail, match.capturedStart() - tail));
+ QString key = match.captured(1);
auto iter = with.find(key);
if (iter != with.end())
{
result.append(*iter);
}
- head += token_regexp.matchedLength();
- tail = head;
+ tail = match.capturedEnd();
}
result.append(text.mid(tail));
return result;
@@ -459,7 +458,7 @@ QStringList MinecraftInstance::processMinecraftArgs(
token_mapping["assets_root"] = absAssetsDir;
token_mapping["assets_index_name"] = assets->id;
- QStringList parts = args_pattern.split(' ', QString::SkipEmptyParts);
+ QStringList parts = args_pattern.split(' ', Qt::SkipEmptyParts);
for (int i = 0; i < parts.length(); i++)
{
parts[i] = replaceTokensIn(parts[i], token_mapping);
diff --git a/launcher/minecraft/MojangVersionFormat_test.cpp b/launcher/minecraft/MojangVersionFormat_test.cpp
index 9d0953406f..183ada997c 100644
--- a/launcher/minecraft/MojangVersionFormat_test.cpp
+++ b/launcher/minecraft/MojangVersionFormat_test.cpp
@@ -12,7 +12,8 @@ class MojangVersionFormatTest : public QObject
{
auto path = QFINDTESTDATA(file);
QFile jsonFile(path);
- jsonFile.open(QIODevice::ReadOnly);
+ if (!jsonFile.open(QIODevice::ReadOnly))
+ return QJsonDocument();
auto data = jsonFile.readAll();
jsonFile.close();
return QJsonDocument::fromJson(data);
@@ -20,7 +21,8 @@ class MojangVersionFormatTest : public QObject
static void writeJson(const char *file, QJsonDocument doc)
{
QFile jsonFile(file);
- jsonFile.open(QIODevice::WriteOnly | QIODevice::Text);
+ if (!jsonFile.open(QIODevice::WriteOnly | QIODevice::Text))
+ return;
auto data = doc.toJson(QJsonDocument::Indented);
qDebug() << QString::fromUtf8(data);
jsonFile.write(data);
diff --git a/launcher/minecraft/OneSixVersionFormat.cpp b/launcher/minecraft/OneSixVersionFormat.cpp
index d5e8c680d9..acc03c5960 100644
--- a/launcher/minecraft/OneSixVersionFormat.cpp
+++ b/launcher/minecraft/OneSixVersionFormat.cpp
@@ -272,7 +272,7 @@ QJsonDocument OneSixVersionFormat::versionFileToJson(const VersionFilePtr &patch
}
writeString(root, "appletClass", patch->appletClass);
writeStringList(root, "+tweakers", patch->addTweakers);
- writeStringList(root, "+traits", patch->traits.toList());
+ writeStringList(root, "+traits", patch->traits.values());
if (!patch->libraries.isEmpty())
{
QJsonArray array;
diff --git a/launcher/minecraft/PackProfile.cpp b/launcher/minecraft/PackProfile.cpp
index f557cbc90a..e149b132ef 100644
--- a/launcher/minecraft/PackProfile.cpp
+++ b/launcher/minecraft/PackProfile.cpp
@@ -925,7 +925,7 @@ void PackProfile::move(const int index, const MoveDirection direction)
return;
}
beginMoveRows(QModelIndex(), index, index, QModelIndex(), togap);
- d->components.swap(index, theirIndex);
+ d->components.swapItemsAt(index, theirIndex);
endMoveRows();
invalidateLaunchProfile();
scheduleSave();
diff --git a/launcher/minecraft/ProfileUtils.cpp b/launcher/minecraft/ProfileUtils.cpp
index 8ca24cc8cc..88aaae0b1b 100644
--- a/launcher/minecraft/ProfileUtils.cpp
+++ b/launcher/minecraft/ProfileUtils.cpp
@@ -149,7 +149,7 @@ VersionFilePtr parseBinaryJsonFile(const QFileInfo &fileInfo)
auto errorStr = QObject::tr("Unable to open the version file %1: %2.").arg(fileInfo.fileName(), file.errorString());
return createErrorVersionFile(fileInfo.completeBaseName(), fileInfo.absoluteFilePath(), errorStr);
}
- QJsonDocument doc = QJsonDocument::fromBinaryData(file.readAll());
+ QJsonDocument doc = QJsonDocument::fromJson(file.readAll());
file.close();
if (doc.isNull())
{
diff --git a/launcher/minecraft/World.cpp b/launcher/minecraft/World.cpp
index a2b4dac7a8..03600a01b2 100644
--- a/launcher/minecraft/World.cpp
+++ b/launcher/minecraft/World.cpp
@@ -299,7 +299,7 @@ bool World::install(const QString &to, const QString &name)
if(ok && !name.isEmpty() && m_actualName != name)
{
- World newWorld(finalPath);
+ World newWorld{QFileInfo(finalPath)};
if(newWorld.isValid())
{
newWorld.rename(name);
diff --git a/launcher/minecraft/WorldList.cpp b/launcher/minecraft/WorldList.cpp
index dcdbc32147..130f221e6f 100644
--- a/launcher/minecraft/WorldList.cpp
+++ b/launcher/minecraft/WorldList.cpp
@@ -197,7 +197,7 @@ QVariant WorldList::data(const QModelIndex &index, int role) const
}
case SeedRole:
{
- return qVariantFromValue<qlonglong>(world.seed());
+ return QVariant::fromValue<qlonglong>(world.seed());
}
case NameRole:
{
@@ -286,7 +286,7 @@ protected:
urls.append(QUrl::fromLocalFile(worldPath));
}
const_cast<WorldMimeData*>(this)->setUrls(urls);
- return QMimeData::retrieveData(mimetype, type);
+ return QMimeData::retrieveData(mimetype, QMetaType(type));
}
private:
QList<World> m_worlds;
diff --git a/launcher/minecraft/auth/AccountData.cpp b/launcher/minecraft/auth/AccountData.cpp
index 7526c9517c..5470e1e7fe 100644
--- a/launcher/minecraft/auth/AccountData.cpp
+++ b/launcher/minecraft/auth/AccountData.cpp
@@ -4,6 +4,7 @@
#include <QJsonArray>
#include <QDebug>
#include <QUuid>
+#include <QRegularExpression>
namespace {
void tokenToJSONV3(QJsonObject &parent, Katabasis::Token t, const char * tokenName) {
@@ -238,71 +239,6 @@ bool entitlementFromJSONV3(const QJsonObject &parent, MinecraftEntitlement & out
}
-bool AccountData::resumeStateFromV2(QJsonObject data) {
- // The JSON object must at least have a username for it to be valid.
- if (!data.value("username").isString())
- {
- qCritical() << "Can't load Mojang account info from JSON object. Username field is missing or of the wrong type.";
- return false;
- }
-
- QString userName = data.value("username").toString("");
- QString clientToken = data.value("clientToken").toString("");
- QString accessToken = data.value("accessToken").toString("");
-
- QJsonArray profileArray = data.value("profiles").toArray();
- if (profileArray.size() < 1)
- {
- qCritical() << "Can't load Mojang account with username \"" << userName << "\". No profiles found.";
- return false;
- }
-
- struct AccountProfile
- {
- QString id;
- QString name;
- bool legacy;
- };
-
- QList<AccountProfile> profiles;
- int currentProfileIndex = 0;
- int index = -1;
- QString currentProfile = data.value("activeProfile").toString("");
- for (QJsonValue profileVal : profileArray)
- {
- index++;
- QJsonObject profileObject = profileVal.toObject();
- QString id = profileObject.value("id").toString("");
- QString name = profileObject.value("name").toString("");
- bool legacy = profileObject.value("legacy").toBool(false);
- if (id.isEmpty() || name.isEmpty())
- {
- qWarning() << "Unable to load a profile" << name << "because it was missing an ID or a name.";
- continue;
- }
- if(id == currentProfile) {
- currentProfileIndex = index;
- }
- profiles.append({id, name, legacy});
- }
- auto & profile = profiles[currentProfileIndex];
-
- type = AccountType::Mojang;
- legacy = profile.legacy;
-
- minecraftProfile.id = profile.id;
- minecraftProfile.name = profile.name;
- minecraftProfile.validity = Katabasis::Validity::Assumed;
-
- yggdrasilToken.token = accessToken;
- yggdrasilToken.extra["clientToken"] = clientToken;
- yggdrasilToken.extra["userName"] = userName;
- yggdrasilToken.validity = Katabasis::Validity::Assumed;
-
- validity_ = minecraftProfile.validity;
- return true;
-}
-
bool AccountData::resumeStateFromV3(QJsonObject data) {
auto typeV = data.value("type");
if(!typeV.isString()) {
@@ -312,24 +248,15 @@ bool AccountData::resumeStateFromV3(QJsonObject data) {
auto typeS = typeV.toString();
if(typeS == "MSA") {
type = AccountType::MSA;
- } else if (typeS == "Mojang") {
- type = AccountType::Mojang;
} else {
- qWarning() << "Failed to parse account data: type is not recognized.";
+ qWarning() << "Failed to parse account data: type is not recognized (only MSA is supported).";
return false;
}
- if(type == AccountType::Mojang) {
- legacy = data.value("legacy").toBool(false);
- canMigrateToMSA = data.value("canMigrateToMSA").toBool(false);
- }
-
- if(type == AccountType::MSA) {
- msaToken = tokenFromJSONV3(data, "msa");
- userToken = tokenFromJSONV3(data, "utoken");
- xboxApiToken = tokenFromJSONV3(data, "xrp-main");
- mojangservicesToken = tokenFromJSONV3(data, "xrp-mc");
- }
+ msaToken = tokenFromJSONV3(data, "msa");
+ userToken = tokenFromJSONV3(data, "utoken");
+ xboxApiToken = tokenFromJSONV3(data, "xrp-main");
+ mojangservicesToken = tokenFromJSONV3(data, "xrp-mc");
yggdrasilToken = tokenFromJSONV3(data, "ygg");
minecraftProfile = profileFromJSONV3(data, "profile");
@@ -347,22 +274,11 @@ bool AccountData::resumeStateFromV3(QJsonObject data) {
QJsonObject AccountData::saveState() const {
QJsonObject output;
- if(type == AccountType::Mojang) {
- output["type"] = "Mojang";
- if(legacy) {
- output["legacy"] = true;
- }
- if(canMigrateToMSA) {
- output["canMigrateToMSA"] = true;
- }
- }
- else if (type == AccountType::MSA) {
- output["type"] = "MSA";
- tokenToJSONV3(output, msaToken, "msa");
- tokenToJSONV3(output, userToken, "utoken");
- tokenToJSONV3(output, xboxApiToken, "xrp-main");
- tokenToJSONV3(output, mojangservicesToken, "xrp-mc");
- }
+ output["type"] = "MSA";
+ tokenToJSONV3(output, msaToken, "msa");
+ tokenToJSONV3(output, userToken, "utoken");
+ tokenToJSONV3(output, xboxApiToken, "xrp-main");
+ tokenToJSONV3(output, mojangservicesToken, "xrp-mc");
tokenToJSONV3(output, yggdrasilToken, "ygg");
profileToJSONV3(output, minecraftProfile, "profile");
@@ -370,45 +286,10 @@ QJsonObject AccountData::saveState() const {
return output;
}
-QString AccountData::userName() const {
- if(type != AccountType::Mojang) {
- return QString();
- }
- return yggdrasilToken.extra["userName"].toString();
-}
-
QString AccountData::accessToken() const {
return yggdrasilToken.token;
}
-QString AccountData::clientToken() const {
- if(type != AccountType::Mojang) {
- return QString();
- }
- return yggdrasilToken.extra["clientToken"].toString();
-}
-
-void AccountData::setClientToken(QString clientToken) {
- if(type != AccountType::Mojang) {
- return;
- }
- yggdrasilToken.extra["clientToken"] = clientToken;
-}
-
-void AccountData::generateClientTokenIfMissing() {
- if(yggdrasilToken.extra.contains("clientToken")) {
- return;
- }
- invalidateClientToken();
-}
-
-void AccountData::invalidateClientToken() {
- if(type != AccountType::Mojang) {
- return;
- }
- yggdrasilToken.extra["clientToken"] = QUuid::createUuid().toString().remove(QRegExp("[{-}]"));
-}
-
QString AccountData::profileId() const {
return minecraftProfile.id;
}
@@ -423,20 +304,10 @@ QString AccountData::profileName() const {
}
QString AccountData::accountDisplayString() const {
- switch(type) {
- case AccountType::Mojang: {
- return userName();
- }
- case AccountType::MSA: {
- if(xboxApiToken.extra.contains("gtg")) {
- return xboxApiToken.extra["gtg"].toString();
- }
- return "Xbox profile missing";
- }
- default: {
- return "Invalid Account";
- }
+ if(xboxApiToken.extra.contains("gtg")) {
+ return xboxApiToken.extra["gtg"].toString();
}
+ return "Xbox profile missing";
}
QString AccountData::lastError() const {
diff --git a/launcher/minecraft/auth/AccountData.h b/launcher/minecraft/auth/AccountData.h
index abf84e43a6..dcd58b8d9f 100644
--- a/launcher/minecraft/auth/AccountData.h
+++ b/launcher/minecraft/auth/AccountData.h
@@ -37,8 +37,7 @@ struct MinecraftProfile {
};
enum class AccountType {
- MSA,
- Mojang
+ MSA
};
enum class AccountState {
@@ -53,21 +52,11 @@ enum class AccountState {
struct AccountData {
QJsonObject saveState() const;
- bool resumeStateFromV2(QJsonObject data);
bool resumeStateFromV3(QJsonObject data);
- //! userName for Mojang accounts, gamertag for MSA
+ //! Gamertag for MSA
QString accountDisplayString() const;
- //! Only valid for Mojang accounts. MSA does not preserve this information
- QString userName() const;
-
- //! Only valid for Mojang accounts.
- QString clientToken() const;
- void setClientToken(QString clientToken);
- void invalidateClientToken();
- void generateClientTokenIfMissing();
-
//! Yggdrasil access token, as passed to the game.
QString accessToken() const;
@@ -77,8 +66,6 @@ struct AccountData {
QString lastError() const;
AccountType type = AccountType::MSA;
- bool legacy = false;
- bool canMigrateToMSA = false;
Katabasis::Token msaToken;
Katabasis::Token userToken;
diff --git a/launcher/minecraft/auth/AccountList.cpp b/launcher/minecraft/auth/AccountList.cpp
index ef8b435d13..47daac950d 100644
--- a/launcher/minecraft/auth/AccountList.cpp
+++ b/launcher/minecraft/auth/AccountList.cpp
@@ -301,18 +301,6 @@ QVariant AccountList::data(const QModelIndex &index, int role) const
return account->profileName();
}
- case MigrationColumn: {
- if(account->isMSA()) {
- return tr("N/A", "Can Migrate?");
- }
- if (account->canMigrate()) {
- return tr("Yes", "Can Migrate?");
- }
- else {
- return tr("No", "Can Migrate?");
- }
- }
-
default:
return QVariant();
}
@@ -348,8 +336,6 @@ QVariant AccountList::headerData(int section, Qt::Orientation orientation, int r
return tr("Type");
case StatusColumn:
return tr("Status");
- case MigrationColumn:
- return tr("Can Migrate?");
case ProfileNameColumn:
return tr("Profile");
default:
@@ -362,11 +348,9 @@ QVariant AccountList::headerData(int section, Qt::Orientation orientation, int r
case NameColumn:
return tr("User name of the account.");
case TypeColumn:
- return tr("Type of the account - Mojang or MSA.");
+ return tr("Type of the account.");
case StatusColumn:
return tr("Current status of the account.");
- case MigrationColumn:
- return tr("Can this account migrate to Microsoft account?");
case ProfileNameColumn:
return tr("Name of the Minecraft profile associated with the account.");
default:
@@ -423,7 +407,7 @@ bool AccountList::loadList()
{
if (m_listFilePath.isEmpty())
{
- qCritical() << "Can't load Mojang account list. No file path given and no default set.";
+ qCritical() << "Can't load account list. No file path given and no default set.";
return false;
}
@@ -465,10 +449,6 @@ bool AccountList::loadList()
// Make sure the format version matches.
auto listVersion = root.value("formatVersion").toVariant().toInt();
switch(listVersion) {
- case AccountListVersion::MojangOnly: {
- return loadV2(root);
- }
- break;
case AccountListVersion::MojangMSA: {
return loadV3(root);
}
@@ -483,39 +463,6 @@ bool AccountList::loadList()
}
}
-bool AccountList::loadV2(QJsonObject& root) {
- beginResetModel();
- auto defaultUserName = root.value("activeAccount").toString("");
- QJsonArray accounts = root.value("accounts").toArray();
- for (QJsonValue accountVal : accounts)
- {
- QJsonObject accountObj = accountVal.toObject();
- MinecraftAccountPtr account = MinecraftAccount::loadFromJsonV2(accountObj);
- if (account.get() != nullptr)
- {
- auto profileId = account->profileId();
- if(!profileId.size()) {
- continue;
- }
- if(findAccountByProfileId(profileId) != -1) {
- continue;
- }
- connect(account.get(), &MinecraftAccount::changed, this, &AccountList::accountChanged);
- connect(account.get(), &MinecraftAccount::activityChanged, this, &AccountList::accountActivityChanged);
- m_accounts.append(account);
- if (defaultUserName.size() && account->mojangUserName() == defaultUserName) {
- m_defaultAccount = account;
- }
- }
- else
- {
- qWarning() << "Failed to load an account.";
- }
- }
- endResetModel();
- return true;
-}
-
bool AccountList::loadV3(QJsonObject& root) {
beginResetModel();
QJsonArray accounts = root.value("accounts").toArray();
@@ -552,7 +499,7 @@ bool AccountList::saveList()
{
if (m_listFilePath.isEmpty())
{
- qCritical() << "Can't save Mojang account list. No file path given and no default set.";
+ qCritical() << "Can't save account list. No file path given and no default set.";
return false;
}
diff --git a/launcher/minecraft/auth/AccountList.h b/launcher/minecraft/auth/AccountList.h
index 9f020a5033..c6e315a302 100644
--- a/launcher/minecraft/auth/AccountList.h
+++ b/launcher/minecraft/auth/AccountList.h
@@ -40,7 +40,6 @@ public:
// TODO: Add icon column.
NameColumn = 0,
ProfileNameColumn,
- MigrationColumn,
TypeColumn,
StatusColumn,
@@ -82,7 +81,6 @@ public:
void setListFilePath(QString path, bool autosave = false);
bool loadList();
- bool loadV2(QJsonObject &root);
bool loadV3(QJsonObject &root);
bool saveList();
diff --git a/launcher/minecraft/auth/AccountTask.h b/launcher/minecraft/auth/AccountTask.h
index dac3f1b551..4084da3536 100644
--- a/launcher/minecraft/auth/AccountTask.h
+++ b/launcher/minecraft/auth/AccountTask.h
@@ -55,8 +55,7 @@ public:
}
signals:
- void showVerificationUriAndCode(const QUrl &uri, const QString &code, int expiresIn);
- void hideVerificationUriAndCode();
+ void authorizeWithBrowser(const QUrl &url);
protected:
diff --git a/launcher/minecraft/auth/AuthRequest.cpp b/launcher/minecraft/auth/AuthRequest.cpp
index feface80f8..1f5813d616 100644
--- a/launcher/minecraft/auth/AuthRequest.cpp
+++ b/launcher/minecraft/auth/AuthRequest.cpp
@@ -20,7 +20,7 @@ void AuthRequest::get(const QNetworkRequest &req, int timeout/* = 60*1000*/) {
reply_ = APPLICATION->network()->get(request_);
status_ = Requesting;
timedReplies_.add(new Katabasis::Reply(reply_, timeout));
- connect(reply_, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onRequestError(QNetworkReply::NetworkError)));
+ connect(reply_, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(onRequestError(QNetworkReply::NetworkError)));
connect(reply_, SIGNAL(finished()), this, SLOT(onRequestFinished()));
connect(reply_, &QNetworkReply::sslErrors, this, &AuthRequest::onSslErrors);
}
@@ -31,7 +31,7 @@ void AuthRequest::post(const QNetworkRequest &req, const QByteArray &data, int t
status_ = Requesting;
reply_ = APPLICATION->network()->post(request_, data_);
timedReplies_.add(new Katabasis::Reply(reply_, timeout));
- connect(reply_, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onRequestError(QNetworkReply::NetworkError)));
+ connect(reply_, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(onRequestError(QNetworkReply::NetworkError)));
connect(reply_, SIGNAL(finished()), this, SLOT(onRequestFinished()));
connect(reply_, &QNetworkReply::sslErrors, this, &AuthRequest::onSslErrors);
connect(reply_, SIGNAL(uploadProgress(qint64,qint64)), this, SLOT(onUploadProgress(qint64,qint64)));
diff --git a/launcher/minecraft/auth/AuthStep.h b/launcher/minecraft/auth/AuthStep.h
index 2a8dc2cac9..7ae99d63fc 100644
--- a/launcher/minecraft/auth/AuthStep.h
+++ b/launcher/minecraft/auth/AuthStep.h
@@ -25,8 +25,7 @@ public slots:
signals:
void finished(AccountTaskState resultingState, QString message);
- void showVerificationUriAndCode(const QUrl &uri, const QString &code, int expiresIn);
- void hideVerificationUriAndCode();
+ void authorizeWithBrowser(const QUrl &url);
protected:
AccountData *m_data;
diff --git a/launcher/minecraft/auth/MinecraftAccount.cpp b/launcher/minecraft/auth/MinecraftAccount.cpp
index ed9e945ee2..8fdae71c18 100644
--- a/launcher/minecraft/auth/MinecraftAccount.cpp
+++ b/launcher/minecraft/auth/MinecraftAccount.cpp
@@ -20,7 +20,7 @@
#include <QUuid>
#include <QJsonObject>
#include <QJsonArray>
-#include <QRegExp>
+#include <QRegularExpression>
#include <QStringList>
#include <QJsonDocument>
@@ -29,21 +29,12 @@
#include <QPainter>
#include "flows/MSA.h"
-#include "flows/Mojang.h"
MinecraftAccount::MinecraftAccount(QObject* parent) : QObject(parent) {
- data.internalId = QUuid::createUuid().toString().remove(QRegExp("[{}-]"));
+ data.internalId = QUuid::createUuid().toString().remove(QRegularExpression("[{}-]"));
}
-MinecraftAccountPtr MinecraftAccount::loadFromJsonV2(const QJsonObject& json) {
- MinecraftAccountPtr account(new MinecraftAccount());
- if(account->data.resumeStateFromV2(json)) {
- return account;
- }
- return nullptr;
-}
-
MinecraftAccountPtr MinecraftAccount::loadFromJsonV3(const QJsonObject& json) {
MinecraftAccountPtr account(new MinecraftAccount());
if(account->data.resumeStateFromV3(json)) {
@@ -52,14 +43,6 @@ MinecraftAccountPtr MinecraftAccount::loadFromJsonV3(const QJsonObject& json) {
return nullptr;
}
-MinecraftAccountPtr MinecraftAccount::createFromUsername(const QString &username)
-{
- MinecraftAccountPtr account = new MinecraftAccount();
- account->data.type = AccountType::Mojang;
- account->data.yggdrasilToken.extra["userName"] = username;
- account->data.yggdrasilToken.extra["clientToken"] = QUuid::createUuid().toString().remove(QRegExp("[{}-]"));
- return account;
-}
MinecraftAccountPtr MinecraftAccount::createBlankMSA()
{
@@ -91,16 +74,6 @@ QPixmap MinecraftAccount::getFace() const {
}
-shared_qobject_ptr<AccountTask> MinecraftAccount::login(QString password) {
- Q_ASSERT(m_currentTask.get() == nullptr);
-
- m_currentTask.reset(new MojangLogin(&data, password));
- connect(m_currentTask.get(), SIGNAL(succeeded()), SLOT(authSucceeded()));
- connect(m_currentTask.get(), SIGNAL(failed(QString)), SLOT(authFailed(QString)));
- emit activityChanged(true);
- return m_currentTask;
-}
-
shared_qobject_ptr<AccountTask> MinecraftAccount::loginMSA() {
Q_ASSERT(m_currentTask.get() == nullptr);
@@ -116,12 +89,7 @@ shared_qobject_ptr<AccountTask> MinecraftAccount::refresh() {
return m_currentTask;
}
- if(data.type == AccountType::MSA) {
m_currentTask.reset(new MSASilent(&data));
- }
- else {
- m_currentTask.reset(new MojangRefresh(&data));
- }
connect(m_currentTask.get(), SIGNAL(succeeded()), SLOT(authSucceeded()));
connect(m_currentTask.get(), SIGNAL(failed(QString)), SLOT(authFailed(QString)));
@@ -150,17 +118,10 @@ void MinecraftAccount::authFailed(QString reason)
}
break;
case AccountTaskState::STATE_FAILED_HARD: {
- if(isMSA()) {
data.msaToken.token = QString();
data.msaToken.refresh_token = QString();
data.msaToken.validity = Katabasis::Validity::None;
data.validity_ = Katabasis::Validity::None;
- }
- else {
- data.yggdrasilToken.token = QString();
- data.yggdrasilToken.validity = Katabasis::Validity::None;
- data.validity_ = Katabasis::Validity::None;
- }
emit changed();
}
break;
@@ -205,8 +166,8 @@ bool MinecraftAccount::shouldRefresh() const {
}
}
auto now = QDateTime::currentDateTimeUtc();
- auto issuedTimestamp = data.yggdrasilToken.issueInstant;
- auto expiresTimestamp = data.yggdrasilToken.notAfter;
+ auto issuedTimestamp = data.msaToken.issueInstant;
+ auto expiresTimestamp = data.msaToken.notAfter;
if(!expiresTimestamp.isValid()) {
expiresTimestamp = issuedTimestamp.addSecs(24 * 3600);
@@ -231,13 +192,12 @@ void MinecraftAccount::fillSession(AuthSessionPtr session)
}
}
- // the user name. you have to have an user name
- // FIXME: not with MSA
- session->username = data.userName();
+ // the user name
+ session->username = data.profileName();
// volatile auth token
session->access_token = data.accessToken();
// the semi-permanent client token
- session->client_token = data.clientToken();
+ session->client_token = QString();
// profile name
session->player_name = data.profileName();
// profile ID
diff --git a/launcher/minecraft/auth/MinecraftAccount.h b/launcher/minecraft/auth/MinecraftAccount.h
index 0299d77858..fbb012f58c 100644
--- a/launcher/minecraft/auth/MinecraftAccount.h
+++ b/launcher/minecraft/auth/MinecraftAccount.h
@@ -69,11 +69,8 @@ public: /* construction */
//! Default constructor
explicit MinecraftAccount(QObject *parent = 0);
- static MinecraftAccountPtr createFromUsername(const QString &username);
-
static MinecraftAccountPtr createBlankMSA();
- static MinecraftAccountPtr loadFromJsonV2(const QJsonObject &json);
static MinecraftAccountPtr loadFromJsonV3(const QJsonObject &json);
//! Saves a MinecraftAccount to a JSON object and returns it.
@@ -81,12 +78,6 @@ public: /* construction */
public: /* manipulation */
- /**
- * Attempt to login. Empty password means we use the token.
- * If the attempt fails because we already are performing some task, it returns false.
- */
- shared_qobject_ptr<AccountTask> login(QString password);
-
shared_qobject_ptr<AccountTask> loginMSA();
shared_qobject_ptr<AccountTask> refresh();
@@ -102,10 +93,6 @@ public: /* queries */
return data.accountDisplayString();
}
- QString mojangUserName() const {
- return data.userName();
- }
-
QString accessToken() const {
return data.accessToken();
}
@@ -120,10 +107,6 @@ public: /* queries */
bool isActive() const;
- bool canMigrate() const {
- return data.canMigrateToMSA;
- }
-
bool isMSA() const {
return data.type == AccountType::MSA;
}
@@ -137,22 +120,7 @@ public: /* queries */
}
QString typeString() const {
- switch(data.type) {
- case AccountType::Mojang: {
- if(data.legacy) {
- return "legacy";
- }
- return "mojang";
- }
- break;
- case AccountType::MSA: {
return "msa";
- }
- break;
- default: {
- return "unknown";
- }
- }
}
QPixmap getFace() const;
diff --git a/launcher/minecraft/auth/Yggdrasil.cpp b/launcher/minecraft/auth/Yggdrasil.cpp
deleted file mode 100644
index 7ac842a67d..0000000000
--- a/launcher/minecraft/auth/Yggdrasil.cpp
+++ /dev/null
@@ -1,331 +0,0 @@
-/* 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 "Yggdrasil.h"
-#include "AccountData.h"
-
-#include <QObject>
-#include <QString>
-#include <QJsonObject>
-#include <QJsonDocument>
-#include <QNetworkReply>
-#include <QByteArray>
-
-#include <QDebug>
-
-#include "Application.h"
-
-Yggdrasil::Yggdrasil(AccountData *data, QObject *parent)
- : AccountTask(data, parent)
-{
- changeState(AccountTaskState::STATE_CREATED);
-}
-
-void Yggdrasil::sendRequest(QUrl endpoint, QByteArray content) {
- changeState(AccountTaskState::STATE_WORKING);
-
- QNetworkRequest netRequest(endpoint);
- netRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
- m_netReply = APPLICATION->network()->post(netRequest, content);
- connect(m_netReply, &QNetworkReply::finished, this, &Yggdrasil::processReply);
- connect(m_netReply, &QNetworkReply::uploadProgress, this, &Yggdrasil::refreshTimers);
- connect(m_netReply, &QNetworkReply::downloadProgress, this, &Yggdrasil::refreshTimers);
- connect(m_netReply, &QNetworkReply::sslErrors, this, &Yggdrasil::sslErrors);
- timeout_keeper.setSingleShot(true);
- timeout_keeper.start(timeout_max);
- counter.setSingleShot(false);
- counter.start(time_step);
- progress(0, timeout_max);
- connect(&timeout_keeper, &QTimer::timeout, this, &Yggdrasil::abortByTimeout);
- connect(&counter, &QTimer::timeout, this, &Yggdrasil::heartbeat);
-}
-
-void Yggdrasil::executeTask() {
-}
-
-void Yggdrasil::refresh() {
- start();
- /*
- * {
- * "clientToken": "client identifier"
- * "accessToken": "current access token to be refreshed"
- * "selectedProfile": // specifying this causes errors
- * {
- * "id": "profile ID"
- * "name": "profile name"
- * }
- * "requestUser": true/false // request the user structure
- * }
- */
- QJsonObject req;
- req.insert("clientToken", m_data->clientToken());
- req.insert("accessToken", m_data->accessToken());
- /*
- {
- auto currentProfile = m_account->currentProfile();
- QJsonObject profile;
- profile.insert("id", currentProfile->id());
- profile.insert("name", currentProfile->name());
- req.insert("selectedProfile", profile);
- }
- */
- req.insert("requestUser", false);
- QJsonDocument doc(req);
-
- QUrl reqUrl("https://authserver.mojang.com/refresh");
- QByteArray requestData = doc.toJson();
-
- sendRequest(reqUrl, requestData);
-}
-
-void Yggdrasil::login(QString password) {
- start();
- /*
- * {
- * "agent": { // optional
- * "name": "Minecraft", // So far this is the only encountered value
- * "version": 1 // This number might be increased
- * // by the vanilla client in the future
- * },
- * "username": "mojang account name", // Can be an email address or player name for
- * // unmigrated accounts
- * "password": "mojang account password",
- * "clientToken": "client identifier", // optional
- * "requestUser": true/false // request the user structure
- * }
- */
- QJsonObject req;
-
- {
- QJsonObject agent;
- // C++ makes string literals void* for some stupid reason, so we have to tell it
- // QString... Thanks Obama.
- agent.insert("name", QString("Minecraft"));
- agent.insert("version", 1);
- req.insert("agent", agent);
- }
-
- req.insert("username", m_data->userName());
- req.insert("password", password);
- req.insert("requestUser", false);
-
- // If we already have a client token, give it to the server.
- // Otherwise, let the server give us one.
-
- m_data->generateClientTokenIfMissing();
- req.insert("clientToken", m_data->clientToken());
-
- QJsonDocument doc(req);
-
- QUrl reqUrl("https://authserver.mojang.com/authenticate");
- QNetworkRequest netRequest(reqUrl);
- QByteArray requestData = doc.toJson();
-
- sendRequest(reqUrl, requestData);
-}
-
-
-
-void Yggdrasil::refreshTimers(qint64, qint64) {
- timeout_keeper.stop();
- timeout_keeper.start(timeout_max);
- progress(count = 0, timeout_max);
-}
-
-void Yggdrasil::heartbeat() {
- count += time_step;
- progress(count, timeout_max);
-}
-
-bool Yggdrasil::abort() {
- progress(timeout_max, timeout_max);
- // TODO: actually use this in a meaningful way
- m_aborted = Yggdrasil::BY_USER;
- m_netReply->abort();
- return true;
-}
-
-void Yggdrasil::abortByTimeout() {
- progress(timeout_max, timeout_max);
- // TODO: actually use this in a meaningful way
- m_aborted = Yggdrasil::BY_TIMEOUT;
- m_netReply->abort();
-}
-
-void Yggdrasil::sslErrors(QList<QSslError> errors) {
- int i = 1;
- for (auto error : errors) {
- qCritical() << "LOGIN SSL Error #" << i << " : " << error.errorString();
- auto cert = error.certificate();
- qCritical() << "Certificate in question:\n" << cert.toText();
- i++;
- }
-}
-
-void Yggdrasil::processResponse(QJsonObject responseData) {
- // Read the response data. We need to get the client token, access token, and the selected
- // profile.
- qDebug() << "Processing authentication response.";
-
- // qDebug() << responseData;
- // If we already have a client token, make sure the one the server gave us matches our
- // existing one.
- QString clientToken = responseData.value("clientToken").toString("");
- if (clientToken.isEmpty()) {
- // Fail if the server gave us an empty client token
- changeState(AccountTaskState::STATE_FAILED_HARD, tr("Authentication server didn't send a client token."));
- return;
- }
- if(m_data->clientToken().isEmpty()) {
- m_data->setClientToken(clientToken);
- }
- else if(clientToken != m_data->clientToken()) {
- changeState(AccountTaskState::STATE_FAILED_HARD, tr("Authentication server attempted to change the client token. This isn't supported."));
- return;
- }
-
- // Now, we set the access token.
- qDebug() << "Getting access token.";
- QString accessToken = responseData.value("accessToken").toString("");
- if (accessToken.isEmpty()) {
- // Fail if the server didn't give us an access token.
- changeState(AccountTaskState::STATE_FAILED_HARD, tr("Authentication server didn't send an access token."));
- return;
- }
- // Set the access token.
- m_data->yggdrasilToken.token = accessToken;
- m_data->yggdrasilToken.validity = Katabasis::Validity::Certain;
- m_data->yggdrasilToken.issueInstant = QDateTime::currentDateTimeUtc();
-
- // We've made it through the minefield of possible errors. Return true to indicate that
- // we've succeeded.
- qDebug() << "Finished reading authentication response.";
- changeState(AccountTaskState::STATE_SUCCEEDED);
-}
-
-void Yggdrasil::processReply() {
- changeState(AccountTaskState::STATE_WORKING);
-
- switch (m_netReply->error())
- {
- case QNetworkReply::NoError:
- break;
- case QNetworkReply::TimeoutError:
- changeState(AccountTaskState::STATE_FAILED_SOFT, tr("Authentication operation timed out."));
- return;
- case QNetworkReply::OperationCanceledError:
- changeState(AccountTaskState::STATE_FAILED_SOFT, tr("Authentication operation cancelled."));
- return;
- case QNetworkReply::SslHandshakeFailedError:
- changeState(
- AccountTaskState::STATE_FAILED_SOFT,
- tr(
- "<b>SSL Handshake failed.</b><br/>There might be a few causes for it:<br/>"
- "<ul>"
- "<li>You use Windows and need to update your root certificates, please install any outstanding updates.</li>"
- "<li>Some device on your network is interfering with SSL traffic. In that case, "
- "you have bigger worries than Minecraft not starting.</li>"
- "<li>Possibly something else. Check the log file for details</li>"
- "</ul>"
- )
- );
- return;
- // used for invalid credentials and similar errors. Fall through.
- case QNetworkReply::ContentAccessDenied:
- case QNetworkReply::ContentOperationNotPermittedError:
- break;
- case QNetworkReply::ContentGoneError: {
- changeState(
- AccountTaskState::STATE_FAILED_GONE,
- tr("The Mojang account no longer exists. It may have been migrated to a Microsoft account.")
- );
- }
- default:
- changeState(
- AccountTaskState::STATE_FAILED_SOFT,
- tr("Authentication operation failed due to a network error: %1 (%2)").arg(m_netReply->errorString()).arg(m_netReply->error())
- );
- return;
- }
-
- // Try to parse the response regardless of the response code.
- // Sometimes the auth server will give more information and an error code.
- QJsonParseError jsonError;
- QByteArray replyData = m_netReply->readAll();
- QJsonDocument doc = QJsonDocument::fromJson(replyData, &jsonError);
- // Check the response code.
- int responseCode = m_netReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
-
- if (responseCode == 200) {
- // If the response code was 200, then there shouldn't be an error. Make sure
- // anyways.
- // Also, sometimes an empty reply indicates success. If there was no data received,
- // pass an empty json object to the processResponse function.
- if (jsonError.error == QJsonParseError::NoError || replyData.size() == 0) {
- processResponse(replyData.size() > 0 ? doc.object() : QJsonObject());
- return;
- }
- else {
- changeState(
- AccountTaskState::STATE_FAILED_SOFT,
- tr("Failed to parse authentication server response JSON response: %1 at offset %2.").arg(jsonError.errorString()).arg(jsonError.offset)
- );
- qCritical() << replyData;
- }
- return;
- }
-
- // If the response code was not 200, then Yggdrasil may have given us information
- // about the error.
- // If we can parse the response, then get information from it. Otherwise just say
- // there was an unknown error.
- if (jsonError.error == QJsonParseError::NoError) {
- // We were able to parse the server's response. Woo!
- // Call processError. If a subclass has overridden it then they'll handle their
- // stuff there.
- qDebug() << "The request failed, but the server gave us an error message. Processing error.";
- processError(doc.object());
- }
- else {
- // The server didn't say anything regarding the error. Give the user an unknown
- // error.
- qDebug() << "The request failed and the server gave no error message. Unknown error.";
- changeState(
- AccountTaskState::STATE_FAILED_SOFT,
- tr("An unknown error occurred when trying to communicate with the authentication server: %1").arg(m_netReply->errorString())
- );
- }
-}
-
-void Yggdrasil::processError(QJsonObject responseData) {
- QJsonValue errorVal = responseData.value("error");
- QJsonValue errorMessageValue = responseData.value("errorMessage");
- QJsonValue causeVal = responseData.value("cause");
-
- if (errorVal.isString() && errorMessageValue.isString()) {
- m_error = std::shared_ptr<Error>(
- new Error {
- errorVal.toString(""),
- errorMessageValue.toString(""),
- causeVal.toString("")
- }
- );
- changeState(AccountTaskState::STATE_FAILED_HARD, m_error->m_errorMessageVerbose);
- }
- else {
- // Error is not in standard format. Don't set m_error and return unknown error.
- changeState(AccountTaskState::STATE_FAILED_HARD, tr("An unknown Yggdrasil error occurred."));
- }
-}
diff --git a/launcher/minecraft/auth/Yggdrasil.h b/launcher/minecraft/auth/Yggdrasil.h
deleted file mode 100644
index 4f52a04c2c..0000000000
--- a/launcher/minecraft/auth/Yggdrasil.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/* 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 "AccountTask.h"
-
-#include <QString>
-#include <QJsonObject>
-#include <QTimer>
-#include <qsslerror.h>
-
-#include "MinecraftAccount.h"
-
-class QNetworkAccessManager;
-class QNetworkReply;
-
-/**
- * A Yggdrasil task is a task that performs an operation on a given mojang account.
- */
-class Yggdrasil : public AccountTask
-{
- Q_OBJECT
-public:
- explicit Yggdrasil(
- AccountData *data,
- QObject *parent = 0
- );
- virtual ~Yggdrasil() = default;
-
- void refresh();
- void login(QString password);
-
- struct Error
- {
- QString m_errorMessageShort;
- QString m_errorMessageVerbose;
- QString m_cause;
- };
- std::shared_ptr<Error> m_error;
-
- enum AbortedBy
- {
- BY_NOTHING,
- BY_USER,
- BY_TIMEOUT
- } m_aborted = BY_NOTHING;
-
-protected:
- void executeTask() override;
-
- /**
- * Processes the response received from the server.
- * If an error occurred, this should emit a failed signal.
- * If Yggdrasil gave an error response, it should call setError() first, and then return false.
- * Otherwise, it should return true.
- * Note: If the response from the server was blank, and the HTTP code was 200, this function is called with
- * an empty QJsonObject.
- */
- void processResponse(QJsonObject responseData);
-
- /**
- * Processes an error response received from the server.
- * The default implementation will read data from Yggdrasil's standard error response format and set it as this task's Error.
- * \returns a QString error message that will be passed to emitFailed.
- */
- virtual void processError(QJsonObject responseData);
-
-protected slots:
- void processReply();
- void refreshTimers(qint64, qint64);
- void heartbeat();
- void sslErrors(QList<QSslError>);
- void abortByTimeout();
-
-public slots:
- virtual bool abort() override;
-
-private:
- void sendRequest(QUrl endpoint, QByteArray content);
-
-protected:
- QNetworkReply *m_netReply = nullptr;
- QTimer timeout_keeper;
- QTimer counter;
- int count = 0; // num msec since time reset
-
- const int timeout_max = 30000;
- const int time_step = 50;
-};
diff --git a/launcher/minecraft/auth/flows/AuthFlow.cpp b/launcher/minecraft/auth/flows/AuthFlow.cpp
index 4f78e8c31e..46904a48af 100644
--- a/launcher/minecraft/auth/flows/AuthFlow.cpp
+++ b/launcher/minecraft/auth/flows/AuthFlow.cpp
@@ -40,8 +40,7 @@ void AuthFlow::nextStep() {
qDebug() << "AuthFlow:" << m_currentStep->describe();
m_steps.pop_front();
connect(m_currentStep.get(), &AuthStep::finished, this, &AuthFlow::stepFinished);
- connect(m_currentStep.get(), &AuthStep::showVerificationUriAndCode, this, &AuthFlow::showVerificationUriAndCode);
- connect(m_currentStep.get(), &AuthStep::hideVerificationUriAndCode, this, &AuthFlow::hideVerificationUriAndCode);
+ connect(m_currentStep.get(), &AuthStep::authorizeWithBrowser, this, &AuthFlow::authorizeWithBrowser);
m_currentStep->perform();
}
diff --git a/launcher/minecraft/auth/flows/AuthFlow.h b/launcher/minecraft/auth/flows/AuthFlow.h
index e067cc99fb..e840060be4 100644
--- a/launcher/minecraft/auth/flows/AuthFlow.h
+++ b/launcher/minecraft/auth/flows/AuthFlow.h
@@ -7,9 +7,6 @@
#include <QNetworkReply>
#include <QImage>
-#include <katabasis/DeviceFlow.h>
-
-#include "minecraft/auth/Yggdrasil.h"
#include "minecraft/auth/AccountData.h"
#include "minecraft/auth/AccountTask.h"
#include "minecraft/auth/AuthStep.h"
@@ -30,7 +27,7 @@ public:
void executeTask() override;
signals:
- void activityChanged(Katabasis::Activity activity);
+ // No extra signals needed - authorizeWithBrowser is on AccountTask
private slots:
void stepFinished(AccountTaskState resultingState, QString message);
diff --git a/launcher/minecraft/auth/flows/Mojang.cpp b/launcher/minecraft/auth/flows/Mojang.cpp
deleted file mode 100644
index 4661dbe23a..0000000000
--- a/launcher/minecraft/auth/flows/Mojang.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-#include "Mojang.h"
-
-#include "minecraft/auth/steps/YggdrasilStep.h"
-#include "minecraft/auth/steps/MinecraftProfileStep.h"
-#include "minecraft/auth/steps/MigrationEligibilityStep.h"
-#include "minecraft/auth/steps/GetSkinStep.h"
-
-MojangRefresh::MojangRefresh(
- AccountData *data,
- QObject *parent
-) : AuthFlow(data, parent) {
- m_steps.append(new YggdrasilStep(m_data, QString()));
- m_steps.append(new MinecraftProfileStep(m_data));
- m_steps.append(new MigrationEligibilityStep(m_data));
- m_steps.append(new GetSkinStep(m_data));
-}
-
-MojangLogin::MojangLogin(
- AccountData *data,
- QString password,
- QObject *parent
-): AuthFlow(data, parent), m_password(password) {
- m_steps.append(new YggdrasilStep(m_data, m_password));
- m_steps.append(new MinecraftProfileStep(m_data));
- m_steps.append(new MigrationEligibilityStep(m_data));
- m_steps.append(new GetSkinStep(m_data));
-}
diff --git a/launcher/minecraft/auth/flows/Mojang.h b/launcher/minecraft/auth/flows/Mojang.h
deleted file mode 100644
index c09c81a807..0000000000
--- a/launcher/minecraft/auth/flows/Mojang.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#pragma once
-#include "AuthFlow.h"
-
-class MojangRefresh : public AuthFlow
-{
- Q_OBJECT
-public:
- explicit MojangRefresh(
- AccountData *data,
- QObject *parent = 0
- );
-};
-
-class MojangLogin : public AuthFlow
-{
- Q_OBJECT
-public:
- explicit MojangLogin(
- AccountData *data,
- QString password,
- QObject *parent = 0
- );
-
-private:
- QString m_password;
-};
diff --git a/launcher/minecraft/auth/steps/MSAStep.cpp b/launcher/minecraft/auth/steps/MSAStep.cpp
index be711f7e8c..b3d57eb15e 100644
--- a/launcher/minecraft/auth/steps/MSAStep.cpp
+++ b/launcher/minecraft/auth/steps/MSAStep.cpp
@@ -1,27 +1,28 @@
#include "MSAStep.h"
#include <QNetworkRequest>
+#include <QDesktopServices>
#include "minecraft/auth/AuthRequest.h"
#include "minecraft/auth/Parsers.h"
#include "Application.h"
-using OAuth2 = Katabasis::DeviceFlow;
-using Activity = Katabasis::Activity;
-
MSAStep::MSAStep(AccountData* data, Action action) : AuthStep(data), m_action(action) {
- OAuth2::Options opts;
- opts.scope = "XboxLive.signin offline_access";
- opts.clientIdentifier = APPLICATION->msaClientId();
- opts.authorizationUrl = "https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode";
- opts.accessTokenUrl = "https://login.microsoftonline.com/consumers/oauth2/v2.0/token";
+ m_replyHandler = new QOAuthHttpServerReplyHandler(this);
+ m_replyHandler->setCallbackText(tr("Login successful! You can close this page and return to MeshMC."));
- // FIXME: OAuth2 is not aware of our fancy shared pointers
- m_oauth2 = new OAuth2(opts, m_data->msaToken, this, APPLICATION->network().get());
+ m_oauth2 = new QOAuth2AuthorizationCodeFlow(this);
+ m_oauth2->setClientIdentifier(APPLICATION->msaClientId());
+ m_oauth2->setAuthorizationUrl(QUrl("https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize"));
+ m_oauth2->setTokenUrl(QUrl("https://login.microsoftonline.com/consumers/oauth2/v2.0/token"));
+ m_oauth2->setScope("XboxLive.signin offline_access");
+ m_oauth2->setReplyHandler(m_replyHandler);
+ m_oauth2->setNetworkAccessManager(APPLICATION->network().get());
- connect(m_oauth2, &OAuth2::activityChanged, this, &MSAStep::onOAuthActivityChanged);
- connect(m_oauth2, &OAuth2::showVerificationUriAndCode, this, &MSAStep::showVerificationUriAndCode);
+ connect(m_oauth2, &QOAuth2AuthorizationCodeFlow::granted, this, &MSAStep::onGranted);
+ connect(m_oauth2, &QOAuth2AuthorizationCodeFlow::requestFailed, this, &MSAStep::onRequestFailed);
+ connect(m_oauth2, &QOAuth2AuthorizationCodeFlow::authorizeWithBrowser, this, &MSAStep::onOpenBrowser);
}
MSAStep::~MSAStep() noexcept = default;
@@ -47,65 +48,71 @@ void MSAStep::rehydrate() {
void MSAStep::perform() {
switch(m_action) {
case Refresh: {
- m_oauth2->refresh();
+ // Load the refresh token from stored account data
+ m_oauth2->setRefreshToken(m_data->msaToken.refresh_token);
+ m_oauth2->refreshTokens();
return;
}
case Login: {
- QVariantMap extraOpts;
- extraOpts["prompt"] = "select_account";
- m_oauth2->setExtraRequestParams(extraOpts);
-
*m_data = AccountData();
- m_oauth2->login();
+ if (!m_replyHandler->isListening()) {
+ if (!m_replyHandler->listen(QHostAddress::LocalHost)) {
+ emit finished(AccountTaskState::STATE_FAILED_HARD, tr("Failed to start local HTTP server for OAuth2 callback."));
+ return;
+ }
+ }
+ m_oauth2->setModifyParametersFunction(
+ [](QAbstractOAuth::Stage stage, QMultiMap<QString, QVariant> *parameters) {
+ if (stage == QAbstractOAuth::Stage::RequestingAuthorization) {
+ parameters->insert("prompt", "select_account");
+ }
+ }
+ );
+ m_oauth2->grant();
return;
}
}
}
-void MSAStep::onOAuthActivityChanged(Katabasis::Activity activity) {
- switch(activity) {
- case Katabasis::Activity::Idle:
- case Katabasis::Activity::LoggingIn:
- case Katabasis::Activity::Refreshing:
- case Katabasis::Activity::LoggingOut: {
- // We asked it to do something, it's doing it. Nothing to act upon.
- return;
- }
- case Katabasis::Activity::Succeeded: {
- // Succeeded or did not invalidate tokens
- emit hideVerificationUriAndCode();
- QVariantMap extraTokens = m_oauth2->extraTokens();
-#ifndef NDEBUG
- if (!extraTokens.isEmpty()) {
- qDebug() << "Extra tokens in response:";
- foreach (QString key, extraTokens.keys()) {
- qDebug() << "\t" << key << ":" << extraTokens.value(key);
- }
- }
-#endif
- emit finished(AccountTaskState::STATE_WORKING, tr("Got "));
- return;
- }
- case Katabasis::Activity::FailedSoft: {
- // NOTE: soft error in the first step means 'offline'
- emit hideVerificationUriAndCode();
- emit finished(AccountTaskState::STATE_OFFLINE, tr("Microsoft user authentication ended with a network error."));
+void MSAStep::onOpenBrowser(const QUrl &url) {
+ emit authorizeWithBrowser(url);
+ QDesktopServices::openUrl(url);
+}
+
+void MSAStep::onGranted() {
+ m_replyHandler->close();
+
+ // Store the tokens in account data
+ m_data->msaToken.token = m_oauth2->token();
+ m_data->msaToken.refresh_token = m_oauth2->refreshToken();
+ m_data->msaToken.issueInstant = QDateTime::currentDateTimeUtc();
+ m_data->msaToken.notAfter = m_oauth2->expirationAt();
+ if (!m_data->msaToken.notAfter.isValid()) {
+ m_data->msaToken.notAfter = m_data->msaToken.issueInstant.addSecs(3600);
+ }
+ m_data->msaToken.validity = Katabasis::Validity::Certain;
+
+ emit finished(AccountTaskState::STATE_WORKING, tr("Got MSA token."));
+}
+
+void MSAStep::onRequestFailed(QAbstractOAuth::Error error) {
+ m_replyHandler->close();
+
+ switch(error) {
+ case QAbstractOAuth::Error::NetworkError:
+ emit finished(AccountTaskState::STATE_OFFLINE, tr("Microsoft authentication failed due to a network error."));
return;
- }
- case Katabasis::Activity::FailedGone: {
- emit hideVerificationUriAndCode();
- emit finished(AccountTaskState::STATE_FAILED_GONE, tr("Microsoft user authentication failed - user no longer exists."));
+ case QAbstractOAuth::Error::ServerError:
+ case QAbstractOAuth::Error::OAuthTokenNotFoundError:
+ case QAbstractOAuth::Error::OAuthTokenSecretNotFoundError:
+ case QAbstractOAuth::Error::OAuthCallbackNotVerified:
+ emit finished(AccountTaskState::STATE_FAILED_HARD, tr("Microsoft authentication failed."));
return;
- }
- case Katabasis::Activity::FailedHard: {
- emit hideVerificationUriAndCode();
- emit finished(AccountTaskState::STATE_FAILED_HARD, tr("Microsoft user authentication failed."));
+ case QAbstractOAuth::Error::ExpiredError:
+ emit finished(AccountTaskState::STATE_FAILED_GONE, tr("Microsoft authentication token expired."));
return;
- }
- default: {
- emit hideVerificationUriAndCode();
- emit finished(AccountTaskState::STATE_FAILED_HARD, tr("Microsoft user authentication completed with an unrecognized result."));
+ default:
+ emit finished(AccountTaskState::STATE_FAILED_HARD, tr("Microsoft authentication failed with an unrecognized error."));
return;
- }
}
}
diff --git a/launcher/minecraft/auth/steps/MSAStep.h b/launcher/minecraft/auth/steps/MSAStep.h
index 49ba3542e7..36fc23213f 100644
--- a/launcher/minecraft/auth/steps/MSAStep.h
+++ b/launcher/minecraft/auth/steps/MSAStep.h
@@ -5,7 +5,8 @@
#include "QObjectPtr.h"
#include "minecraft/auth/AuthStep.h"
-#include <katabasis/DeviceFlow.h>
+#include <QOAuth2AuthorizationCodeFlow>
+#include <QOAuthHttpServerReplyHandler>
class MSAStep : public AuthStep {
Q_OBJECT
@@ -24,9 +25,12 @@ public:
QString describe() override;
private slots:
- void onOAuthActivityChanged(Katabasis::Activity activity);
+ void onGranted();
+ void onRequestFailed(QAbstractOAuth::Error error);
+ void onOpenBrowser(const QUrl &url);
private:
- Katabasis::DeviceFlow *m_oauth2 = nullptr;
+ QOAuth2AuthorizationCodeFlow *m_oauth2 = nullptr;
+ QOAuthHttpServerReplyHandler *m_replyHandler = nullptr;
Action m_action;
};
diff --git a/launcher/minecraft/auth/steps/MigrationEligibilityStep.cpp b/launcher/minecraft/auth/steps/MigrationEligibilityStep.cpp
deleted file mode 100644
index f5b5637a47..0000000000
--- a/launcher/minecraft/auth/steps/MigrationEligibilityStep.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-#include "MigrationEligibilityStep.h"
-
-#include <QNetworkRequest>
-
-#include "minecraft/auth/AuthRequest.h"
-#include "minecraft/auth/Parsers.h"
-
-MigrationEligibilityStep::MigrationEligibilityStep(AccountData* data) : AuthStep(data) {
-
-}
-
-MigrationEligibilityStep::~MigrationEligibilityStep() noexcept = default;
-
-QString MigrationEligibilityStep::describe() {
- return tr("Checking for migration eligibility.");
-}
-
-void MigrationEligibilityStep::perform() {
- auto url = QUrl("https://api.minecraftservices.com/rollout/v1/msamigration");
- QNetworkRequest request = QNetworkRequest(url);
- request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
- request.setRawHeader("Authorization", QString("Bearer %1").arg(m_data->yggdrasilToken.token).toUtf8());
-
- AuthRequest *requestor = new AuthRequest(this);
- connect(requestor, &AuthRequest::finished, this, &MigrationEligibilityStep::onRequestDone);
- requestor->get(request);
-}
-
-void MigrationEligibilityStep::rehydrate() {
- // NOOP, for now. We only save bools and there's nothing to check.
-}
-
-void MigrationEligibilityStep::onRequestDone(
- QNetworkReply::NetworkError error,
- QByteArray data,
- QList<QNetworkReply::RawHeaderPair> headers
-) {
- auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
- requestor->deleteLater();
-
- if (error == QNetworkReply::NoError) {
- Parsers::parseRolloutResponse(data, m_data->canMigrateToMSA);
- }
- emit finished(AccountTaskState::STATE_WORKING, tr("Got migration flags"));
-}
diff --git a/launcher/minecraft/auth/steps/MigrationEligibilityStep.h b/launcher/minecraft/auth/steps/MigrationEligibilityStep.h
deleted file mode 100644
index b1bf9cbf49..0000000000
--- a/launcher/minecraft/auth/steps/MigrationEligibilityStep.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#pragma once
-#include <QObject>
-
-#include "QObjectPtr.h"
-#include "minecraft/auth/AuthStep.h"
-
-
-class MigrationEligibilityStep : public AuthStep {
- Q_OBJECT
-
-public:
- explicit MigrationEligibilityStep(AccountData *data);
- virtual ~MigrationEligibilityStep() noexcept;
-
- void perform() override;
- void rehydrate() override;
-
- QString describe() override;
-
-private slots:
- void onRequestDone(QNetworkReply::NetworkError, QByteArray, QList<QNetworkReply::RawHeaderPair>);
-};
diff --git a/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp b/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp
index add9165998..94dddf1786 100644
--- a/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp
+++ b/launcher/minecraft/auth/steps/MinecraftProfileStep.cpp
@@ -44,10 +44,6 @@ void MinecraftProfileStep::onRequestDone(
#endif
if (error == QNetworkReply::ContentNotFoundError) {
// NOTE: Succeed even if we do not have a profile. This is a valid account state.
- if(m_data->type == AccountType::Mojang) {
- m_data->minecraftEntitlement.canPlayMinecraft = false;
- m_data->minecraftEntitlement.ownsMinecraft = false;
- }
m_data->minecraftProfile = MinecraftProfile();
emit finished(
AccountTaskState::STATE_SUCCEEDED,
@@ -79,11 +75,6 @@ void MinecraftProfileStep::onRequestDone(
return;
}
- if(m_data->type == AccountType::Mojang) {
- auto validProfile = m_data->minecraftProfile.validity == Katabasis::Validity::Certain;
- m_data->minecraftEntitlement.canPlayMinecraft = validProfile;
- m_data->minecraftEntitlement.ownsMinecraft = validProfile;
- }
emit finished(
AccountTaskState::STATE_WORKING,
tr("Minecraft Java profile acquisition succeeded.")
diff --git a/launcher/minecraft/auth/steps/YggdrasilStep.cpp b/launcher/minecraft/auth/steps/YggdrasilStep.cpp
deleted file mode 100644
index 4c6b1624b3..0000000000
--- a/launcher/minecraft/auth/steps/YggdrasilStep.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-#include "YggdrasilStep.h"
-
-#include "minecraft/auth/AuthRequest.h"
-#include "minecraft/auth/Parsers.h"
-#include "minecraft/auth/Yggdrasil.h"
-
-YggdrasilStep::YggdrasilStep(AccountData* data, QString password) : AuthStep(data), m_password(password) {
- m_yggdrasil = new Yggdrasil(m_data, this);
-
- connect(m_yggdrasil, &Task::failed, this, &YggdrasilStep::onAuthFailed);
- connect(m_yggdrasil, &Task::succeeded, this, &YggdrasilStep::onAuthSucceeded);
-}
-
-YggdrasilStep::~YggdrasilStep() noexcept = default;
-
-QString YggdrasilStep::describe() {
- return tr("Logging in with Mojang account.");
-}
-
-void YggdrasilStep::rehydrate() {
- // NOOP, for now.
-}
-
-void YggdrasilStep::perform() {
- if(m_password.size()) {
- m_yggdrasil->login(m_password);
- }
- else {
- m_yggdrasil->refresh();
- }
-}
-
-void YggdrasilStep::onAuthSucceeded() {
- emit finished(AccountTaskState::STATE_WORKING, tr("Logged in with Mojang"));
-}
-
-void YggdrasilStep::onAuthFailed() {
- // TODO: hook these in again, expand to MSA
- // m_error = m_yggdrasil->m_error;
- // m_aborted = m_yggdrasil->m_aborted;
-
- auto state = m_yggdrasil->taskState();
- QString errorMessage = tr("Mojang user authentication failed.");
-
- // NOTE: soft error in the first step means 'offline'
- if(state == AccountTaskState::STATE_FAILED_SOFT) {
- state = AccountTaskState::STATE_OFFLINE;
- errorMessage = tr("Mojang user authentication ended with a network error.");
- }
- emit finished(state, errorMessage);
-}
diff --git a/launcher/minecraft/auth/steps/YggdrasilStep.h b/launcher/minecraft/auth/steps/YggdrasilStep.h
deleted file mode 100644
index ebafb8e5b1..0000000000
--- a/launcher/minecraft/auth/steps/YggdrasilStep.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#pragma once
-#include <QObject>
-
-#include "QObjectPtr.h"
-#include "minecraft/auth/AuthStep.h"
-
-class Yggdrasil;
-
-class YggdrasilStep : public AuthStep {
- Q_OBJECT
-
-public:
- explicit YggdrasilStep(AccountData *data, QString password);
- virtual ~YggdrasilStep() noexcept;
-
- void perform() override;
- void rehydrate() override;
-
- QString describe() override;
-
-private slots:
- void onAuthSucceeded();
- void onAuthFailed();
-
-private:
- Yggdrasil *m_yggdrasil = nullptr;
- QString m_password;
-};
diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp
index f0c53c3929..dbc613d79d 100644
--- a/launcher/minecraft/mod/ModFolderModel.cpp
+++ b/launcher/minecraft/mod/ModFolderModel.cpp
@@ -89,9 +89,11 @@ bool ModFolderModel::update()
void ModFolderModel::finishUpdate()
{
- QSet<QString> currentSet = modsIndex.keys().toSet();
+ auto keys1 = modsIndex.keys();
+ QSet<QString> currentSet(keys1.begin(), keys1.end());
auto & newMods = m_update->mods;
- QSet<QString> newSet = newMods.keys().toSet();
+ auto keys2 = newMods.keys();
+ QSet<QString> newSet(keys2.begin(), keys2.end());
// see if the kept mods changed in some way
{
@@ -278,7 +280,7 @@ bool ModFolderModel::installMod(const QString &filename)
return false;
}
FS::updateTimestamp(newpath);
- installedMod.repath(newpath);
+ installedMod.repath(QFileInfo(newpath));
update();
return true;
}
@@ -296,7 +298,7 @@ bool ModFolderModel::installMod(const QString &filename)
qWarning() << "Copy of folder from" << originalPath << "to" << newpath << "has (potentially partially) failed.";
return false;
}
- installedMod.repath(newpath);
+ installedMod.repath(QFileInfo(newpath));
update();
return true;
}
diff --git a/launcher/minecraft/services/CapeChange.cpp b/launcher/minecraft/services/CapeChange.cpp
index e49c166abe..25041d26e1 100644
--- a/launcher/minecraft/services/CapeChange.cpp
+++ b/launcher/minecraft/services/CapeChange.cpp
@@ -20,7 +20,7 @@ void CapeChange::setCape(QString& cape) {
m_reply = shared_qobject_ptr<QNetworkReply>(rep);
connect(rep, &QNetworkReply::uploadProgress, this, &Task::setProgress);
- connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(downloadError(QNetworkReply::NetworkError)));
+ connect(rep, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(downloadError(QNetworkReply::NetworkError)));
connect(rep, SIGNAL(finished()), this, SLOT(downloadFinished()));
}
@@ -34,7 +34,7 @@ void CapeChange::clearCape() {
m_reply = shared_qobject_ptr<QNetworkReply>(rep);
connect(rep, &QNetworkReply::uploadProgress, this, &Task::setProgress);
- connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(downloadError(QNetworkReply::NetworkError)));
+ connect(rep, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(downloadError(QNetworkReply::NetworkError)));
connect(rep, SIGNAL(finished()), this, SLOT(downloadFinished()));
}
diff --git a/launcher/minecraft/services/SkinDelete.cpp b/launcher/minecraft/services/SkinDelete.cpp
index cce8364e18..cd383cfbfb 100644
--- a/launcher/minecraft/services/SkinDelete.cpp
+++ b/launcher/minecraft/services/SkinDelete.cpp
@@ -19,7 +19,7 @@ void SkinDelete::executeTask()
setStatus(tr("Deleting skin"));
connect(rep, &QNetworkReply::uploadProgress, this, &Task::setProgress);
- connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(downloadError(QNetworkReply::NetworkError)));
+ connect(rep, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(downloadError(QNetworkReply::NetworkError)));
connect(rep, SIGNAL(finished()), this, SLOT(downloadFinished()));
}
diff --git a/launcher/minecraft/services/SkinUpload.cpp b/launcher/minecraft/services/SkinUpload.cpp
index 7c2e833770..4aacedc34d 100644
--- a/launcher/minecraft/services/SkinUpload.cpp
+++ b/launcher/minecraft/services/SkinUpload.cpp
@@ -44,7 +44,7 @@ void SkinUpload::executeTask()
setStatus(tr("Uploading skin"));
connect(rep, &QNetworkReply::uploadProgress, this, &Task::setProgress);
- connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(downloadError(QNetworkReply::NetworkError)));
+ connect(rep, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(downloadError(QNetworkReply::NetworkError)));
connect(rep, SIGNAL(finished()), this, SLOT(downloadFinished()));
}
diff --git a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp
index 0f4f6dbbd9..2716856c55 100644
--- a/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp
+++ b/launcher/modplatform/atlauncher/ATLPackInstallTask.cpp
@@ -18,6 +18,7 @@
#include "ATLPackInstallTask.h"
#include <QtConcurrent/QtConcurrent>
+#include <QRegularExpression>
#include <quazip.h>
@@ -475,7 +476,11 @@ void PackInstallTask::extractConfigs()
return;
}
- m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractDir, archivePath, extractDir.absolutePath() + "/minecraft");
+ QString extractPath = extractDir.absolutePath() + "/minecraft";
+ QString archivePathCopy = archivePath;
+ m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), [archivePathCopy, extractPath]() {
+ return MMCZip::extractDir(archivePathCopy, extractPath);
+ });
connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::finished, this, [&]()
{
downloadMods();
@@ -623,7 +628,12 @@ void PackInstallTask::onModsDownloaded() {
jobPtr.reset();
if(!modsToExtract.empty() || !modsToDecomp.empty() || !modsToCopy.empty()) {
- m_modExtractFuture = QtConcurrent::run(QThreadPool::globalInstance(), this, &PackInstallTask::extractMods, modsToExtract, modsToDecomp, modsToCopy);
+ auto modsToExtractCopy = modsToExtract;
+ auto modsToDecompCopy = modsToDecomp;
+ auto modsToCopyCopy = modsToCopy;
+ m_modExtractFuture = QtConcurrent::run(QThreadPool::globalInstance(), [this, modsToExtractCopy, modsToDecompCopy, modsToCopyCopy]() {
+ return this->extractMods(modsToExtractCopy, modsToDecompCopy, modsToCopyCopy);
+ });
connect(&m_modExtractFutureWatcher, &QFutureWatcher<QStringList>::finished, this, &PackInstallTask::onModsExtracted);
connect(&m_modExtractFutureWatcher, &QFutureWatcher<QStringList>::canceled, this, [&]()
{
@@ -675,7 +685,7 @@ bool PackInstallTask::extractMods(
QString folderToExtract = "";
if(mod.type == ModType::Extract) {
folderToExtract = mod.extractFolder;
- folderToExtract.remove(QRegExp("^/"));
+ folderToExtract.remove(QRegularExpression("^/"));
}
qDebug() << "Extracting " + mod.file + " to " + extractToDir;
diff --git a/launcher/modplatform/flame/FlamePackIndex.cpp b/launcher/modplatform/flame/FlamePackIndex.cpp
index 387529dbfe..3916665900 100644
--- a/launcher/modplatform/flame/FlamePackIndex.cpp
+++ b/launcher/modplatform/flame/FlamePackIndex.cpp
@@ -98,7 +98,12 @@ void Flame::loadIndexedPackVersions(Flame::IndexedPack & pack, QJsonArray & arr)
file.addonId = pack.addonId;
file.fileId = Json::requireInteger(version, "id");
- auto versionArray = Json::requireArray(version, "gameVersion");
+ QJsonArray versionArray;
+ if(version.contains("gameVersions")) {
+ versionArray = Json::requireArray(version, "gameVersions");
+ } else {
+ versionArray = Json::requireArray(version, "gameVersion");
+ }
if(versionArray.size() < 1) {
continue;
}
@@ -106,7 +111,7 @@ void Flame::loadIndexedPackVersions(Flame::IndexedPack & pack, QJsonArray & arr)
// pick the latest version supported
file.mcVersion = versionArray[0].toString();
file.version = Json::requireString(version, "displayName");
- file.downloadUrl = Json::requireString(version, "downloadUrl");
+ file.downloadUrl = Json::ensureString(version, "downloadUrl", "");
unsortedVersions.append(file);
}
diff --git a/launcher/modplatform/flame/PackManifest.h b/launcher/modplatform/flame/PackManifest.h
index 02f39f0ea9..f24cf5b0b0 100644
--- a/launcher/modplatform/flame/PackManifest.h
+++ b/launcher/modplatform/flame/PackManifest.h
@@ -20,7 +20,7 @@ struct File
bool resolved = false;
QString fileName;
QUrl url;
- QString targetFolder = QLatin1Literal("mods");
+ QString targetFolder = QLatin1String("mods");
enum class Type
{
Unknown,
diff --git a/launcher/modplatform/legacy_ftb/PackFetchTask.cpp b/launcher/modplatform/legacy_ftb/PackFetchTask.cpp
index 961fe868cc..5bc01ed265 100644
--- a/launcher/modplatform/legacy_ftb/PackFetchTask.cpp
+++ b/launcher/modplatform/legacy_ftb/PackFetchTask.cpp
@@ -103,7 +103,7 @@ bool PackFetchTask::parseAndAddPacks(QByteArray &data, PackType packType, Modpac
if(!doc.setContent(data, false, &errorMsg, &errorLine, &errorCol))
{
- auto fullErrMsg = QString("Failed to fetch modpack data: %1 %2:3d!").arg(errorMsg, errorLine, errorCol);
+ auto fullErrMsg = QString("Failed to fetch modpack data: %1 %2:%3!").arg(errorMsg).arg(errorLine).arg(errorCol);
qWarning() << fullErrMsg;
data.clear();
return false;
diff --git a/launcher/modplatform/legacy_ftb/PackInstallTask.cpp b/launcher/modplatform/legacy_ftb/PackInstallTask.cpp
index 1d300192db..9bd55271a4 100644
--- a/launcher/modplatform/legacy_ftb/PackInstallTask.cpp
+++ b/launcher/modplatform/legacy_ftb/PackInstallTask.cpp
@@ -88,7 +88,11 @@ void PackInstallTask::unzip()
return;
}
- m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractDir, archivePath, extractDir.absolutePath() + "/unzip");
+ QString extractPath = extractDir.absolutePath() + "/unzip";
+ QString archivePathCopy = archivePath;
+ m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), [archivePathCopy, extractPath]() {
+ return MMCZip::extractDir(archivePathCopy, extractPath);
+ });
connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::finished, this, &PackInstallTask::onUnzipFinished);
connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::canceled, this, &PackInstallTask::onUnzipCanceled);
m_extractFutureWatcher.setFuture(m_extractFuture);
@@ -137,7 +141,11 @@ void PackInstallTask::install()
QDir jarmodDir = QDir(m_stagingPath + "/unzip/instMods");
if(packJson.exists())
{
- packJson.open(QIODevice::ReadOnly | QIODevice::Text);
+ if (!packJson.open(QIODevice::ReadOnly | QIODevice::Text))
+ {
+ emitFailed(tr("Failed to open pack.json!"));
+ return;
+ }
QJsonDocument doc = QJsonDocument::fromJson(packJson.readAll());
packJson.close();
diff --git a/launcher/modplatform/legacy_ftb/PrivatePackManager.cpp b/launcher/modplatform/legacy_ftb/PrivatePackManager.cpp
index 501e6003ef..09e0e49764 100644
--- a/launcher/modplatform/legacy_ftb/PrivatePackManager.cpp
+++ b/launcher/modplatform/legacy_ftb/PrivatePackManager.cpp
@@ -10,7 +10,8 @@ void PrivatePackManager::load()
{
try
{
- currentPacks = QString::fromUtf8(FS::read(m_filename)).split('\n', QString::SkipEmptyParts).toSet();
+ auto parts = QString::fromUtf8(FS::read(m_filename)).split('\n', Qt::SkipEmptyParts);
+ currentPacks = QSet<QString>(parts.begin(), parts.end());
dirty = false;
}
catch(...)
@@ -28,7 +29,7 @@ void PrivatePackManager::save() const
}
try
{
- QStringList list = currentPacks.toList();
+ QStringList list = currentPacks.values();
FS::write(m_filename, list.join('\n').toUtf8());
dirty = false;
}
diff --git a/launcher/net/Download.cpp b/launcher/net/Download.cpp
index e36ed61a65..57e3692d34 100644
--- a/launcher/net/Download.cpp
+++ b/launcher/net/Download.cpp
@@ -108,7 +108,7 @@ void Download::startImpl()
m_reply.reset(rep);
connect(rep, SIGNAL(downloadProgress(qint64, qint64)), SLOT(downloadProgress(qint64, qint64)));
connect(rep, SIGNAL(finished()), SLOT(downloadFinished()));
- connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(downloadError(QNetworkReply::NetworkError)));
+ connect(rep, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), SLOT(downloadError(QNetworkReply::NetworkError)));
connect(rep, &QNetworkReply::sslErrors, this, &Download::sslErrors);
connect(rep, &QNetworkReply::readyRead, this, &Download::downloadReadyRead);
}
diff --git a/launcher/net/HttpMetaCache.cpp b/launcher/net/HttpMetaCache.cpp
index 8734e0bfbd..7d5c98ed3c 100644
--- a/launcher/net/HttpMetaCache.cpp
+++ b/launcher/net/HttpMetaCache.cpp
@@ -96,7 +96,8 @@ MetaEntryPtr HttpMetaCache::resolveEntry(QString base, QString resource_path, QS
if (file_last_changed != entry->local_changed_timestamp)
{
QFile input(real_path);
- input.open(QIODevice::ReadOnly);
+ if (!input.open(QIODevice::ReadOnly))
+ return staleEntry(base, resource_path);
QString md5sum = QCryptographicHash::hash(input.readAll(), QCryptographicHash::Md5)
.toHex()
.constData();
diff --git a/launcher/net/NetJob.cpp b/launcher/net/NetJob.cpp
index 9bad89edd0..d1c0d371f0 100644
--- a/launcher/net/NetJob.cpp
+++ b/launcher/net/NetJob.cpp
@@ -182,10 +182,10 @@ bool NetJob::abort()
{
bool fullyAborted = true;
// fail all waiting
- m_failed.unite(m_todo.toSet());
+ m_failed.unite(QSet<int>(m_todo.begin(), m_todo.end()));
m_todo.clear();
// abort active
- auto toKill = m_doing.toList();
+ auto toKill = m_doing.values();
for(auto index: toKill)
{
auto part = downloads[index];
diff --git a/launcher/net/PasteUpload.cpp b/launcher/net/PasteUpload.cpp
index 4b69b68a1b..a18f713db1 100644
--- a/launcher/net/PasteUpload.cpp
+++ b/launcher/net/PasteUpload.cpp
@@ -47,7 +47,7 @@ void PasteUpload::executeTask()
m_reply = std::shared_ptr<QNetworkReply>(rep);
setStatus(tr("Uploading to paste.ee"));
connect(rep, &QNetworkReply::uploadProgress, this, &Task::setProgress);
- connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(downloadError(QNetworkReply::NetworkError)));
+ connect(rep, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(downloadError(QNetworkReply::NetworkError)));
connect(rep, SIGNAL(finished()), this, SLOT(downloadFinished()));
}
diff --git a/launcher/news/NewsChecker.cpp b/launcher/news/NewsChecker.cpp
index 4f4359b893..61a208ee16 100644
--- a/launcher/news/NewsChecker.cpp
+++ b/launcher/news/NewsChecker.cpp
@@ -61,7 +61,7 @@ void NewsChecker::rssDownloadFinished()
// Parse the XML.
if (!doc.setContent(newsData, false, &errorMsg, &errorLine, &errorCol))
{
- QString fullErrorMsg = QString("Error parsing RSS feed XML. %s at %d:%d.").arg(errorMsg, errorLine, errorCol);
+ QString fullErrorMsg = QString("Error parsing RSS feed XML. %1 at %2:%3.").arg(errorMsg).arg(errorLine).arg(errorCol);
fail(fullErrorMsg);
newsData.clear();
return;
diff --git a/launcher/screenshots/ImgurAlbumCreation.cpp b/launcher/screenshots/ImgurAlbumCreation.cpp
index d5de302a03..28b9421ffa 100644
--- a/launcher/screenshots/ImgurAlbumCreation.cpp
+++ b/launcher/screenshots/ImgurAlbumCreation.cpp
@@ -38,7 +38,7 @@ void ImgurAlbumCreation::startImpl()
m_reply.reset(rep);
connect(rep, &QNetworkReply::uploadProgress, this, &ImgurAlbumCreation::downloadProgress);
connect(rep, &QNetworkReply::finished, this, &ImgurAlbumCreation::downloadFinished);
- connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(downloadError(QNetworkReply::NetworkError)));
+ connect(rep, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), SLOT(downloadError(QNetworkReply::NetworkError)));
}
void ImgurAlbumCreation::downloadError(QNetworkReply::NetworkError error)
{
diff --git a/launcher/screenshots/ImgurUpload.cpp b/launcher/screenshots/ImgurUpload.cpp
index 76a84947bf..63b53dc672 100644
--- a/launcher/screenshots/ImgurUpload.cpp
+++ b/launcher/screenshots/ImgurUpload.cpp
@@ -52,7 +52,7 @@ void ImgurUpload::startImpl()
m_reply.reset(rep);
connect(rep, &QNetworkReply::uploadProgress, this, &ImgurUpload::downloadProgress);
connect(rep, &QNetworkReply::finished, this, &ImgurUpload::downloadFinished);
- connect(rep, SIGNAL(error(QNetworkReply::NetworkError)),
+ connect(rep, SIGNAL(errorOccurred(QNetworkReply::NetworkError)),
SLOT(downloadError(QNetworkReply::NetworkError)));
}
void ImgurUpload::downloadError(QNetworkReply::NetworkError error)
diff --git a/launcher/settings/INIFile.cpp b/launcher/settings/INIFile.cpp
index 6a3c801d6f..be37906794 100644
--- a/launcher/settings/INIFile.cpp
+++ b/launcher/settings/INIFile.cpp
@@ -29,10 +29,10 @@ INIFile::INIFile()
QString INIFile::unescape(QString orig)
{
QString out;
- QChar prev = 0;
+ QChar prev = QChar();
for(auto c: orig)
{
- if(prev == '\\')
+ if(prev == QLatin1Char('\\'))
{
if(c == 'n')
out += '\n';
@@ -42,7 +42,7 @@ QString INIFile::unescape(QString orig)
out += '#';
else
out += c;
- prev = 0;
+ prev = QChar();
}
else
{
@@ -52,7 +52,7 @@ QString INIFile::unescape(QString orig)
continue;
}
out += c;
- prev = 0;
+ prev = QChar();
}
}
return out;
@@ -117,7 +117,7 @@ bool INIFile::loadFile(QString fileName)
bool INIFile::loadFile(QByteArray file)
{
QTextStream in(file);
- in.setCodec("UTF-8");
+ // Qt6 uses UTF-8 by default
QStringList lines = in.readAll().split('\n');
for (int i = 0; i < lines.count(); i++)
diff --git a/launcher/translations/TranslationsModel.cpp b/launcher/translations/TranslationsModel.cpp
index 5e01031526..f0b0c0f550 100644
--- a/launcher/translations/TranslationsModel.cpp
+++ b/launcher/translations/TranslationsModel.cpp
@@ -17,7 +17,7 @@
#include "Application.h"
-const static QLatin1Literal defaultLangCode("en_US");
+const static QLatin1String defaultLangCode("en_US");
enum class FileType
{
@@ -314,7 +314,7 @@ void TranslationsModel::reloadLocalFiles()
{
return;
}
- beginInsertRows(QModelIndex(), 0, d->m_languages.size() + languages.size() - 1);
+ beginResetModel();
for(auto & language: languages)
{
d->m_languages.append(language);
@@ -322,7 +322,7 @@ void TranslationsModel::reloadLocalFiles()
std::sort(d->m_languages.begin(), d->m_languages.end(), [](const Language& a, const Language& b) {
return a.key.compare(b.key) < 0;
});
- endInsertRows();
+ endResetModel();
}
namespace {
@@ -359,7 +359,7 @@ QVariant TranslationsModel::data(const QModelIndex& index, int role) const
case Column::Completeness:
{
QString text;
- text.sprintf("%3.1f %%", lang.percentTranslated());
+ text = QString::asprintf("%3.1f %%", lang.percentTranslated());
return text;
}
}
@@ -431,7 +431,7 @@ Language * TranslationsModel::findLanguage(const QString& key)
}
else
{
- return found;
+ return &(*found);
}
}
@@ -556,7 +556,7 @@ QModelIndex TranslationsModel::selectedIndex()
if(found)
{
// QVector iterator freely converts to pointer to contained type
- return index(found - d->m_languages.begin(), 0, QModelIndex());
+ return index(found - d->m_languages.data(), 0, QModelIndex());
}
return QModelIndex();
}
diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp
index f831622d02..3ce7535a7d 100644
--- a/launcher/ui/MainWindow.cpp
+++ b/launcher/ui/MainWindow.cpp
@@ -642,6 +642,12 @@ public:
retranslateUi(MainWindow);
QMetaObject::connectSlotsByName(MainWindow);
+
+ // Explicit connections for actions that connectSlotsByName can't auto-connect in Qt6
+ auto mainWin = qobject_cast<class MainWindow*>(MainWindow);
+ QObject::connect(actionREDDIT.operator->(), &QAction::triggered, mainWin, &MainWindow::on_actionREDDIT_triggered);
+ QObject::connect(actionDISCORD.operator->(), &QAction::triggered, mainWin, &MainWindow::on_actionDISCORD_triggered);
+ QObject::connect(actionReportBug.operator->(), &QAction::triggered, mainWin, &MainWindow::on_actionReportBug_triggered);
} // setupUi
void retranslateUi(QMainWindow *MainWindow)
@@ -1240,7 +1246,7 @@ void MainWindow::updateNotAvailable()
QList<int> stringToIntList(const QString &string)
{
- QStringList split = string.split(',', QString::SkipEmptyParts);
+ QStringList split = string.split(',', Qt::SkipEmptyParts);
QList<int> out;
for (int i = 0; i < split.size(); ++i)
{
diff --git a/launcher/ui/dialogs/AboutDialog.cpp b/launcher/ui/dialogs/AboutDialog.cpp
index f5fa5735f7..38356514d3 100644
--- a/launcher/ui/dialogs/AboutDialog.cpp
+++ b/launcher/ui/dialogs/AboutDialog.cpp
@@ -31,7 +31,6 @@ QString getCreditsHtml(QStringList patrons)
QString patronsHeading = QObject::tr("Patrons", "About Credits");
QString output;
QTextStream stream(&output);
- stream.setCodec(QTextCodec::codecForName("UTF-8"));
stream << "<center>\n";
// TODO: possibly retrieve from git history at build time?
stream << "<h2> MeshMC Developers </h2>\n";
@@ -55,7 +54,10 @@ QString getLicenseHtml()
{
HoeDown hoedown;
QFile dataFile(":/documents/COPYING.md");
- dataFile.open(QIODevice::ReadOnly);
+ if (!dataFile.open(QIODevice::ReadOnly))
+ {
+ return QString();
+ }
QString output = hoedown.process(dataFile.readAll());
return output;
}
@@ -94,15 +96,6 @@ AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent), ui(new Ui::AboutDia
else
ui->channelLabel->setVisible(false);
- ui->redistributionText->setHtml(tr(
-"<p>We keep MeshMC open source because we think it's important to be able to see the source code for a project like this, and we do so using the Apache license.</p>\n"
-"<p>Part of the reason for using the Apache license is we don't want people using the &quot;MeshMC&quot; name when redistributing the project. "
-"This means people must take the time to go through the source code and remove all references to &quot;MeshMC&quot;, including but not limited to the project "
-"icon and the title of windows, (no <b>MeshMC-fork</b> in the title).</p>\n"
-"<p>The Apache license covers reasonable use for the name - a mention of the project's origins in the About dialog and the license is acceptable. "
-"However, it should be abundantly clear that the project is a fork <b>without</b> implying that you have our blessing.</p>"
- ));
-
QString urlText("<html><head/><body><p><a href=\"%1\">%1</a></p></body></html>");
ui->urlLabel->setText(urlText.arg(BuildConfig.LAUNCHER_GIT));
diff --git a/launcher/ui/dialogs/AboutDialog.ui b/launcher/ui/dialogs/AboutDialog.ui
index 06f0b26ddf..341137f6d3 100644
--- a/launcher/ui/dialogs/AboutDialog.ui
+++ b/launcher/ui/dialogs/AboutDialog.ui
@@ -251,20 +251,6 @@
</item>
</layout>
</widget>
- <widget class="QWidget" name="forkingTab">
- <attribute name="title">
- <string>Forking/Redistribution</string>
- </attribute>
- <layout class="QVBoxLayout" name="verticalLayout_4">
- <item>
- <widget class="QTextEdit" name="redistributionText">
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
</widget>
</item>
<item>
@@ -307,7 +293,6 @@
<tabstop>tabWidget</tabstop>
<tabstop>creditsText</tabstop>
<tabstop>licenseText</tabstop>
- <tabstop>redistributionText</tabstop>
<tabstop>aboutQt</tabstop>
<tabstop>closeButton</tabstop>
</tabstops>
diff --git a/launcher/ui/dialogs/CopyInstanceDialog.cpp b/launcher/ui/dialogs/CopyInstanceDialog.cpp
index e5113981cd..a79b0a11cd 100644
--- a/launcher/ui/dialogs/CopyInstanceDialog.cpp
+++ b/launcher/ui/dialogs/CopyInstanceDialog.cpp
@@ -39,8 +39,8 @@ CopyInstanceDialog::CopyInstanceDialog(InstancePtr original, QWidget *parent)
ui->iconButton->setIcon(APPLICATION->icons()->getIcon(InstIconKey));
ui->instNameTextBox->setText(original->name());
ui->instNameTextBox->setFocus();
- auto groups = APPLICATION->instances()->getGroups().toSet();
- auto groupList = QStringList(groups.toList());
+ auto groupList = APPLICATION->instances()->getGroups();
+ groupList.removeDuplicates();
groupList.sort(Qt::CaseInsensitive);
groupList.removeOne("");
groupList.push_front("");
diff --git a/launcher/ui/dialogs/ExportInstanceDialog.cpp b/launcher/ui/dialogs/ExportInstanceDialog.cpp
index 1a16487517..eebe310319 100644
--- a/launcher/ui/dialogs/ExportInstanceDialog.cpp
+++ b/launcher/ui/dialogs/ExportInstanceDialog.cpp
@@ -97,7 +97,7 @@ public:
flags |= Qt::ItemIsUserCheckable;
if (sourceIndex.model()->hasChildren(sourceIndex))
{
- flags |= Qt::ItemIsTristate;
+ flags |= Qt::ItemIsAutoTristate;
}
}
@@ -190,7 +190,7 @@ public:
QStack<QModelIndex> todo;
while (1)
{
- auto node = doing.child(row, 0);
+ auto node = fsm->index(row, 0, doing);
if (!node.isValid())
{
if (!todo.size())
@@ -239,7 +239,7 @@ public:
QStack<QModelIndex> todo;
while (1)
{
- auto node = doing.child(row, 0);
+ auto node = doing.model()->index(row, 0, doing);
if (!node.isValid())
{
if (!todo.size())
@@ -403,7 +403,7 @@ bool ExportInstanceDialog::doExport()
auto & blocked = proxyModel->blockedPaths();
using std::placeholders::_1;
- if (!JlCompress::compressDir(output, m_instance->instanceRoot(), name, std::bind(&SeparatorPrefixTree<'/'>::covers, blocked, _1)))
+ if (!MMCZip::compressDir(output, m_instance->instanceRoot(), std::bind(&SeparatorPrefixTree<'/'>::covers, blocked, _1)))
{
QMessageBox::warning(this, tr("Error"), tr("Unable to export instance"));
return false;
@@ -434,7 +434,7 @@ void ExportInstanceDialog::rowsInserted(QModelIndex parent, int top, int bottom)
//WARNING: possible off-by-one?
for(int i = top; i < bottom; i++)
{
- auto node = parent.child(i, 0);
+ auto node = parent.model()->index(i, 0, parent);
if(proxyModel->shouldExpand(node))
{
auto expNode = node.parent();
@@ -462,7 +462,7 @@ void ExportInstanceDialog::loadPackIgnore()
}
auto data = ignoreFile.readAll();
auto string = QString::fromUtf8(data);
- proxyModel->setBlockedPaths(string.split('\n', QString::SkipEmptyParts));
+ proxyModel->setBlockedPaths(string.split('\n', Qt::SkipEmptyParts));
}
void ExportInstanceDialog::savePackIgnore()
diff --git a/launcher/ui/dialogs/LoginDialog.cpp b/launcher/ui/dialogs/LoginDialog.cpp
deleted file mode 100644
index 194315a7c3..0000000000
--- a/launcher/ui/dialogs/LoginDialog.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-/* 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 "LoginDialog.h"
-#include "ui_LoginDialog.h"
-
-#include "minecraft/auth/AccountTask.h"
-
-#include <QtWidgets/QPushButton>
-
-LoginDialog::LoginDialog(QWidget *parent) : QDialog(parent), ui(new Ui::LoginDialog)
-{
- ui->setupUi(this);
- ui->progressBar->setVisible(false);
- ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
-
- connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
- connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
-}
-
-LoginDialog::~LoginDialog()
-{
- delete ui;
-}
-
-// Stage 1: User interaction
-void LoginDialog::accept()
-{
- setUserInputsEnabled(false);
- ui->progressBar->setVisible(true);
-
- // Setup the login task and start it
- m_account = MinecraftAccount::createFromUsername(ui->userTextBox->text());
- m_loginTask = m_account->login(ui->passTextBox->text());
- connect(m_loginTask.get(), &Task::failed, this, &LoginDialog::onTaskFailed);
- connect(m_loginTask.get(), &Task::succeeded, this, &LoginDialog::onTaskSucceeded);
- connect(m_loginTask.get(), &Task::status, this, &LoginDialog::onTaskStatus);
- connect(m_loginTask.get(), &Task::progress, this, &LoginDialog::onTaskProgress);
- m_loginTask->start();
-}
-
-void LoginDialog::setUserInputsEnabled(bool enable)
-{
- ui->userTextBox->setEnabled(enable);
- ui->passTextBox->setEnabled(enable);
- ui->buttonBox->setEnabled(enable);
-}
-
-// Enable the OK button only when both textboxes contain something.
-void LoginDialog::on_userTextBox_textEdited(const QString &newText)
-{
- ui->buttonBox->button(QDialogButtonBox::Ok)
- ->setEnabled(!newText.isEmpty() && !ui->passTextBox->text().isEmpty());
-}
-void LoginDialog::on_passTextBox_textEdited(const QString &newText)
-{
- ui->buttonBox->button(QDialogButtonBox::Ok)
- ->setEnabled(!newText.isEmpty() && !ui->userTextBox->text().isEmpty());
-}
-
-void LoginDialog::onTaskFailed(const QString &reason)
-{
- // Set message
- auto lines = reason.split('\n');
- QString processed;
- for(auto line: lines) {
- if(line.size()) {
- processed += "<font color='red'>" + line + "</font><br />";
- }
- else {
- processed += "<br />";
- }
- }
- ui->label->setText(processed);
-
- // Re-enable user-interaction
- setUserInputsEnabled(true);
- ui->progressBar->setVisible(false);
-}
-
-void LoginDialog::onTaskSucceeded()
-{
- QDialog::accept();
-}
-
-void LoginDialog::onTaskStatus(const QString &status)
-{
- ui->label->setText(status);
-}
-
-void LoginDialog::onTaskProgress(qint64 current, qint64 total)
-{
- ui->progressBar->setMaximum(total);
- ui->progressBar->setValue(current);
-}
-
-// Public interface
-MinecraftAccountPtr LoginDialog::newAccount(QWidget *parent, QString msg)
-{
- LoginDialog dlg(parent);
- dlg.ui->label->setText(msg);
- if (dlg.exec() == QDialog::Accepted)
- {
- return dlg.m_account;
- }
- return 0;
-}
diff --git a/launcher/ui/dialogs/LoginDialog.h b/launcher/ui/dialogs/LoginDialog.h
deleted file mode 100644
index f8101ff572..0000000000
--- a/launcher/ui/dialogs/LoginDialog.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* 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 <QtWidgets/QDialog>
-#include <QtCore/QEventLoop>
-
-#include "minecraft/auth/MinecraftAccount.h"
-#include "tasks/Task.h"
-
-namespace Ui
-{
-class LoginDialog;
-}
-
-class LoginDialog : public QDialog
-{
- Q_OBJECT
-
-public:
- ~LoginDialog();
-
- static MinecraftAccountPtr newAccount(QWidget *parent, QString message);
-
-private:
- explicit LoginDialog(QWidget *parent = 0);
-
- void setUserInputsEnabled(bool enable);
-
-protected
-slots:
- void accept();
-
- void onTaskFailed(const QString &reason);
- void onTaskSucceeded();
- void onTaskStatus(const QString &status);
- void onTaskProgress(qint64 current, qint64 total);
-
- void on_userTextBox_textEdited(const QString &newText);
- void on_passTextBox_textEdited(const QString &newText);
-
-private:
- Ui::LoginDialog *ui;
- MinecraftAccountPtr m_account;
- Task::Ptr m_loginTask;
-};
diff --git a/launcher/ui/dialogs/LoginDialog.ui b/launcher/ui/dialogs/LoginDialog.ui
deleted file mode 100644
index 8fa4a45d25..0000000000
--- a/launcher/ui/dialogs/LoginDialog.ui
+++ /dev/null
@@ -1,77 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>LoginDialog</class>
- <widget class="QDialog" name="LoginDialog">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>421</width>
- <height>198</height>
- </rect>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="windowTitle">
- <string>Add Account</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <widget class="QLabel" name="label">
- <property name="text">
- <string notr="true">Message label placeholder.</string>
- </property>
- <property name="textFormat">
- <enum>Qt::RichText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLineEdit" name="userTextBox">
- <property name="placeholderText">
- <string>Email</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLineEdit" name="passTextBox">
- <property name="echoMode">
- <enum>QLineEdit::Password</enum>
- </property>
- <property name="placeholderText">
- <string>Password</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QProgressBar" name="progressBar">
- <property name="value">
- <number>24</number>
- </property>
- <property name="textVisible">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QDialogButtonBox" name="buttonBox">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="standardButtons">
- <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/launcher/ui/dialogs/MSALoginDialog.cpp b/launcher/ui/dialogs/MSALoginDialog.cpp
index f46aa3b9a2..71c243b351 100644
--- a/launcher/ui/dialogs/MSALoginDialog.cpp
+++ b/launcher/ui/dialogs/MSALoginDialog.cpp
@@ -25,7 +25,6 @@ MSALoginDialog::MSALoginDialog(QWidget *parent) : QDialog(parent), ui(new Ui::MS
{
ui->setupUi(this);
ui->progressBar->setVisible(false);
- // ui->buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false);
connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
@@ -34,6 +33,8 @@ MSALoginDialog::MSALoginDialog(QWidget *parent) : QDialog(parent), ui(new Ui::MS
int MSALoginDialog::exec() {
setUserInputsEnabled(false);
ui->progressBar->setVisible(true);
+ ui->progressBar->setMaximum(0); // Indeterminate progress
+ ui->label->setText(tr("Opening your browser for Microsoft login..."));
// Setup the login task and start it
m_account = MinecraftAccount::createBlankMSA();
@@ -42,9 +43,7 @@ int MSALoginDialog::exec() {
connect(m_loginTask.get(), &Task::succeeded, this, &MSALoginDialog::onTaskSucceeded);
connect(m_loginTask.get(), &Task::status, this, &MSALoginDialog::onTaskStatus);
connect(m_loginTask.get(), &Task::progress, this, &MSALoginDialog::onTaskProgress);
- connect(m_loginTask.get(), &AccountTask::showVerificationUriAndCode, this, &MSALoginDialog::showVerificationUriAndCode);
- connect(m_loginTask.get(), &AccountTask::hideVerificationUriAndCode, this, &MSALoginDialog::hideVerificationUriAndCode);
- connect(&m_externalLoginTimer, &QTimer::timeout, this, &MSALoginDialog::externalLoginTick);
+ connect(m_loginTask.get(), &AccountTask::authorizeWithBrowser, this, &MSALoginDialog::onAuthorizeWithBrowser);
m_loginTask->start();
return QDialog::exec();
@@ -56,35 +55,13 @@ MSALoginDialog::~MSALoginDialog()
delete ui;
}
-void MSALoginDialog::externalLoginTick() {
- m_externalLoginElapsed++;
- ui->progressBar->setValue(m_externalLoginElapsed);
- ui->progressBar->repaint();
-
- if(m_externalLoginElapsed >= m_externalLoginTimeout) {
- m_externalLoginTimer.stop();
- }
-}
-
-
-void MSALoginDialog::showVerificationUriAndCode(const QUrl& uri, const QString& code, int expiresIn) {
- m_externalLoginElapsed = 0;
- m_externalLoginTimeout = expiresIn;
-
- m_externalLoginTimer.setInterval(1000);
- m_externalLoginTimer.setSingleShot(false);
- m_externalLoginTimer.start();
-
- ui->progressBar->setMaximum(expiresIn);
- ui->progressBar->setValue(m_externalLoginElapsed);
-
- QString urlString = uri.toString();
- QString linkString = QString("<a href=\"%1\">%2</a>").arg(urlString, urlString);
- ui->label->setText(tr("<p>Please open up %1 in a browser and put in the code <b>%2</b> to proceed with login.</p>").arg(linkString, code));
-}
-
-void MSALoginDialog::hideVerificationUriAndCode() {
- m_externalLoginTimer.stop();
+void MSALoginDialog::onAuthorizeWithBrowser(const QUrl& url) {
+ QString urlString = url.toString();
+ QString linkString = QString("<a href=\"%1\">%2</a>").arg(urlString, tr("here"));
+ ui->label->setText(
+ tr("<p>A browser window will open for Microsoft login.</p>"
+ "<p>If it doesn't open automatically, click %1.</p>").arg(linkString)
+ );
}
void MSALoginDialog::setUserInputsEnabled(bool enable)
@@ -137,5 +114,5 @@ MinecraftAccountPtr MSALoginDialog::newAccount(QWidget *parent, QString msg)
{
return dlg.m_account;
}
- return 0;
+ return nullptr;
}
diff --git a/launcher/ui/dialogs/MSALoginDialog.h b/launcher/ui/dialogs/MSALoginDialog.h
index 4cf146ab3f..e4524cad6f 100644
--- a/launcher/ui/dialogs/MSALoginDialog.h
+++ b/launcher/ui/dialogs/MSALoginDialog.h
@@ -17,7 +17,6 @@
#include <QtWidgets/QDialog>
#include <QtCore/QEventLoop>
-#include <QTimer>
#include "minecraft/auth/MinecraftAccount.h"
@@ -47,17 +46,11 @@ slots:
void onTaskSucceeded();
void onTaskStatus(const QString &status);
void onTaskProgress(qint64 current, qint64 total);
- void showVerificationUriAndCode(const QUrl &uri, const QString &code, int expiresIn);
- void hideVerificationUriAndCode();
-
- void externalLoginTick();
+ void onAuthorizeWithBrowser(const QUrl &url);
private:
Ui::MSALoginDialog *ui;
MinecraftAccountPtr m_account;
shared_qobject_ptr<AccountTask> m_loginTask;
- QTimer m_externalLoginTimer;
- int m_externalLoginElapsed = 0;
- int m_externalLoginTimeout = 0;
};
diff --git a/launcher/ui/dialogs/NewComponentDialog.cpp b/launcher/ui/dialogs/NewComponentDialog.cpp
index bcb68cdaf7..e7995bcc4f 100644
--- a/launcher/ui/dialogs/NewComponentDialog.cpp
+++ b/launcher/ui/dialogs/NewComponentDialog.cpp
@@ -46,7 +46,8 @@ NewComponentDialog::NewComponentDialog(const QString & initialName, const QStrin
connect(ui->nameTextBox, &QLineEdit::textChanged, this, &NewComponentDialog::updateDialogState);
connect(ui->uidTextBox, &QLineEdit::textChanged, this, &NewComponentDialog::updateDialogState);
- auto groups = APPLICATION->instances()->getGroups().toSet();
+ auto groups = APPLICATION->instances()->getGroups();
+ groups.removeDuplicates();
ui->nameTextBox->setFocus();
originalPlaceholderText = ui->uidTextBox->placeholderText();
diff --git a/launcher/ui/dialogs/NewInstanceDialog.cpp b/launcher/ui/dialogs/NewInstanceDialog.cpp
index b402839cf3..d4cc9b8c65 100644
--- a/launcher/ui/dialogs/NewInstanceDialog.cpp
+++ b/launcher/ui/dialogs/NewInstanceDialog.cpp
@@ -53,8 +53,8 @@ NewInstanceDialog::NewInstanceDialog(const QString & initialGroup, const QString
InstIconKey = "default";
ui->iconButton->setIcon(APPLICATION->icons()->getIcon(InstIconKey));
- auto groups = APPLICATION->instances()->getGroups().toSet();
- auto groupList = QStringList(groups.toList());
+ auto groupList = APPLICATION->instances()->getGroups();
+ groupList.removeDuplicates();
groupList.sort(Qt::CaseInsensitive);
groupList.removeOne("");
groupList.push_front(initialGroup);
diff --git a/launcher/ui/dialogs/ProfileSetupDialog.cpp b/launcher/ui/dialogs/ProfileSetupDialog.cpp
index 76b6af4981..a534744546 100644
--- a/launcher/ui/dialogs/ProfileSetupDialog.cpp
+++ b/launcher/ui/dialogs/ProfileSetupDialog.cpp
@@ -18,7 +18,7 @@
#include <QPushButton>
#include <QAction>
-#include <QRegExpValidator>
+#include <QRegularExpressionValidator>
#include <QJsonDocument>
#include <QDebug>
@@ -39,9 +39,9 @@ ProfileSetupDialog::ProfileSetupDialog(MinecraftAccountPtr accountToSetup, QWidg
yellowIcon = APPLICATION->getThemedIcon("status-yellow");
badIcon = APPLICATION->getThemedIcon("status-bad");
- QRegExp permittedNames("[a-zA-Z0-9_]{3,16}");
+ QRegularExpression permittedNames("[a-zA-Z0-9_]{3,16}");
auto nameEdit = ui->nameEdit;
- nameEdit->setValidator(new QRegExpValidator(permittedNames));
+ nameEdit->setValidator(new QRegularExpressionValidator(permittedNames));
nameEdit->setClearButtonEnabled(true);
validityAction = nameEdit->addAction(yellowIcon, QLineEdit::LeadingPosition);
connect(nameEdit, &QLineEdit::textEdited, this, &ProfileSetupDialog::nameEdited);
diff --git a/launcher/ui/dialogs/SkinUploadDialog.cpp b/launcher/ui/dialogs/SkinUploadDialog.cpp
index 6a5a324f50..ef2ae432e5 100644
--- a/launcher/ui/dialogs/SkinUploadDialog.cpp
+++ b/launcher/ui/dialogs/SkinUploadDialog.cpp
@@ -1,6 +1,7 @@
#include <QFileInfo>
#include <QFileDialog>
#include <QPainter>
+#include <QRegularExpression>
#include <FileSystem.h>
@@ -22,10 +23,10 @@ void SkinUploadDialog::on_buttonBox_accepted()
{
QString fileName;
QString input = ui->skinPathTextBox->text();
- QRegExp urlPrefixMatcher("^([a-z]+)://.+$");
+ QRegularExpression urlPrefixMatcher("^([a-z]+)://.+$");
bool isLocalFile = false;
// it has an URL prefix -> it is an URL
- if(urlPrefixMatcher.exactMatch(input))
+ if(urlPrefixMatcher.match(input).hasMatch())
{
QUrl fileURL = input;
if(fileURL.isValid())
diff --git a/launcher/ui/dialogs/UpdateDialog.cpp b/launcher/ui/dialogs/UpdateDialog.cpp
index c352e0935b..502bba0652 100644
--- a/launcher/ui/dialogs/UpdateDialog.cpp
+++ b/launcher/ui/dialogs/UpdateDialog.cpp
@@ -1,6 +1,7 @@
#include "UpdateDialog.h"
#include "ui_UpdateDialog.h"
#include <QDebug>
+#include <QRegularExpression>
#include "Application.h"
#include <settings/SettingsObject.h>
#include <Json.h>
@@ -58,7 +59,7 @@ QString reprocessMarkdown(QByteArray markdown)
QString output = hoedown.process(markdown);
// HACK: easier than customizing hoedown
- output.replace(QRegExp("GH-([0-9]+)"), "<a href=\"https://github.com/Project-Tick/MeshMC/issues/\\1\">GH-\\1</a>");
+ output.replace(QRegularExpression("GH-([0-9]+)"), "<a href=\"https://github.com/Project-Tick/MeshMC/issues/\\1\">GH-\\1</a>");
qDebug() << output;
return output;
}
diff --git a/launcher/ui/instanceview/InstanceDelegate.cpp b/launcher/ui/instanceview/InstanceDelegate.cpp
index 3c4ca63f23..063ce70504 100644
--- a/launcher/ui/instanceview/InstanceDelegate.cpp
+++ b/launcher/ui/instanceview/InstanceDelegate.cpp
@@ -61,7 +61,7 @@ void drawSelectionRect(QPainter *painter, const QStyleOptionViewItem &option,
painter->fillRect(rect, option.palette.brush(QPalette::Highlight));
else
{
- QColor backgroundColor = option.palette.color(QPalette::Background);
+ QColor backgroundColor = option.palette.color(QPalette::Window);
backgroundColor.setAlpha(160);
painter->fillRect(rect, QBrush(backgroundColor));
}
diff --git a/launcher/ui/instanceview/InstanceView.cpp b/launcher/ui/instanceview/InstanceView.cpp
index 25aec1abe9..89d4e7e544 100644
--- a/launcher/ui/instanceview/InstanceView.cpp
+++ b/launcher/ui/instanceview/InstanceView.cpp
@@ -794,7 +794,7 @@ QPair<VisualGroup *, VisualGroup::HitResults> InstanceView::rowDropPos(const QPo
{
VisualGroup::HitResults hitresult;
auto group = categoryAt(pos + offset(), hitresult);
- return qMakePair<VisualGroup*, int>(group, hitresult);
+ return qMakePair(group, hitresult);
}
QPoint InstanceView::offset() const
diff --git a/launcher/ui/instanceview/InstanceView.h b/launcher/ui/instanceview/InstanceView.h
index 406362e628..f3ba26b778 100644
--- a/launcher/ui/instanceview/InstanceView.h
+++ b/launcher/ui/instanceview/InstanceView.h
@@ -40,6 +40,12 @@ public:
InstanceView(QWidget *parent = 0);
~InstanceView();
+ QStyleOptionViewItem viewOptions() const {
+ QStyleOptionViewItem option;
+ initViewItemOption(&option);
+ return option;
+ }
+
void setModel(QAbstractItemModel *model) override;
using visibilityFunction = std::function<bool(const QString &)>;
diff --git a/launcher/ui/pages/global/AccountListPage.cpp b/launcher/ui/pages/global/AccountListPage.cpp
index c0386ea6e7..4ab57319b1 100644
--- a/launcher/ui/pages/global/AccountListPage.cpp
+++ b/launcher/ui/pages/global/AccountListPage.cpp
@@ -24,7 +24,6 @@
#include "net/NetJob.h"
#include "ui/dialogs/ProgressDialog.h"
-#include "ui/dialogs/LoginDialog.h"
#include "ui/dialogs/MSALoginDialog.h"
#include "ui/dialogs/CustomMessageBox.h"
#include "ui/dialogs/SkinUploadDialog.h"
@@ -43,7 +42,7 @@ AccountListPage::AccountListPage(QWidget *parent)
ui->setupUi(this);
ui->listView->setEmptyString(tr(
"Welcome!\n"
- "If you're new here, you can click the \"Add\" button to add your Mojang or Minecraft account."
+ "If you're new here, you can click the \"Add Microsoft\" button to add your Microsoft account."
));
ui->listView->setEmptyMode(VersionListView::String);
ui->listView->setContextMenuPolicy(Qt::CustomContextMenu);
@@ -51,12 +50,10 @@ AccountListPage::AccountListPage(QWidget *parent)
m_accounts = APPLICATION->accounts();
ui->listView->setModel(m_accounts.get());
+ // Expand the account column
ui->listView->header()->setSectionResizeMode(0, QHeaderView::Stretch);
ui->listView->header()->setSectionResizeMode(1, QHeaderView::Stretch);
ui->listView->header()->setSectionResizeMode(2, QHeaderView::ResizeToContents);
- ui->listView->setSelectionMode(QAbstractItemView::SingleSelection);
-
- // Expand the account column
QItemSelectionModel *selectionModel = ui->listView->selectionModel();
@@ -109,22 +106,6 @@ void AccountListPage::listChanged()
updateButtonStates();
}
-void AccountListPage::on_actionAddMojang_triggered()
-{
- MinecraftAccountPtr account = LoginDialog::newAccount(
- this,
- tr("Please enter your Mojang account email and password to add your account.")
- );
-
- if (account)
- {
- m_accounts->addAccount(account);
- if (m_accounts->count() == 1) {
- m_accounts->setDefaultAccount(account);
- }
- }
-}
-
void AccountListPage::on_actionAddMicrosoft_triggered()
{
if(BuildConfig.BUILD_PLATFORM == "osx64") {
@@ -141,7 +122,7 @@ void AccountListPage::on_actionAddMicrosoft_triggered()
}
MinecraftAccountPtr account = MSALoginDialog::newAccount(
this,
- tr("Please enter your Mojang account email and password to add your account.")
+ tr("Log in with your Microsoft account to add it.")
);
if (account)
diff --git a/launcher/ui/pages/global/AccountListPage.h b/launcher/ui/pages/global/AccountListPage.h
index 1c65e70814..83105604a3 100644
--- a/launcher/ui/pages/global/AccountListPage.h
+++ b/launcher/ui/pages/global/AccountListPage.h
@@ -60,7 +60,6 @@ public:
}
public slots:
- void on_actionAddMojang_triggered();
void on_actionAddMicrosoft_triggered();
void on_actionRemove_triggered();
void on_actionRefresh_triggered();
diff --git a/launcher/ui/pages/global/AccountListPage.ui b/launcher/ui/pages/global/AccountListPage.ui
index 29738c0237..96d0dc7518 100644
--- a/launcher/ui/pages/global/AccountListPage.ui
+++ b/launcher/ui/pages/global/AccountListPage.ui
@@ -53,7 +53,6 @@
<bool>false</bool>
</attribute>
<addaction name="actionAddMicrosoft"/>
- <addaction name="actionAddMojang"/>
<addaction name="actionRefresh"/>
<addaction name="actionRemove"/>
<addaction name="actionSetDefault"/>
@@ -62,11 +61,6 @@
<addaction name="actionUploadSkin"/>
<addaction name="actionDeleteSkin"/>
</widget>
- <action name="actionAddMojang">
- <property name="text">
- <string>Add Mojang</string>
- </property>
- </action>
<action name="actionRemove">
<property name="text">
<string>Remove</string>
diff --git a/launcher/ui/pages/global/ProxyPage.cpp b/launcher/ui/pages/global/ProxyPage.cpp
index 5bc8199eea..75323d0437 100644
--- a/launcher/ui/pages/global/ProxyPage.cpp
+++ b/launcher/ui/pages/global/ProxyPage.cpp
@@ -29,7 +29,7 @@ ProxyPage::ProxyPage(QWidget *parent) : QWidget(parent), ui(new Ui::ProxyPage)
loadSettings();
updateCheckboxStuff();
- connect(ui->proxyGroup, SIGNAL(buttonClicked(int)), SLOT(proxyChanged(int)));
+ connect(ui->proxyGroup, &QButtonGroup::idClicked, this, &ProxyPage::proxyChanged);
}
ProxyPage::~ProxyPage()
diff --git a/launcher/ui/pages/instance/LogPage.cpp b/launcher/ui/pages/instance/LogPage.cpp
index b66c6cc7b5..55b5fbbca0 100644
--- a/launcher/ui/pages/instance/LogPage.cpp
+++ b/launcher/ui/pages/instance/LogPage.cpp
@@ -27,7 +27,7 @@ public:
{
case Qt::FontRole:
return m_font;
- case Qt::TextColorRole:
+ case Qt::ForegroundRole:
{
MessageLevel::Enum level = (MessageLevel::Enum) QIdentityProxyModel::data(index, LogModel::LevelRole).toInt();
return m_colors->getFront(level);
diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp
index e63b1434eb..4ceba14556 100644
--- a/launcher/ui/pages/instance/ModFolderPage.cpp
+++ b/launcher/ui/pages/instance/ModFolderPage.cpp
@@ -60,14 +60,14 @@ protected:
return false;
}
const auto &mod = model->at(source_row);
- if(mod.name().contains(filterRegExp())) {
+ if(mod.name().contains(filterRegularExpression())) {
return true;
}
- if(mod.description().contains(filterRegExp())) {
+ if(mod.description().contains(filterRegularExpression())) {
return true;
}
for(auto & author: mod.authors()) {
- if (author.contains(filterRegExp())) {
+ if (author.contains(filterRegularExpression())) {
return true;
}
}
diff --git a/launcher/ui/pages/instance/ScreenshotsPage.cpp b/launcher/ui/pages/instance/ScreenshotsPage.cpp
index f568ef0d99..9a8389754e 100644
--- a/launcher/ui/pages/instance/ScreenshotsPage.cpp
+++ b/launcher/ui/pages/instance/ScreenshotsPage.cpp
@@ -9,6 +9,7 @@
#include <QFileSystemModel>
#include <QStyledItemDelegate>
#include <QLineEdit>
+#include <QRegularExpression>
#include <QEvent>
#include <QPainter>
#include <QClipboard>
@@ -118,7 +119,7 @@ public:
if (role == Qt::DisplayRole || role == Qt::EditRole)
{
QVariant result = sourceModel()->data(mapToSource(proxyIndex), role);
- return result.toString().remove(QRegExp("\\.png$"));
+ return result.toString().remove(QRegularExpression("\\.png$"));
}
if (role == Qt::DecorationRole)
{
@@ -234,7 +235,7 @@ ScreenshotsPage::ScreenshotsPage(QString path, QWidget *parent)
ui->listView->setViewMode(QListView::IconMode);
ui->listView->setResizeMode(QListView::Adjust);
ui->listView->installEventFilter(this);
- ui->listView->setEditTriggers(0);
+ ui->listView->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->listView->setItemDelegate(new CenteredEditingDelegate(this));
ui->listView->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui->listView, &QListView::customContextMenuRequested, this, &ScreenshotsPage::ShowContextMenu);
diff --git a/launcher/ui/pages/instance/ServersPage.cpp b/launcher/ui/pages/instance/ServersPage.cpp
index 8116d2bfaf..8c525a48e2 100644
--- a/launcher/ui/pages/instance/ServersPage.cpp
+++ b/launcher/ui/pages/instance/ServersPage.cpp
@@ -252,7 +252,7 @@ public:
return false;
}
beginMoveRows(QModelIndex(), row, row, QModelIndex(), row - 1);
- m_servers.swap(row-1, row);
+ m_servers.swapItemsAt(row-1, row);
endMoveRows();
scheduleSave();
return true;
@@ -270,7 +270,7 @@ public:
return false;
}
beginMoveRows(QModelIndex(), row, row, QModelIndex(), row + 2);
- m_servers.swap(row+1, row);
+ m_servers.swapItemsAt(row+1, row);
endMoveRows();
scheduleSave();
return true;
diff --git a/launcher/ui/pages/modplatform/flame/FlamePage.cpp b/launcher/ui/pages/modplatform/flame/FlamePage.cpp
index 1138a2987e..f94cc19010 100644
--- a/launcher/ui/pages/modplatform/flame/FlamePage.cpp
+++ b/launcher/ui/pages/modplatform/flame/FlamePage.cpp
@@ -106,13 +106,18 @@ void FlamePage::onSelectionChanged(QModelIndex first, QModelIndex second)
ui->packDescription->setHtml(text + current.description);
+ if(isOpened)
+ {
+ dialog->setSuggestedPack(current.name);
+ }
+
if (current.versionsLoaded == false)
{
qDebug() << "Loading flame modpack versions";
NetJob *netJob = new NetJob(QString("Flame::PackVersions(%1)").arg(current.name), APPLICATION->network());
std::shared_ptr<QByteArray> response = std::make_shared<QByteArray>();
int addonId = current.addonId;
- netJob->addNetAction(Net::Download::makeByteArray(QString("https://addons-ecs.forgesvc.net/api/v2/addon/%1/files").arg(addonId), response.get()));
+ netJob->addNetAction(Net::Download::makeByteArray(QString("https://api.curseforge.com/v1/mods/%1/files").arg(addonId), response.get()));
QObject::connect(netJob, &NetJob::succeeded, this, [this, response]
{
@@ -123,7 +128,12 @@ void FlamePage::onSelectionChanged(QModelIndex first, QModelIndex second)
qWarning() << *response;
return;
}
- QJsonArray arr = doc.array();
+ QJsonArray arr;
+ if(doc.isObject() && doc.object().contains("data")) {
+ arr = doc.object().value("data").toArray();
+ } else {
+ arr = doc.array();
+ }
try
{
Flame::loadIndexedPackVersions(current, arr);
diff --git a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp
index 9c46e887f9..fce16e35d1 100644
--- a/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp
+++ b/launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp
@@ -133,7 +133,7 @@ QVariant ListModel::data(const QModelIndex &index, int role) const
((ListModel *)this)->requestLogo(pack.logo);
return icon;
}
- else if(role == Qt::TextColorRole)
+ else if(role == Qt::ForegroundRole)
{
if(pack.broken)
{
diff --git a/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp b/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp
index 891704de8d..8d17ad2805 100644
--- a/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp
+++ b/launcher/ui/pages/modplatform/legacy_ftb/Page.cpp
@@ -116,7 +116,7 @@ void Page::openedImpl()
ftbFetchTask->fetch();
ftbPrivatePacks->load();
- ftbFetchTask->fetchPrivate(ftbPrivatePacks->getCurrentPackCodes().toList());
+ ftbFetchTask->fetchPrivate(ftbPrivatePacks->getCurrentPackCodes().values());
initialized = true;
}
suggestCurrent();
diff --git a/launcher/ui/themes/BrightTheme.cpp b/launcher/ui/themes/BrightTheme.cpp
index b9188bdd2c..7469edfcc7 100644
--- a/launcher/ui/themes/BrightTheme.cpp
+++ b/launcher/ui/themes/BrightTheme.cpp
@@ -1,5 +1,7 @@
#include "BrightTheme.h"
+#include <QObject>
+
QString BrightTheme::id()
{
return "bright";
diff --git a/launcher/ui/themes/DarkTheme.cpp b/launcher/ui/themes/DarkTheme.cpp
index 31ecd559fb..30cbb543b2 100644
--- a/launcher/ui/themes/DarkTheme.cpp
+++ b/launcher/ui/themes/DarkTheme.cpp
@@ -1,5 +1,7 @@
#include "DarkTheme.h"
+#include <QObject>
+
QString DarkTheme::id()
{
return "dark";
diff --git a/launcher/ui/widgets/LabeledToolButton.cpp b/launcher/ui/widgets/LabeledToolButton.cpp
index ab2d3278af..7d3d1e57a8 100644
--- a/launcher/ui/widgets/LabeledToolButton.cpp
+++ b/launcher/ui/widgets/LabeledToolButton.cpp
@@ -81,7 +81,7 @@ QSize LabeledToolButton::sizeHint() const
w += style()->pixelMetric(QStyle::PM_MenuButtonIndicator, &opt, this);
QSize rawSize = style()->sizeFromContents(QStyle::CT_ToolButton, &opt, QSize(w, h), this);
- QSize sizeHint = rawSize.expandedTo(QApplication::globalStrut());
+ QSize sizeHint = rawSize;
return sizeHint;
}
diff --git a/launcher/ui/widgets/LogView.cpp b/launcher/ui/widgets/LogView.cpp
index 26a2a527ef..3bb5c69afb 100644
--- a/launcher/ui/widgets/LogView.cpp
+++ b/launcher/ui/widgets/LogView.cpp
@@ -102,7 +102,7 @@ void LogView::rowsInserted(const QModelIndex& parent, int first, int last)
{
format.setFont(font.value<QFont>());
}
- auto fg = m_model->data(idx, Qt::TextColorRole);
+ auto fg = m_model->data(idx, Qt::ForegroundRole);
if(fg.isValid())
{
format.setForeground(fg.value<QColor>());
diff --git a/launcher/ui/widgets/PageContainer.cpp b/launcher/ui/widgets/PageContainer.cpp
index 9578628778..c2bc5fcb23 100644
--- a/launcher/ui/widgets/PageContainer.cpp
+++ b/launcher/ui/widgets/PageContainer.cpp
@@ -44,7 +44,7 @@ public:
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
- const QString pattern = filterRegExp().pattern();
+ const QString pattern = filterRegularExpression().pattern();
const auto model = static_cast<PageModel *>(sourceModel());
const auto page = model->pages().at(sourceRow);
if (!page->shouldDisplay())
@@ -149,7 +149,7 @@ void PageContainer::createUI()
headerHLayout->addSpacerItem(new QSpacerItem(rightMargin, 0, QSizePolicy::Fixed, QSizePolicy::Ignored));
headerHLayout->setContentsMargins(0, 6, 0, 0);
- m_pageStack->setMargin(0);
+ m_pageStack->setContentsMargins(0, 0, 0, 0);
m_pageStack->addWidget(new QWidget(this));
m_layout = new QGridLayout;
diff --git a/launcher/ui/widgets/VersionListView.cpp b/launcher/ui/widgets/VersionListView.cpp
index aba0b1a10d..6419d0377d 100644
--- a/launcher/ui/widgets/VersionListView.cpp
+++ b/launcher/ui/widgets/VersionListView.cpp
@@ -136,7 +136,7 @@ void VersionListView::paintInfoLabel(QPaintEvent *event) const
auto innerBounds = bounds;
innerBounds.adjust(10, 10, -10, -10);
- QColor background = QApplication::palette().color(QPalette::Foreground);
+ QColor background = QApplication::palette().color(QPalette::Text);
QColor foreground = QApplication::palette().color(QPalette::Base);
foreground.setAlpha(190);
painter.setFont(font);
diff --git a/libraries/LocalPeer/src/LocalPeer.cpp b/libraries/LocalPeer/src/LocalPeer.cpp
index cb218466fc..3145b418c7 100644
--- a/libraries/LocalPeer/src/LocalPeer.cpp
+++ b/libraries/LocalPeer/src/LocalPeer.cpp
@@ -62,6 +62,7 @@ static PProcessIdToSessionId pProcessIdToSessionId = 0;
#include <chrono>
#include <thread>
#include <QCryptographicHash>
+#include <QRegularExpression>
static const char* ack = "ack";
@@ -72,7 +73,7 @@ ApplicationId ApplicationId::fromTraditionalApp()
protoId = protoId.toLower();
#endif
auto prefix = protoId.section(QLatin1Char('/'), -1);
- prefix.remove(QRegExp("[^a-zA-Z]"));
+ prefix.remove(QRegularExpression("[^a-zA-Z]"));
prefix.truncate(6);
QByteArray idc = protoId.toUtf8();
quint16 idNum = qChecksum(idc.constData(), idc.size());
diff --git a/libraries/classparser/src/classparser.cpp b/libraries/classparser/src/classparser.cpp
index 8825ea399f..601521f682 100644
--- a/libraries/classparser/src/classparser.cpp
+++ b/libraries/classparser/src/classparser.cpp
@@ -18,7 +18,7 @@
#include "classparser.h"
#include <QFile>
-#include <quazipfile.h>
+#include <quazip/quazipfile.h>
#include <QDebug>
namespace classparser
diff --git a/libraries/iconfix/internal/qiconloader.cpp b/libraries/iconfix/internal/qiconloader.cpp
index 0d8466f07d..b91ddba888 100644
--- a/libraries/iconfix/internal/qiconloader.cpp
+++ b/libraries/iconfix/internal/qiconloader.cpp
@@ -42,7 +42,7 @@
#include <QtCore/QSettings>
#include <QtGui/QPainter>
#include <QApplication>
-#include <QLatin1Literal>
+#include <QString>
#include "qhexstring_p.h"
@@ -651,38 +651,25 @@ QString QIconLoaderEngineFixed::key() const
return QLatin1String("QIconLoaderEngineFixed");
}
-void QIconLoaderEngineFixed::virtual_hook(int id, void *data)
+QList<QSize> QIconLoaderEngineFixed::availableSizes(QIcon::Mode mode, QIcon::State state)
{
ensureLoaded();
- switch (id)
- {
- case QIconEngine::AvailableSizesHook:
- {
- QIconEngine::AvailableSizesArgument &arg =
- *reinterpret_cast<QIconEngine::AvailableSizesArgument *>(data);
- const int N = m_entries.size();
- QList<QSize> sizes;
- sizes.reserve(N);
-
- // Gets all sizes from the DirectoryInfo entries
- for (int i = 0; i < N; ++i)
- {
- int size = m_entries.at(i)->dir.size;
- sizes.append(QSize(size, size));
- }
- arg.sizes.swap(sizes); // commit
- }
- break;
- case QIconEngine::IconNameHook:
+ const int N = m_entries.size();
+ QList<QSize> sizes;
+ sizes.reserve(N);
+
+ for (int i = 0; i < N; ++i)
{
- QString &name = *reinterpret_cast<QString *>(data);
- name = m_iconName;
- }
- break;
- default:
- QIconEngine::virtual_hook(id, data);
+ int size = m_entries.at(i)->dir.size;
+ sizes.append(QSize(size, size));
}
+ return sizes;
+}
+
+QString QIconLoaderEngineFixed::iconName()
+{
+ return m_iconName;
}
} // QtXdg
diff --git a/libraries/iconfix/internal/qiconloader_p.h b/libraries/iconfix/internal/qiconloader_p.h
index e45a08d642..3fb6d75ea2 100644
--- a/libraries/iconfix/internal/qiconloader_p.h
+++ b/libraries/iconfix/internal/qiconloader_p.h
@@ -123,7 +123,8 @@ private:
QString key() const;
bool hasIcon() const;
void ensureLoaded();
- void virtual_hook(int id, void *data);
+ QList<QSize> availableSizes(QIcon::Mode mode = QIcon::Normal, QIcon::State state = QIcon::Off) override;
+ QString iconName() override;
QIconLoaderEngineEntry *entryForSize(const QSize &size);
QIconLoaderEngineFixed(const QIconLoaderEngineFixed &other);
QThemeIconEntries m_entries;
diff --git a/libraries/systeminfo/src/distroutils.cpp b/libraries/systeminfo/src/distroutils.cpp
index fb9ae25d16..37ff9783ce 100644
--- a/libraries/systeminfo/src/distroutils.cpp
+++ b/libraries/systeminfo/src/distroutils.cpp
@@ -36,6 +36,7 @@ SOFTWARE.
#include <QProcess>
#include <QDebug>
#include <QDir>
+#include <QRegularExpression>
#include <functional>
@@ -170,7 +171,7 @@ void Sys::lsb_postprocess(Sys::LsbInfo & lsb, Sys::DistributionInfo & out)
else
{
// ubuntu, debian, gentoo, scientific, slackware, ... ?
- auto parts = dist.split(QRegExp("\\s+"), QString::SkipEmptyParts);
+ auto parts = dist.split(QRegularExpression("\\s+"), Qt::SkipEmptyParts);
if(parts.size())
{
dist = parts[0];
@@ -209,7 +210,7 @@ QString Sys::_extract_distribution(const QString & x)
{
return "sles";
}
- QStringList list = release.split(QRegExp("\\s+"), QString::SkipEmptyParts);
+ QStringList list = release.split(QRegularExpression("\\s+"), Qt::SkipEmptyParts);
if(list.size())
{
return list[0];
@@ -219,12 +220,12 @@ QString Sys::_extract_distribution(const QString & x)
QString Sys::_extract_version(const QString & x)
{
- QRegExp versionish_string("\\d+(?:\\.\\d+)*$");
- QStringList list = x.split(QRegExp("\\s+"), QString::SkipEmptyParts);
+ QRegularExpression versionish_string("\\d+(?:\\.\\d+)*$");
+ QStringList list = x.split(QRegularExpression("\\s+"), Qt::SkipEmptyParts);
for(int i = list.size() - 1; i >= 0; --i)
{
QString chunk = list[i];
- if(versionish_string.exactMatch(chunk))
+ if(versionish_string.match(chunk).hasMatch())
{
return chunk;
}